1
- import re
1
+ '''
2
+ The forward-chaining algorithm PL-FC-ENTAILS? (KB, q) determines if a single proposition
3
+ symbol q—the query—is entailed by a knowledge base of definite clauses. It begins from
4
+ known facts (positive literals) in the knowledge base.
5
+ known facts (positive literals) in the knowledge base.
6
+
7
+ Reference: https://dl.ebooksworld.ir/books/Artificial.Intelligence.A.Modern.Approach.4th.Edition.Peter.Norvig.%20Stuart.Russell.Pearson.9780134610993.EBooksWorld.ir.pdf
8
+
9
+ '''
2
10
11
+ import re
3
12
4
13
def find_symbols_in_kb (knowledge_base : list [str ]) -> dict :
5
- """ """
14
+ '''
15
+ Find all unique symbols in the Knowledge_base
16
+ :param knowledge_base: a list of string of definite clauses
17
+ :returns: a dictionary with symbols as the keys their values are False
18
+ '''
19
+
6
20
inferred = {}
7
21
8
22
for i in range (len (knowledge_base )):
9
- symbols = re .findall (r" [a-zA-Z]" , knowledge_base [i ])
23
+ symbols = re .findall (r' [a-zA-Z]' , knowledge_base [i ])
10
24
for symbol in symbols :
11
25
if symbol not in inferred :
12
26
inferred [symbol ] = False
@@ -15,21 +29,32 @@ def find_symbols_in_kb(knowledge_base: list[str]) -> dict:
15
29
16
30
17
31
def number_of_symbols_in_premise (knowledge_base : list [str ]) -> dict :
18
- """ """
32
+
33
+ '''
34
+ Count the number of prposiotion symbols in each premise of KB clause
35
+ :param knowledge_base: a list of string of definite clauses
36
+ :returns: a dictionary with key as the premise of KB clause and value of count of symbols in the premise
37
+ '''
19
38
20
39
count = {}
21
40
for clause in knowledge_base :
22
- if len (clause ) != 1 :
41
+ if ( len (clause ) != 1 ) :
23
42
index = clause .find ("=>" )
24
43
premise = clause [:index ]
25
- letters = "" .join (e for e in premise if e .isalpha ())
44
+ letters = '' .join (e for e in premise if e .isalpha ())
26
45
count [premise ] = len (letters )
27
46
28
47
return count
29
48
30
49
31
50
def get_known_facts (knowledge_base : list [str ]) -> list [str ]:
32
- """ """
51
+ '''
52
+ Get the known facts in KB
53
+ :param knowledge_base: a list of string of definite clauses
54
+ :returns: list of facts
55
+
56
+ '''
57
+
33
58
facts = []
34
59
for clause in knowledge_base :
35
60
if len (clause ) == 1 :
@@ -38,16 +63,28 @@ def get_known_facts(knowledge_base: list[str]) -> list[str]:
38
63
return facts
39
64
40
65
41
- def forward_chianing (knowledge_base : list [str ], query : str ) -> bool :
66
+
67
+
68
+ def forward_chaining (knowledge_base : list [str ], query :str ) -> bool :
69
+ ''' Forward chaining on Knowledge Base(KB) of definite clauses
70
+ :param knowledge_base: a list of string of definite clauses
71
+ :param query: a single proposition symbol that you are checking if it is entailed by the KB
72
+ :returns: If the query entailed by the KB or not?
73
+ >>> forward_chaining([ "P => Q", "L & M => P", "B&L=> M", "A&P=>L", "A&B=>L", "A", "B" ], "Q")
74
+ True
75
+ >>> forward_chaining([ "P => Q", "L & M => P", "B&L=> M", "A&P=>L", "A&B=>L", "A", "B" ], "C")
76
+ False
77
+
78
+ '''
79
+
42
80
count = number_of_symbols_in_premise (knowledge_base )
43
81
inferred = find_symbols_in_kb (knowledge_base )
44
82
queue = get_known_facts (knowledge_base )
45
83
46
- while len (queue ) > 0 :
84
+ while ( len (queue ) > 0 ) :
47
85
p = queue .pop ()
48
- if p == query :
49
- return True
50
- if inferred [p ] == False :
86
+ if p == query : return True
87
+ if not inferred [p ]:
51
88
inferred [p ] = True
52
89
for clause in knowledge_base :
53
90
index = clause .find ("=>" )
@@ -60,22 +97,39 @@ def forward_chianing(knowledge_base: list[str], query: str) -> bool:
60
97
return False
61
98
62
99
100
+
101
+
102
+ KB = [
103
+ "P => Q" ,
104
+ "L & M => P" ,
105
+ "B&L=> M" ,
106
+ "A&P=>L" ,
107
+ "A&B=>L" ,
108
+ "A" ,
109
+ "B" ]
110
+
111
+ '''
112
+ 1)- KB must be written in horn form.
113
+ 2)- It must be written as an implcaion whose
114
+ 2)- It must be written as an implcaion whose
115
+ its premise(head) must be conjunction of positive literals and its conclusion(body)
116
+ 3)- It must contains facts about the world which are written as a single proposition symbol
117
+ '''
118
+ QUERY = "Q"
119
+
120
+ '''
121
+ Query is a signe proposition symbol that you check if it is entailed by the KB
122
+
123
+ '''
124
+
63
125
if __name__ == "__main__" :
64
- kb = [
65
- "p => q" ,
66
- "q => r" ,
67
- "r => p" ,
68
- "s => t" ,
69
- "u => v" ,
70
- "v => w" ,
71
- "w => u" ,
72
- "a" ,
73
- "b" ,
74
- "c" ,
75
- "w" ,
76
- "u&q=>r" ,
77
- "q" ,
78
- ]
79
-
80
- result = forward_chianing (kb , "p" )
81
- print (result )
126
+
127
+
128
+
129
+ import doctest
130
+
131
+ doctest .testmod (verbose = True )
132
+
133
+
134
+ result = forward_chaining (KB , QUERY )
135
+ print (result )
0 commit comments