Knowledge Reasoning And Planning
Propositional Logic
Chapter 1's semantic networks and frames are intuitive but informal — nothing mathematically guarantees that following the "is-a" chain to conclude "Tweety can
Jr Codex AI Notes
Level: Intermediate Prerequisites: Chapter 1 Time to complete: ~25 minutes
Table of Contents
- Why Formal Logic?
- Syntax — Building Valid Sentences
- Semantics — Truth Tables
- Logical Equivalence
- Entailment — the Core Reasoning Question
- Checking Entailment with Truth Tables in Code
- The Limits of Propositional Logic
- Summary & Next Steps
1. Why Formal Logic?
Chapter 1's semantic networks and frames are intuitive but informal — nothing mathematically guarantees that following the "is-a" chain to conclude "Tweety can fly" is actually a valid inference. Propositional logic gives knowledge representation a precise, mathematical foundation — rules for what follows from what, with no ambiguity.
Informal (Ch.1) Formal (this chapter)
───────────────────────────── ─────────────────────────────
"Tweety is a canary, canaries Rain ∧ (Rain → WetGround) ⊨ WetGround
are birds, birds fly, so (formally PROVABLE, not just
Tweety probably flies" intuitively plausible)
───────────────────────────── ─────────────────────────────
2. Syntax — Building Valid Sentences
Propositional logic starts with propositions (statements that are either true or false) and combines them with logical connectives.
Propositional Symbols
─────────────────────────────────────────
P = "It is raining"
Q = "The ground is wet"
R = "I bring an umbrella"
Each is a SIMPLE proposition — atomic, either True or False,
no internal structure logic can inspect (that's Chapter 3's job).
─────────────────────────────────────────
The Five Logical Connectives
─────────────────────────────────────────
¬P NOT P "It is NOT raining"
P ∧ Q P AND Q "It is raining AND the ground is wet"
P ∨ Q P OR Q "It is raining OR I bring an umbrella"
P → Q P IMPLIES Q "IF it is raining THEN the ground is wet"
P ↔ Q P IFF Q "It is raining IF AND ONLY IF the ground is wet"
─────────────────────────────────────────
# Representing propositional sentences as Python expressions over booleans
def evaluate_sentence(P, Q):
not_p = not P
p_and_q = P and Q
p_or_q = P or Q
p_implies_q = (not P) or Q # P → Q is FALSE only when P is True and Q is False
p_iff_q = P == Q
return {
"¬P": not_p, "P∧Q": p_and_q, "P∨Q": p_or_q,
"P→Q": p_implies_q, "P↔Q": p_iff_q,
}
print(evaluate_sentence(P=True, Q=False))
# {'¬P': False, 'P∧Q': False, 'P∨Q': True, 'P→Q': False, 'P↔Q': False}The implication P → Q trips up almost every beginner — it's only false when P is true and Q is false; if P is false, P → Q is considered true regardless of Q ("if it's not raining, the umbrella claim is vacuously fine either way").
3. Semantics — Truth Tables
The semantics of a sentence define its truth value under every possible combination of its propositions' truth values — a truth table enumerates all of them.
from itertools import product
def truth_table(variables, sentence_fn):
"""Print a full truth table for a sentence over the given variable names."""
header = variables + ["Result"]
print(" | ".join(header))
print("-" * (len(header) * 8))
for values in product([True, False], repeat=len(variables)):
assignment = dict(zip(variables, values))
result = sentence_fn(assignment)
row = [str(assignment[v]) for v in variables] + [str(result)]
print(" | ".join(row))
# P → Q
truth_table(["P", "Q"], lambda a: (not a["P"]) or a["Q"])
# P | Q | Result
# ------------------------
# True | True | True
# True | False | False
# False | True | True
# False | False | TrueReading the Implication's Truth Table
─────────────────────────────────────────
P=True, Q=True → True (raining AND ground wet — consistent)
P=True, Q=False → False (raining but ground NOT wet — CONTRADICTS the claim)
P=False, Q=True → True (not raining, but ground wet anyway — claim wasn't about THIS)
P=False, Q=False → True (not raining, ground not wet — consistent, vacuously)
─────────────────────────────────────────
4. Logical Equivalence
Two sentences are logically equivalent if they have identical truth tables — they mean exactly the same thing, just expressed differently.
def sentences_equivalent(variables, sentence1, sentence2):
"""Check equivalence by comparing truth tables across every assignment."""
for values in product([True, False], repeat=len(variables)):
assignment = dict(zip(variables, values))
if sentence1(assignment) != sentence2(assignment):
return False
return True
# De Morgan's Law: ¬(P ∧ Q) is equivalent to (¬P ∨ ¬Q)
equiv = sentences_equivalent(
["P", "Q"],
lambda a: not (a["P"] and a["Q"]),
lambda a: (not a["P"]) or (not a["Q"]),
)
print(equiv) # True — De Morgan's Law holdsCommon Equivalences Worth Recognizing
─────────────────────────────────────────
De Morgan's Laws: ¬(P ∧ Q) ≡ (¬P ∨ ¬Q)
¬(P ∨ Q) ≡ (¬P ∧ ¬Q)
Implication elimination: (P → Q) ≡ (¬P ∨ Q)
(used directly in Section 2's code!)
Contrapositive: (P → Q) ≡ (¬Q → ¬P)
─────────────────────────────────────────
These equivalences aren't just theoretical curiosities — automated reasoning systems (Chapter 4) rely on rewriting sentences into equivalent, more convenient forms (like eliminating implications) before applying inference rules.
5. Entailment — the Core Reasoning Question
Entailment, written KB ⊨ α ("knowledge base KB entails sentence α"), is the central question of logical reasoning: given what we know (KB) to be true, must α also be true?
Formal Definition
─────────────────────────────────────────
KB ⊨ α means: in EVERY possible world (every truth
assignment) where KB is true, α is
ALSO true.
If there's even ONE assignment where KB holds but α doesn't,
entailment FAILS — KB does NOT guarantee α.
─────────────────────────────────────────
Worked Example
─────────────────────────────────────────
KB: Rain → WetGround (if it rains, the ground gets wet)
Rain (it IS raining)
Does KB entail WetGround?
Check EVERY assignment where BOTH KB sentences are true:
Rain=True, WetGround=True: Rain→WetGround = True ✓, Rain = True ✓
→ WetGround = True ✓ (holds)
Rain=True, WetGround=False: Rain→WetGround = False ✗ (violates KB — excluded)
In every world where KB is true, WetGround is ALSO true.
→ KB ⊨ WetGround (entailment holds!)
─────────────────────────────────────────
6. Checking Entailment with Truth Tables in Code
The most basic (if inefficient for large problems) way to check entailment — enumerate every possible world and verify the definition from Section 5 directly.
from itertools import product
def check_entailment(variables, kb_sentences, query_sentence):
"""
KB entails query if, in EVERY assignment where all KB sentences
are true, the query is ALSO true.
"""
for values in product([True, False], repeat=len(variables)):
assignment = dict(zip(variables, values))
kb_holds = all(sentence(assignment) for sentence in kb_sentences)
if kb_holds and not query_sentence(assignment):
return False # found a WORLD where KB is true but query is FALSE — entailment fails
return True # no counterexample found — entailment holds
kb = [
lambda a: (not a["Rain"]) or a["WetGround"], # Rain → WetGround
lambda a: a["Rain"], # Rain (known fact)
]
query = lambda a: a["WetGround"]
result = check_entailment(["Rain", "WetGround"], kb, query)
print(result) # True — KB entails WetGroundThis "check every possible world" approach is called model checking — it's guaranteed correct, but its cost doubles with every additional variable (2^n worlds for n variables), motivating Chapter 4's more efficient, targeted inference algorithms.
7. The Limits of Propositional Logic
Propositional logic is precise, but structurally limited — it treats each proposition as an indivisible atom, unable to express relationships between objects or generalize across many individuals.
# Propositional logic CAN express:
# "Socrates is a man" as a single atomic proposition: SocratesIsMan
# But it CANNOT naturally express the GENERAL rule:
# "ALL men are mortal"
# without a SEPARATE proposition for every individual man:
# SocratesIsMan → SocratesIsMortal
# PlatoIsMan → PlatoIsMortal
# AristotleIsMan → AristotleIsMortal
# ... (one explicit sentence per person, no way to generalize!)Why This Is a Real Problem
─────────────────────────────────────────
A knowledge base about even a MODEST domain (all birds, all
countries, all customers) would need a SEPARATE, hand-written
sentence for every single individual — utterly impractical,
and directly violating Chapter 1's "acquisition efficiency"
property.
This exact limitation is what First-Order Logic (Chapter 3)
is built to solve — introducing VARIABLES and QUANTIFIERS
so a single sentence can express a rule about EVERY object
in a domain at once.
─────────────────────────────────────────
8. Summary & Next Steps
Key Takeaways
- Propositional logic combines atomic true/false propositions using connectives (¬, ∧, ∨, →, ↔), each with a precisely defined truth table.
- Two sentences are logically equivalent if their truth tables match exactly — De Morgan's Laws and implication elimination are commonly used equivalences.
- Entailment (
KB ⊨ α) asks whether α must be true in every possible world where the knowledge base is true — the central formal reasoning question. - Model checking (enumerating every possible world) correctly determines entailment but scales as
2^nwith the number of variables — impractical for large knowledge bases. - Propositional logic cannot naturally express general rules across many individuals without a separate sentence per individual — motivating First-Order Logic in Chapter 3.
Concept Check
- Why is
P → Qconsidered true whenever P is false, regardless of Q's value? - What does it mean, formally, for a knowledge base to "entail" a sentence?
- Why does representing "all men are mortal" become impractical in pure propositional logic?
Next Chapter
→ Chapter 3: First-Order Logic
Jr Codex — 1-on-1 Personalized Coaching | Back to Module Index