Skip to content

Forward chaining implementation #11400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions inference_engine_algorithms/forward_chaining.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
'''

Check failure on line 1 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (INP001)

inference_engine_algorithms/forward_chaining.py:1:1: INP001 File `inference_engine_algorithms/forward_chaining.py` is part of an implicit namespace package. Add an `__init__.py`.
The forward-chaining algorithm PL-FC-ENTAILS? (KB, q) determines if a single proposition
symbol q—the query—is entailed by a knowledge base of definite clauses. It begins from
known facts (positive literals) in the knowledge base.

Check failure on line 4 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W291)

inference_engine_algorithms/forward_chaining.py:4:55: W291 Trailing whitespace
known facts (positive literals) in the knowledge base.

Reference: https://dl.ebooksworld.ir/books/Artificial.Intelligence.A.Modern.Approach.4th.Edition.Peter.Norvig.%20Stuart.Russell.Pearson.9780134610993.EBooksWorld.ir.pdf

'''

import re

def find_symbols_in_kb(knowledge_base: list[str]) -> dict:

Check failure on line 13 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

inference_engine_algorithms/forward_chaining.py:11:1: I001 Import block is un-sorted or un-formatted
'''
Find all unique symbols in the Knowledge_base
:param knowledge_base: a list of string of definite clauses
:returns: a dictionary with symbols as the keys their values are False
'''

inferred = {}

for i in range(len(knowledge_base)):
symbols = re.findall(r'[a-zA-Z]', knowledge_base[i])
for symbol in symbols:
if symbol not in inferred:
inferred[symbol] = False

return inferred


def number_of_symbols_in_premise(knowledge_base: list[str]) -> dict:

'''
Count the number of prposiotion symbols in each premise of KB clause
:param knowledge_base: a list of string of definite clauses
:returns: a dictionary with key as the premise of KB clause and value of count of symbols in the premise

Check failure on line 36 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

inference_engine_algorithms/forward_chaining.py:36:89: E501 Line too long (108 > 88)
'''

count = {}
for clause in knowledge_base:
if(len(clause) != 1):
index = clause.find("=>")
premise = clause[:index]
letters = ''.join(e for e in premise if e.isalpha())
count[premise] = len(letters)

return count


def get_known_facts(knowledge_base: list[str]) -> list[str]:
'''
Get the known facts in KB
:param knowledge_base: a list of string of definite clauses
:returns: list of facts

'''

facts = []
for clause in knowledge_base:
if len(clause) == 1:
facts.append(clause)

return facts




def forward_chaining(knowledge_base: list[str], query:str) -> bool:
''' Forward chaining on Knowledge Base(KB) of definite clauses
:param knowledge_base: a list of string of definite clauses
:param query: a single proposition symbol that you are checking if it is entailed by the KB

Check failure on line 71 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

inference_engine_algorithms/forward_chaining.py:71:89: E501 Line too long (96 > 88)
:returns: If the query entailed by the KB or not?
>>> forward_chaining([ "P => Q", "L & M => P", "B&L=> M", "A&P=>L", "A&B=>L", "A", "B" ], "Q")

Check failure on line 73 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

inference_engine_algorithms/forward_chaining.py:73:89: E501 Line too long (98 > 88)
True
>>> forward_chaining([ "P => Q", "L & M => P", "B&L=> M", "A&P=>L", "A&B=>L", "A", "B" ], "C")

Check failure on line 75 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E501)

inference_engine_algorithms/forward_chaining.py:75:89: E501 Line too long (98 > 88)
False

'''

count = number_of_symbols_in_premise(knowledge_base)
inferred = find_symbols_in_kb(knowledge_base)
queue = get_known_facts(knowledge_base)

while(len(queue) > 0):
p = queue.pop()
if p == query: return True

Check failure on line 86 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E701)

inference_engine_algorithms/forward_chaining.py:86:22: E701 Multiple statements on one line (colon)
if not inferred[p]:
inferred[p] = True
for clause in knowledge_base:
index = clause.find("=>")
premise = clause[:index]
if p in premise:
count[premise] -= 1
if count[premise] == 0:
queue.append(clause[-1])

return False




KB = [
"P => Q",
"L & M => P",
"B&L=> M",
"A&P=>L",

Check failure on line 106 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W291)

inference_engine_algorithms/forward_chaining.py:106:18: W291 Trailing whitespace
"A&B=>L",

Check failure on line 107 in inference_engine_algorithms/forward_chaining.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (W291)

inference_engine_algorithms/forward_chaining.py:107:18: W291 Trailing whitespace
"A",
"B" ]

'''
1)- KB must be written in horn form.
2)- It must be written as an implcaion whose
2)- It must be written as an implcaion whose
its premise(head) must be conjunction of positive literals and its conclusion(body)
3)- It must contains facts about the world which are written as a single proposition symbol
'''
QUERY = "Q"

'''
Query is a signe proposition symbol that you check if it is entailed by the KB

'''

if __name__ == "__main__":



import doctest

doctest.testmod(verbose=True)


result = forward_chaining(KB, QUERY)
print(result)