Chapterبەش 7 · Lectureوانە 7.2
Reasoning with a Knowledge Base in Pythonبیرکردنەوە بە بنکەیەکی زانین لە Pythonـدا
Build a small Python toolkit for propositional logic: sentences as tuples, evaluation in a model, model checking with yes / no / unknown answers. Then use it on a campus knowledge base, a lost-and-found puzzle, a scheduling puzzle and knights-and-knaves puzzles.
ئامرازێکی بچووکی بۆ دروست بکە: ڕستە وەک ، هەڵسەنگاندن لە ، بە وەڵامی بەڵێ / نەخێر / نەزانراو. پاشان لەسەر زانکۆ، مەتەڵی شتی ونبوو، مەتەڵی خشتەی کات و مەتەڵەکانی سوارچاک و درۆزن بەکاری بهێنە.
What you will learnچی فێر دەبیت
- Represent logical sentences in Python and evaluate them in a model.
- Explain how model checking decides KB ⊨ α, and write it with a loop or with recursion.
- Build a knowledge base from facts with
And(...)and get yes / no / unknown answers. - Turn a logic puzzle into rules and clues, and solve it with the computer.
- Explain why model checking becomes slow as the number of symbols grows.
- لە نیشان بدەیت و لە هەڵیان بسەنگێنیت.
- ڕوونی بکەیتەوە چۆن بڕیار لەسەر KB ⊨ α دەدات و بە یان بە بینووسیت.
- لە ڕاستییەکانەوە بە
And(...)دروست بکەیت و وەڵامی بەڵێ / نەخێر / نەزانراو وەربگریت. - مەتەڵێکی لۆجیکی بکەیت بە یاسا و ئاماژە و بە کۆمپیوتەر چارەسەری بکەیت.
- ڕوونی بکەیتەوە بۆچی لەگەڵ زیادبوونی ژمارەی هێماکان خاو دەبێت.
From logic on paper to logic in Pythonلە لۆجیکی سەر کاغەزەوە بۆ لۆجیک لە Pythonـدا
In the previous lesson you checked entailment by hand with a truth table. That works for 3 symbols, but not for 16. In this lesson we write a small Python toolkit, minilogic.py, that can hold any knowledge base and answer questions about it by model checking. Then we use it on three puzzles.
لە وانەی پێشوودا، بە دەست و بە پشکنی. ئەمە بۆ 3 هێما کار دەکات، بەڵام بۆ 16 نا. لەم وانەیەدا ئامرازێکی بچووکی دەنووسین، minilogic.py، کە دەتوانێت هەر هەڵبگرێت و بە وەڵامی پرسیارەکانی دەربارەی بداتەوە. پاشان لەسەر سێ مەتەڵ بەکاری دەهێنین.
- represent symbols and sentences built with ;
- say whether a sentence is true in a model (one possible world);
- print a sentence with logic signs, and list its symbols;
- decide KB ⊨ α by trying every model.
- هێما و ئەو ڕستانە نیشان بدات کە بە دروست کراون؛
- بڵێت ئایا ڕستەیەک لە (یەک جیهانی گونجاو) ڕاستە؛
- ڕستەیەک بە هێماکانی لۆجیک چاپ بکات و هێماکانی ڕیز بکات؛
- بە تاقیکردنەوەی هەموو بڕیار لەسەر KB ⊨ α بدات.
Part 1: building sentencesبەشی ١: دروستکردنی ڕستە
A symbol is just a name in a string, such as "rain". A bigger sentence is a tuple whose first item names the connective: ("not", A), ("and", A, B, …), ("or", A, B, …), ("implies", A, B) and ("iff", A, B). Small functions build these tuples for us, so we can write Implies("rain", "bus") instead of a raw tuple.
هێما تەنیا ناوێکە لە ، وەک "rain". ڕستەیەکی گەورەتر کە یەکەم بڕگەی ناوی بەستەرەکەیە: ("not", A)، ("and", A, B, …)، ("or", A, B, …)، ("implies", A, B) و ("iff", A, B). چەند بچووک ئەم بۆمان دروست دەکەن، بۆیە دەتوانین بنووسین Implies("rain", "bus") لە جیاتی ڕووت.
# minilogic.py - a tiny propositional-logic toolkit (CêIT, original code)
#
# A sentence is either
# - a symbol: a name in a string, such as "rain", or
# - a tuple that starts with a connective:
# ("not", A) ("and", A, B, ...) ("or", A, B, ...)
# ("implies", A, B) ("iff", A, B)
from itertools import product
class MissingValueError(Exception):
"""A symbol has no True/False value in the model."""
def Not(a):
return ("not", a)
def And(*parts):
return ("and",) + parts
def Or(*parts):
return ("or",) + parts
def Implies(a, b):
return ("implies", a, b)
def Iff(a, b):
return ("iff", a, b)Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3-7
The rule of the toolkit: a sentence is a string or a tuple.
یاسای ئامرازەکە: ڕستە یان یان .
- Lineدێڕی 11-12
Our own error type, raised when a symbol has no value in the model.
جۆرێکی خۆمان، کاتێک هەڵدەدرێت کە هێمایەک لە نرخی نەبێت.
- Lineدێڕی 19-24
*partscollects any number of arguments, soAnd(a, b, c, d)works.*partsهەر ژمارەیەک کۆ دەکاتەوە، بۆیەAnd(a, b, c, d)کار دەکات.
| Ideaبیرۆکە | The course's logic.py (CS50)logic.pyی کۆرسەکە (CS50) | Our minilogic.pyminilogic.pyی ئێمە |
|---|---|---|
| a symbolهێمایەک | Symbol("rain") | "rain" |
| notنا | Not(a) | Not(a) |
| and / or of many partsAND / ORـی چەند بەشێک | And(*conjuncts) / Or(*disjuncts) | And(*parts) / Or(*parts) |
| if … thenئەگەر … ئەوا | Implication(a, b) | Implies(a, b) |
| if and only ifئەگەر و تەنیا ئەگەر | Biconditional(a, b) | Iff(a, b) |
| a sentence in generalڕستە بە گشتی | a class Sentence with subclasses بە ناوی Sentence لەگەڵ کلاسە لاوەکییەکانی | any string or tupleهەر یان |
| add one more factزیادکردنی ڕاستییەکی دیکە | knowledge.add(s) | collect facts in a list, then And(*facts)ڕاستییەکان لە کۆ بکەرەوە، پاشان And(*facts) |
Part 2: true or false in a modelبەشی ٢: ڕاست یان هەڵە لە مۆدێلێکدا
A model is a dictionary that gives every symbol True or False, for example {"rain": True, "bus": False}. The function is_true works out the value of a sentence in a model with recursion: for a compound sentence it first works out its parts, then applies the connective.
کە True یان False دەدات بە هەموو هێمایەک، بۆ نموونە {"rain": True, "bus": False}. is_true نرخی ڕستەیەک لە بە دەدۆزێتەوە: بۆ ڕستەیەکی ئاوێتە یەکەمجار نرخی بەشەکانی دەدۆزێتەوە، پاشان بەستەرەکە جێبەجێ دەکات.
def is_true(s, model):
"""Is sentence s true in this model (a dict: symbol -> True/False)?"""
if isinstance(s, str):
if s not in model:
raise MissingValueError(f"the model has no value for {s!r}")
return model[s]
op, *parts = s
if op == "not":
return not is_true(parts[0], model)
if op == "and":
return all(is_true(p, model) for p in parts)
if op == "or":
return any(is_true(p, model) for p in parts)
if op == "implies":
return (not is_true(parts[0], model)) or is_true(parts[1], model)
if op == "iff":
return is_true(parts[0], model) == is_true(parts[1], model)
raise ValueError(f"unknown connective {op!r}")
def symbols(s):
"""The set of symbol names used in sentence s."""
if isinstance(s, str):
return {s}
names = set()
for p in s[1:]:
names |= symbols(p)
return names
SIGN = {"and": " ∧ ", "or": " ∨ ", "implies": " → ", "iff": " ↔ "}
def show(s):
"""Write sentence s with logic signs and brackets."""
if isinstance(s, str):
return s
if s[0] == "not":
inner = show(s[1])
return "¬" + (inner if isinstance(s[1], str) else "(" + inner + ")")
parts = []
for p in s[1:]:
text = show(p)
parts.append(text if isinstance(p, str) or p[0] == "not" else "(" + text + ")")
return SIGN[s[0]].join(parts)Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3-6
A symbol: look it up in the model. If it is missing, raise our error with a clear message.
هێمایەک: لە بەدوایدا بگەڕێ. ئەگەر نەبوو، هەڵەکەی خۆمان بە پەیامێکی ڕوون هەڵبدە.
- Lineدێڕی 7
Split the tuple: the connective and its parts.
جیا بکەرەوە: بەستەرەکە و بەشەکانی.
- Lineدێڕی 10-13
all()andany()give AND and OR of any number of parts.all()وany()AND و ORـی هەر ژمارەیەک بەش دەدەن.- Lineدێڕی 14-15
A → B is
(not A) or B: false only when A is true and B is false.A → B بریتییە لە
(not A) or B: تەنیا کاتێک هەڵەیە کە A ڕاست و B هەڵە بێت.- Lineدێڕی 21-28
Collect the symbols of all parts into one set.
هێماکانی هەموو بەشەکان لە یەک کۆ دەکاتەوە.
- Lineدێڕی 34-45
Write the sentence with , and put brackets around every compound part so the meaning stays clear.
ڕستەکە بە دەنووسێت و هەموو بەشێکی ئاوێتە دەخاتە ناو کەوانەوە بۆ ئەوەی واتاکە ڕوون بمێنێتەوە.
Part 2: true or false in a modelبەشی ٢: ڕاست یان هەڵە لە مۆدێلێکدا
Trying it outتاقیکردنەوەی ئامرازەکە
Save the three parts as minilogic.py (Part 3 is on the next screen) and run this file next to it:
سێ بەشەکە وەک minilogic.py خەزن بکە (بەشی ٣ لە شاشەی داهاتوودایە) و ئەم لە تەنیشتیەوە جێبەجێ بکە:
from minilogic import Not, And, Or, Implies, is_true, symbols, show
from minilogic import MissingValueError
rain = "rain"
bus = "bus"
sentence = Implies(rain, bus) # rain → bus
print(sentence) # how Python stores it
print(show(sentence)) # how we write it
print(sorted(symbols(sentence))) # the symbols it uses
model = {"rain": True, "bus": False} # one possible world
print(is_true(sentence, model))
print(is_true(Or(rain, Not(bus)), model))
print(show(And(Not(rain), Or(rain, bus))))
try:
is_true(sentence, {"rain": True}) # bus has no value
except MissingValueError as error:
print("Error:", error)('implies', 'rain', 'bus')
rain → bus
['bus', 'rain']
False
True
¬rain ∧ (rain ∨ bus)
Error: the model has no value for 'bus'Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 8
Python shows the tuple behind the sentence.
ئەو پیشان دەدات کە لە پشت ڕستەکەوەیە.
- Lineدێڕی 13
rain is T and bus is F: the only row where is false.
rain ڕاستە (T) و bus هەڵەیە (F): تاکە ڕیز کە تێیدا هەڵەیە.
- Lineدێڕی 17-20
A model without bus: our error explains what is missing.
بێ bus: هەڵەکەمان ڕوون دەکاتەوە چی کەمە.
Part 3: model checkingبەشی ٣: پشکنینی مۆدێل
Now the heart of the toolkit. all_models makes every combination of True/False for the symbols: 2ⁿ models for n symbols. entails goes through them and looks for a counter-example: a model where the KB is true but the query is false. If there is none, KB ⊨ query.
ئێستا دڵی ئامرازەکە. all_models هەموو تێکەڵەیەکی True/False بۆ هێماکان دروست دەکات: بۆ n هێما 2ⁿ . entails بەنێویاندا دەگەڕێت و بەدوای نموونەیەکی پێچەوانەدا دەگەڕێت: کە KB تێیدا ڕاست بێت بەڵام هەڵە بێت. ئەگەر نەبوو، KB ⊨ .
def all_models(names):
"""Every way to give True/False to the names: 2 ** len(names) models."""
names = sorted(names)
for values in product([True, False], repeat=len(names)):
yield dict(zip(names, values))
def entails(kb, query):
"""KB ⊨ query: is the query true in EVERY model where the KB is true?"""
for model in all_models(symbols(kb) | symbols(query)):
if is_true(kb, model) and not is_true(query, model):
return False # a counter-example: KB true, query false
return True
def answer(kb, query):
"""'yes' if KB ⊨ query, 'no' if KB ⊨ ¬query, otherwise 'unknown'."""
if entails(kb, query):
return "yes"
if entails(kb, Not(query)):
return "no"
return "unknown"
def exactly_one(names):
"""Exactly one of these symbols is true."""
rules = [Or(*names)] # at least one of them
for i, a in enumerate(names):
for b in names[i + 1:]:
rules.append(Not(And(a, b))) # but never two together
return And(*rules)Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1-5
product([True, False], repeat=n)gives all 2ⁿ value lists;zippairs them with the names.product([True, False], repeat=n)هەموو 2ⁿ لیستی نرخەکان دەدات؛zipجووتیان دەکات لەگەڵ ناوەکان.- Lineدێڕی 8-13
One counter-example is enough to answer "no", so the loop stops early.
یەک نموونەی پێچەوانە بەسە بۆ وەڵامی «نا»، بۆیە زوو ڕادەوەستێت.
- Lineدێڕی 16-22
Three answers: yes (KB ⊨ q), no (KB ⊨ ¬q) or unknown.
سێ وەڵام: بەڵێ (KB ⊨ q)، نەخێر (KB ⊨ ¬q) یان نەزانراو.
- Lineدێڕی 25-31
A helper for puzzles: at least one of the names is true, and no two are true together.
Not(And(a, b))says the same asImplies(a, Not(b)), the form the course's lab writes for "only one course per person".یاریدەدەرێک بۆ مەتەڵەکان: لانیکەم یەکێک لە ناوەکان ڕاستە و هیچ دوانێکیان پێکەوە ڕاست نین.
Not(And(a, b))هەمان واتایImplies(a, Not(b))هەیە، ئەو شێوەیەی تاقیگەکەی کۆرسەکە بۆ «تەنیا یەک کۆرس بۆ هەر کەسێک» دەینووسێت.
answer is the idea of the course's Clue example: a symbol is true if the KB entails it, and only maybe if the KB does not entail its negation either. Here "maybe" is called unknown.
answer بیرۆکەی نموونەی Clueـی کۆرسەکەیە: هێمایەک ڕاستە ئەگەر لە KB بکەوێتەوە و تەنیا لەوانەیە ئەگەر نەفییەکەشی لە KB نەکەوێتەوە. لێرەدا بە «لەوانەیە» دەوترێت unknown (نەزانراو).
Part 3: model checkingبەشی ٣: پشکنینی مۆدێل
Another way: recursionڕێگەیەکی دیکە: خۆبانگکردنەوە
The course's library does the same job recursively: it gives one symbol a value at a time, first True, then False, and calls itself for the rest. When every symbol has a value, it has one complete model and checks it (recursion itself is taught in Recursion in Fundamentals of Programming). Here is that idea in a few lines of our own:
کتێبخانەکەی کۆرسەکە هەمان کار بە دەکات: هەر جارەی نرخ دەدات بە یەک هێما، یەکەمجار True و پاشان False و بانگی خۆی دەکاتەوە بۆ ئەوانەی ماون. کاتێک هەموو هێماکان نرخیان هەبوو، یەک تەواوی هەیە و دەیپشکنێت ( خۆی لە خۆبانگکردنەوە لە بنەماکانی فێر دەکرێت). ئەمە ئەو بیرۆکەیەیە بە چەند دێڕێکی خۆمان:
# Model checking with recursion: give one symbol a value at a time.
from minilogic import And, Implies, is_true, symbols
def entails_rec(kb, query, names, model):
if not names: # every symbol has a value: one model
if is_true(kb, model):
return is_true(query, model)
return True # KB false here: this model does not matter
first, rest = names[0], names[1:]
return (entails_rec(kb, query, rest, {**model, first: True}) and
entails_rec(kb, query, rest, {**model, first: False}))
def entails(kb, query):
names = sorted(symbols(kb) | symbols(query))
return entails_rec(kb, query, names, {})
kb = And(Implies("snow", "road_closed"), Implies("road_closed", "home"))
print(entails(kb, Implies("snow", "home")))
print(entails(kb, "home"))True False
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6-9
Base case: every symbol has a value. If the KB is false here, this model does not matter.
حاڵەتی بنەڕەت: هەموو هێمایەک نرخی هەیە. ئەگەر KB لێرەدا هەڵە بێت، ئەم گرنگ نییە.
- Lineدێڕی 10-12
Give the first remaining symbol T and F; both halves must agree.
یەکەم هێمای ماوە T و F بدەرێ؛ هەردوو نیوەکە دەبێت ڕاست بن.
- Lineدێڕی 11
{**model, first: True}makes a new dictionary with one more value.{**model, first: True}نوێ دروست دەکات بە نرخێکی زیاترەوە.
Harvard's CS50 AI lecturer explains each idea with clear pictures and Python code; each placement plays only the chapter that matches its screen.
مامۆستای کۆرسی CS50 AIـی زانکۆی Harvard هەر بیرۆکەیەک بە وێنەی ئاشکرا و کۆدی ڕوون دەکاتەوە؛ لە هەر شوێنێک تەنها ئەو بەشەی لێدەدرێت کە لەگەڵ ئەو شاشەیە دەگونجێت.
Plays 2:26:03–2:31:41: the course library's recursive model_check (check_all gives one symbol True, then False) and a run on a small knowledge base. His library uses classes (Symbol, And, Implication); ours uses tuples.
لە 2:26:03 تا 2:31:41 لێدەدرێت: model_check لە کۆرسەکەدا، کە بە کار دەکات (check_all جارێک True بە دەدات و جارێکیش False)، لەگەڵ جێبەجێکردنی لەسەر بچووک. ئەو بەکاردەهێنێت (Symbol، And، Implication)؛ هی ئێمە بەکاردەهێنێت.
Example: Shilan's lab dayنموونە: ڕۆژی تاقیگەی شیلان
A small knowledge base about one day on campus. Facts: Today Shilan has the AI lab or the networks lab. If she has the AI lab, the computer lab is open. The computer lab is closed today. If it rains, Shilan takes the bus. Questions: does she have the networks lab? the AI lab? Does it rain?
بچووک دەربارەی ڕۆژێک لە زانکۆ. ڕاستییەکان: ئەمڕۆ شیلان تاقیگەی یان تاقیگەی تۆڕی هەیە. ئەگەر تاقیگەی هەبێت، تاقیگەی کۆمپیوتەر کراوەیە. تاقیگەی کۆمپیوتەر ئەمڕۆ داخراوە. ئەگەر باران ببارێت، شیلان سواری پاس دەبێت. پرسیارەکان: ئایا تاقیگەی تۆڕی هەیە؟ تاقیگەی ؟ ئایا باران دەبارێت؟
from minilogic import Not, And, Or, Implies, show, answer
ai_lab = "ai_lab" # Shilan has the AI lab today
network_lab = "network_lab" # Shilan has the networks lab today
lab_open = "lab_open" # the computer lab is open
rain = "rain" # it rains
bus = "bus" # Shilan takes the bus
kb = And(
Or(ai_lab, network_lab), # she has the AI lab or the networks lab
Implies(ai_lab, lab_open), # if she has the AI lab, the lab is open
Not(lab_open), # the computer lab is closed today
Implies(rain, bus), # if it rains, she takes the bus
)
print(show(kb))
for question in [network_lab, ai_lab, lab_open, rain, bus]:
print(question, "->", answer(kb, question))(ai_lab ∨ network_lab) ∧ (ai_lab → lab_open) ∧ ¬lab_open ∧ (rain → bus) network_lab -> yes ai_lab -> no lab_open -> no rain -> unknown bus -> unknown
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3-7
The facts' symbols, with a comment that says what each one means.
هێماکانی ڕاستییەکان، لەگەڵ کە دەڵێت هەریەکەیان چی دەگەیەنێت.
- Lineدێڕی 9-14
Put all facts inside one
And(...): the KB is one big sentence.هەموو ڕاستییەکان بخە ناو یەک
And(...)ـەوە: KB یەک ڕستەی گەورەیە.- Lineدێڕی 15
Print the KB with logic signs.
KB بە هێماکانی لۆجیک چاپ بکە.
- Lineدێڕی 16-17
Ask five questions.
پێنج پرسیار بکە.
The answers follow from the facts: the lab is closed, so she cannot have the AI lab (if she did, it would be open); so she has the networks lab. About the rain the KB knows nothing, and "if it rains she takes the bus" does not say whether it rains, so both rain and bus are unknown.
وەڵامەکان لە ڕاستییەکانەوە دێن: تاقیگەکە داخراوە، بۆیە ناکرێت تاقیگەی هەبێت (ئەگەر هەیبوایە، کراوە دەبوو)؛ کەواتە تاقیگەی تۆڕی هەیە. دەربارەی باران KB هیچ نازانێت و «ئەگەر باران ببارێت سواری پاس دەبێت» نالێت باران دەبارێت یان نا، بۆیە rain و bus هەردووکیان نەزانراون.
Example: Shilan's lab dayنموونە: ڕۆژی تاقیگەی شیلان
A common mistake: one variable, four assignmentsهەڵەیەکی باو: یەک گۆڕاو، چوار جار دانانی نرخ
The course's notes first show a "fake" version on purpose: the facts are written one after another into the same variable. Each line replaces the one before, so only the last fact is left:
تێبینییەکانی کۆرسەکە یەکەمجار بە ئەنقەست وەشانێکی «ساختە» پیشان دەدەن: ڕاستییەکان یەک لە دوای یەک لە هەمان دەنووسرێن. هەر دێڕێک جێگەی ئەوەی پێش خۆی دەگرێتەوە، بۆیە تەنیا دوایین ڕاستی دەمێنێتەوە:
from minilogic import Not, Or, Implies, show, answer
kb = Or("ai_lab", "network_lab")
kb = Implies("ai_lab", "lab_open")
kb = Not("lab_open")
kb = Implies("rain", "bus") # each line REPLACES the one before
print(show(kb))
print("network_lab ->", answer(kb, "network_lab"))rain → bus network_lab -> unknown
The KB forgot that the lab is closed, so it cannot answer any more. The right way is the And(...) of the previous screen.
KB لە بیری کرد کە تاقیگەکە داخراوە، بۆیە چیتر ناتوانێت وەڵام بداتەوە. ڕێگە دروستەکە And(...)ـەکەی شاشەی پێشووە.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3-6
Four assignments to
kb: after line 6,kbholds only rain → bus.چوار جار بۆ
kb: دوای دێڕی 6،kbتەنیاrain → busی تێدایە.
Example: a lost-and-found puzzleنموونە: مەتەڵی شتی ونبوو
After a long day the caretaker of the college finds something left behind. One student left one thing in one room. The students: Aram, Dilan and Hana. The rooms: the lab, the library and the canteen. The things: a charger, an umbrella and a scarf. The clues: Hana was at home all day. The library was closed. Aram only went to the canteen. Nothing was found in the canteen. "It was not an umbrella," says the caretaker.
دوای ڕۆژێکی درێژ، پاسەوانی کۆلێژەکە شتێک دەدۆزێتەوە کە بەجێ هێڵراوە. یەک خوێندکار یەک شتی لە یەک ژووردا بەجێ هێشتووە. خوێندکارەکان: ئارام، دیلان و هانا. ژوورەکان: تاقیگە، کتێبخانە و کافتریا. شتەکان: شەحن، چەتر و لەچک. ئاماژەکان: هانا هەموو ڕۆژەکە لە ماڵەوە بوو. کتێبخانە داخرابوو. ئارام تەنیا چووە کافتریا. لە کافتریادا هیچ شتێک نەدۆزرایەوە. پاسەوانەکە دەڵێت: «چەتر نەبوو.»
# Lost and found: who left something behind, where, and what was it?
from minilogic import Not, And, Implies, answer, exactly_one
people = ["aram", "dilan", "hana"]
rooms = ["lab", "library", "canteen"]
items = ["charger", "umbrella", "scarf"]
kb = And(
exactly_one(people), # one person left one thing
exactly_one(rooms), # in one room
exactly_one(items),
Not("hana"), # Hana was at home all day
Not("library"), # the library was closed
Implies("aram", "canteen"), # Aram only went to the canteen
Not("canteen"), # nothing was found in the canteen
Not("umbrella"), # the caretaker: "it was not an umbrella"
)
for name in people + rooms + items:
print(f"{name:9} {answer(kb, name)}")aram no dilan yes hana no lab yes library no canteen no charger unknown umbrella no scarf unknown
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4-6
Nine symbols in three groups.
نۆ هێما لە سێ گرووپدا.
- Lineدێڕی 9-11
Exactly one person, one room and one thing.
ڕێک یەک کەس، یەک ژوور و یەک شت.
- Lineدێڕی 12-16
Each clue is one more fact.
هەر ئاماژەیەک ڕاستییەکی زیاترە.
- Lineدێڕی 19-20
Ask about every symbol: yes, no or unknown.
دەربارەی هەموو هێمایەک بپرسە: بەڵێ، نەخێر یان نەزانراو.
Dilan left something in the lab. Can you follow the reasoning? Hana was at home, and Aram would have been in the canteen, where nothing was found, so it was Dilan. The only room left is the lab. But the thing is still unknown: a charger or a scarf.
دیلان شتێکی لە تاقیگەدا بەجێ هێشتووە. دەتوانیت بیرکردنەوەکە بەدوادا بچیت؟ هانا لە ماڵەوە بوو و ئارام دەبوو لە کافتریا بێت، کە هیچ شتێکی لێ نەدۆزرایەوە، بۆیە دیلان بوو. تاکە ژووری ماوە تاقیگەیە. بەڵام شتەکە هێشتا نەزانراوە: شەحن یان لەچک.
The cleaner of the lab adds: "No scarf was found in the lab." Add this clue to the KB. What does the program print now?
پاککەرەوەی تاقیگەکە دەڵێت: «هیچ لەچکێک لە تاقیگەدا نەدۆزرایەوە.» ئەم ئاماژەیە بخە سەر KB. بەرنامەکە ئێستا چی چاپ دەکات؟
Hintئاماژە
"No scarf in the lab" means: not (scarf and lab).
«لەچک لە تاقیگەدا نییە» واتە: نا (لەچک و تاقیگە).
Show answerوەڵامەکە پیشان بدە
Not(And("scarf", "lab")), # no scarf was found in the labaram no dilan yes hana no lab yes library no canteen no charger yes umbrella no scarf no
Now everything is known: Dilan left a charger in the lab.
ئێستا هەموو شتێک زانراوە: دیلان شەحنێکی لە تاقیگەدا بەجێ هێشتووە.
Example: who presents on which day?نموونە: کێ لە چ ڕۆژێکدا پێشکەشکردن دەکات؟
Four students, Aram, Shilan, Karwan and Dilan, present their projects on four days: Sunday to Wednesday. Each student presents on exactly one day, and there is exactly one student per day. Clues: Karwan presents on Wednesday. Aram presents on Tuesday or Wednesday. Shilan presents on Monday or Tuesday. Who presents when?
چوار خوێندکار، ئارام، شیلان، کاروان و دیلان، لە چوار ڕۆژدا پرۆژەکانیان پێشکەش دەکەن: یەکشەممە تا چوارشەممە. هەر خوێندکارێک ڕێک لە یەک ڕۆژدا پێشکەشی دەکات و هەر ڕۆژێک ڕێک یەک خوێندکاری هەیە. ئاماژەکان: کاروان چوارشەممە پێشکەشی دەکات. ئارام سێشەممە یان چوارشەممە پێشکەشی دەکات. شیلان دووشەممە یان سێشەممە پێشکەشی دەکات. کێ کەی پێشکەشی دەکات؟
# Four students present their projects on four days. Who presents when?
import time
from minilogic import And, Or, entails, exactly_one
people = ["aram", "shilan", "karwan", "dilan"]
days = ["sun", "mon", "tue", "wed"]
rules = []
for person in people: # each student presents on exactly one day
rules.append(exactly_one([f"{person}_{day}" for day in days]))
for day in days: # one student per day
rules.append(exactly_one([f"{person}_{day}" for person in people]))
rules.append("karwan_wed") # Karwan presents on Wednesday
rules.append(Or("aram_tue", "aram_wed")) # Aram: Tuesday or Wednesday
rules.append(Or("shilan_mon", "shilan_tue")) # Shilan: Monday or Tuesday
kb = And(*rules)
start = time.perf_counter()
for person in people:
for day in days:
if entails(kb, f"{person}_{day}"):
print(f"{person} presents on {day}")
print(f"16 questions, 2 ** 16 = {2 ** 16} models each,",
f"{time.perf_counter() - start:.1f} seconds")aram presents on tue shilan presents on mon karwan presents on wed dilan presents on sun 16 questions, 2 ** 16 = 65536 models each, 8.4 seconds
The time is measured on one computer (python3 3.9); yours will be different.
کاتەکە لەسەر یەک پێوراوە (python3 3.9)؛ کاتەکەی تۆ جیاواز دەبێت.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 5-6
4 × 4 = 16 symbols such as
aram_sun,shilan_tue.4 × 4 = 16 هێما وەک
aram_sunوshilan_tue.- Lineدێڕی 8-12
Collect the rules in a list: one day per student, one student per day.
یاساکان لە کۆ دەکەینەوە: یەک ڕۆژ بۆ هەر خوێندکارێک، یەک خوێندکار بۆ هەر ڕۆژێک.
- Lineدێڕی 14-16
The three clues.
سێ ئاماژەکە.
- Lineدێڕی 17
And(*rules)turns the list into one knowledge base.And(*rules)دەکات بە یەک .- Lineدێڕی 20-23
Print every symbol that the KB entails.
هەموو ئەو هێمایانە چاپ بکە کە لە KB دەکەونەوە.
The reasoning is a chain: Karwan has Wednesday, so Aram must take Tuesday, so Shilan must take Monday, and Dilan gets Sunday. The program needs no chain: it simply tries all 2¹⁶ = 65,536 models for each of the 16 questions. That is about a million checks, which is why it takes a while.
بیرکردنەوەکە زنجیرەیەکە: چوارشەممە هی کاروانە، بۆیە ئارام دەبێت سێشەممە وەربگرێت، بۆیە شیلان دەبێت دووشەممە وەربگرێت و یەکشەممە بۆ دیلان دەمێنێتەوە. بەرنامەکە پێویستی بە زنجیرە نییە: بە سادەیی هەموو 2¹⁶ = 65,536 بۆ هەریەکە لە 16 پرسیارەکە تاقی دەکاتەوە. ئەمە نزیکەی ملیۆنێک پشکنینە، بۆیە ماوەیەک دەخایەنێت.
Common mistakesهەڵە باوەکان
from minilogic import Not, And, show, answer
# Mistake 1: Python's own `and` instead of the toolkit's And(...)
kb = "rain" and "bus" # Python keeps only "bus"!
print(show(kb))
# Mistake 2: a knowledge base that contradicts itself
kb = And("rain", Not("rain"))
print(answer(kb, "snow"), answer(kb, Not("snow")))bus yes yes
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4
Python's
andis not a logic builder: with two non-empty strings it simply returns the second one.andی دروستکەری لۆجیک نییە: لەگەڵ دوو نابەتاڵ تەنیا دووەمیان دەگەڕێنێتەوە.- Lineدێڕی 8-9
A KB that contradicts itself has no model, so it "entails" everything, even snow and not snow.
KBـێک کە دژی خۆی بێت هیچ نییە، بۆیە هەموو شتێکی «لێ دەکەوێتەوە»، تەنانەت snow و ¬snowـیش.
| Mistakeهەڵە | What happensچی ڕوو دەدات | Fixچاککردن |
|---|---|---|
Assigning facts one by one to kbدانانی ڕاستییەکان یەک بە یەک لە kbدا | Only the last fact is kept.تەنیا دوایین ڕاستی دەمێنێتەوە. | kb = And(fact1, fact2, …)kb = And(fact1, fact2, …) |
Python's and/or/not between symbolsand/or/notی لە نێوان هێماکاندا | Python works out a value at once; no sentence is built. دەستبەجێ نرخێک دەدۆزێتەوە؛ هیچ ڕستەیەک دروست نابێت. | Use And, Or, Not.And، Or و Not بەکاربهێنە. |
A typo in a symbol name (lab_opne)هەڵەی نووسین لە ناوی هێمادا (lab_opne) | It becomes a new, unrelated symbol; answers turn into "unknown".دەبێت بە هێمایەکی نوێی بێپەیوەندی؛ وەڵامەکان دەبن بە «نەزانراو». | Keep symbols in variables, as campus.py does.هێماکان لە ڕابگرە، وەک campus.py. |
| Contradictory factsڕاستیی دژبەیەک | No model: every question gets "yes".هیچ نییە: هەموو پرسیارێک «بەڵێ» وەردەگرێت. | Check that the KB has at least one model.دڵنیابە کە KB لانیکەم یەک هەیە. |
| Reading "unknown" as "no"خوێندنەوەی «نەزانراو» وەک «نەخێر» | You claim something the KB never said.شتێک دەڵێیت کە KB هەرگیز نەیگوتووە. | "no" only when KB ⊨ ¬α.«نەخێر» تەنیا کاتێک KB ⊨ ¬α. |
| Too many symbolsهێمای زۆر | 2ⁿ models: the program becomes very slow.2ⁿ : بەرنامەکە زۆر خاو دەبێت. | Keep puzzles small, or use smarter algorithms.مەتەڵەکان بچووک ڕابگرە، یان زیرەکتر بەکاربهێنە. |
Exercisesڕاهێنانەکان
Add two facts to campus.py: "It rains today" and "If Shilan takes the bus, she arrives before 8" (symbol early). What are the answers for bus and early now?
دوو ڕاستی بخە سەر campus.py: «ئەمڕۆ باران دەبارێت» و «ئەگەر شیلان سواری پاس ببێت، پێش کاتژمێر 8 دەگات» (هێمای early). وەڵامەکانی bus و early ئێستا چین؟
Show answerوەڵامەکە پیشان بدە
Add rain and Implies(bus, "early") inside And(...). Then bus is yes (modus ponens with rain → bus and rain) and early is yes (again modus ponens, with bus → early and bus).
rain و Implies(bus, "early") بخە ناو And(...)ـەوە. ئەوکات bus بەڵێیە (modus ponens بە rain → bus و rain) و earlyیش بەڵێیە (دیسان modus ponens، بە bus → early و bus).
In presentations.py, remove the clue "Karwan presents on Wednesday". Is the answer still unique? Explain without running the program first, then run it.
لە presentations.pyدا ئاماژەی «کاروان چوارشەممە پێشکەشی دەکات» لابدە. ئایا وەڵامەکە هێشتا تاکە؟ پێش جێبەجێکردنی بەرنامەکە ڕوونی بکەرەوە، پاشان جێبەجێی بکە.
Show answerوەڵامەکە پیشان بدە
No. Without that clue several plans fit the clues: for example Aram on Tuesday and Shilan on Monday, with Karwan and Dilan on Sunday and Wednesday in either order; or Aram on Wednesday, with Shilan on Monday or Tuesday. No symbol is true in every plan, so the program prints no names at all, only the line with the time.
نەخێر. بەبێ ئەو ئاماژەیە چەند پلانێک لەگەڵ ئاماژەکاندا دەگونجێن: بۆ نموونە ئارام سێشەممە و شیلان دووشەممە، لەگەڵ کاروان و دیلان لە یەکشەممە و چوارشەممەدا بە هەر ڕیزبەندییەک؛ یان ئارام چوارشەممە و شیلان دووشەممە یان سێشەممە. هیچ هێمایەک لە هەموو پلانەکاندا ڕاست نییە، بۆیە بەرنامەکە هیچ ناوێک چاپ ناکات، تەنیا دێڕی کاتەکە.
How many models does entails need per question for 3 students on 3 days, and for 5 students on 5 days?
entails بۆ هەر پرسیارێک چەند پێویستە بۆ 3 خوێندکار لە 3 ڕۆژدا و بۆ 5 خوێندکار لە 5 ڕۆژدا؟
Show answerوەڵامەکە پیشان بدە
3 × 3 = 9 symbols: 2⁹ = 512 models. 5 × 5 = 25 symbols: 2²⁵ = 33,554,432 models, 512 times more than the 4 × 4 puzzle.
3 × 3 = 9 هێما: 2⁹ = 512 . 5 × 5 = 25 هێما: 2²⁵ = 33,554,432 ، 512 جار زیاتر لە مەتەڵی 4 × 4.
Summary and reviewپوختە و پێداچوونەوە
- In
minilogic.pya symbol is a string and a sentence is a tuple built byNot,And,Or,ImpliesandIff. - A model is a dictionary of
True/Falsevalues;is_trueevaluates a sentence in it by recursion. entails(kb, q)tries all 2ⁿ models and stops at the first counter-example;answersays yes, no or unknown.- Put every fact into one
And(...);exactly_onehelps with puzzles. - Model checking is simple and correct but slow: every symbol doubles the work.
- لە
minilogic.pyدا هێما و ڕستە کەNot،And،Or،ImpliesوIffدروستی دەکەن. - نرخەکانی
True/Falseـە؛is_trueبە ڕستەیەک تێیدا هەڵدەسەنگێنێت. entails(kb, q)هەموو 2ⁿ تاقی دەکاتەوە و لە یەکەم نموونەی پێچەوانەدا ڕادەوەستێت؛answerدەڵێت بەڵێ، نەخێر یان نەزانراو.- هەموو ڕاستییەک بخە ناو یەک
And(...)ـەوە؛exactly_oneیارمەتیی مەتەڵەکان دەدات. - سادە و دروستە بەڵام خاوە: هەر هێمایەک کارەکە دوو هێندە دەکات.
Why does entails return False as soon as it finds one bad model?بۆچی entails هەر کە یەک مۆدێلێکی خراپی دۆزییەوە False دەگەڕێنێتەوە؟
One model where the KB is true and the query is false is a counter-example: it proves that the query does not follow.
یەک کە KB تێیدا ڕاست و هەڵە بێت نموونەیەکی پێچەوانەیە: دەیسەلمێنێت کە ناکەوێتەوە.
What is the difference between the answers "no" and "unknown"?جیاوازیی نێوان وەڵامی «نەخێر» و «نەزانراو» چییە؟
"no" means the KB entails ¬α. "unknown" means the KB entails neither α nor ¬α.
«نەخێر» واتە ¬α لە KB دەکەوێتەوە. «نەزانراو» واتە نە α و نە ¬α لە KB ناکەونەوە.
How is "Hana says S" written in a knights-and-knaves puzzle?«هانا دەڵێت S» لە مەتەڵی سوارچاک و درۆزندا چۆن دەنووسرێت؟
Iff("hana", S): S is true exactly when Hana is a knight.
Iff("hana", S): S ڕێک کاتێک ڕاستە کە هانا سوارچاک بێت.
Why did the presentation puzzle take several seconds?بۆچی مەتەڵی پێشکەشکردنەکە چەند چرکەیەکی خایاند؟
16 symbols give 65,536 models, and the program checks them for each of 16 questions.
16 هێما 65,536 دەدەن و بەرنامەکە بۆ هەریەکە لە 16 پرسیارەکە دەیانپشکنێت.
Videoڤیدیۆ
Watch a videoسەیری ڤیدیۆیەک بکە
A video that viewers liked a lot and praised in their comments, chosen for this lesson.ڤیدیۆیەک کە بینەران زۆریان پێ خۆش بووە و لە کۆمێنتەکانیاندا ستایشیان کردووە، بۆ ئەم وانەیە هەڵبژێردراوە.
Harvard's CS50 AI lecturer explains each idea with clear pictures and Python code; each placement plays only the chapter that matches its screen.
مامۆستای کۆرسی CS50 AIـی زانکۆی Harvard هەر بیرۆکەیەک بە وێنەی ئاشکرا و کۆدی ڕوون دەکاتەوە؛ لە هەر شوێنێک تەنها ئەو بەشەی لێدەدرێت کە لەگەڵ ئەو شاشەیە دەگونجێت.
Plays 2:32:01–2:56:28: knowledge engineering. Brian Yu writes puzzles as knowledge bases in Python (Clue, people in houses, Mastermind), solves them by model checking, and shows why 2ⁿ models get slow.
لە 2:32:01 تا 2:56:28 لێدەدرێت: ئەندازیاریی زانین. Brian Yu چەند مەتەڵێک وەک بە دەنووسێت (Clue، خەڵک لە خانووەکاندا، Mastermind)، بە چارەسەریان دەکات و پیشان دەدات بۆچی پشکنینی 2ⁿ هێواش دەبێت.
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
Machine Learning Basics (Supplementary)بنەماکانی فێربوونی ئامێر (زیادە)
Related lecturesوانە پەیوەندیدارەکان
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
- CS50's Introduction to AI with Python — Notes 1: Knowledge (the course's lab files were based on this course; not reproduced here)
- CS50 AI — Project 1: Knights (knights-and-knaves puzzles)
- Russell & Norvig, Artificial Intelligence: A Modern Approach, 4th ed., §7.4.4 A simple inference procedure and §7.6 Effective propositional model checking
- Python documentation — itertools.product
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.