9
9
"""
10
10
11
11
import random
12
+ from typing import List , Dict
12
13
13
14
14
15
class Clause :
@@ -31,15 +32,15 @@ class Clause:
31
32
True
32
33
"""
33
34
34
- def __init__ (self , literals ) :
35
+ def __init__ (self , literals : List [ int ]) -> None :
35
36
"""
36
37
Represent the literals and an assignment in a clause."
37
38
"""
38
39
# Assign all literals to None initially
39
40
self .literals = {literal : None for literal in literals }
40
41
self .no_of_literals = len (self .literals )
41
42
42
- def __str__ (self ):
43
+ def __str__ (self ) -> str :
43
44
"""
44
45
To print a clause as in CNF.
45
46
Variable clause holds the string representation.
@@ -53,7 +54,7 @@ def __str__(self):
53
54
54
55
return clause
55
56
56
- def assign (self , model ) :
57
+ def assign (self , model : Dict [ str , bool ]) -> None :
57
58
"""
58
59
Assign values to literals of the clause as given by model.
59
60
"""
@@ -72,7 +73,7 @@ def assign(self, model):
72
73
self .literals [list (self .literals .keys ())[i ]] = val
73
74
i += 1
74
75
75
- def evaluate (self , model ) :
76
+ def evaluate (self , model : Dict [ str , bool ]) -> bool :
76
77
"""
77
78
Evaluates the clause with the assignments in model.
78
79
This has the following steps:
@@ -81,23 +82,21 @@ def evaluate(self, model):
81
82
3. Return None(unable to complete evaluation) if a literal has no assignment.
82
83
4. Compute disjunction of all values assigned in clause.
83
84
"""
84
- for literal in list ( self .literals . keys ()) :
85
+ for literal in self .literals :
85
86
if len (literal ) == 2 :
86
87
symbol = literal + "'"
87
- if symbol in list ( self .literals . keys ()) :
88
+ if symbol in self .literals :
88
89
return True
89
90
else :
90
91
symbol = literal [:2 ]
91
- if symbol in list ( self .literals . keys ()) :
92
+ if symbol in self .literals :
92
93
return True
93
94
94
95
self .assign (model )
95
96
result = False
96
97
for j in self .literals .values ():
97
- if j is True :
98
- return True
99
- elif j is None :
100
- return None
98
+ if j in (True , None ):
99
+ return j
101
100
for j in self .literals .values ():
102
101
result = result or j
103
102
return result
@@ -111,37 +110,39 @@ class Formula:
111
110
{{A1, A2, A3'}, {A5', A2', A1}} is ((A1 v A2 v A3') and (A5' v A2' v A1))
112
111
113
112
Create two clauses and a formula with them
114
- >>> c1 = Clause(["A1", "A2'", "A3"])
115
- >>> c2 = Clause(["A5'", "A2'", "A1"])
113
+ >>> clause1 = Clause(["A1", "A2'", "A3"])
114
+ >>> clause2 = Clause(["A5'", "A2'", "A1"])
116
115
117
- >>> f = Formula([c1, c2 ])
118
- >>> print(f )
119
- { { A1 , A2' , A3 } , { A5' , A2' , A1 } }
116
+ >>> formula = Formula([clause1, clause2 ])
117
+ >>> print(formula )
118
+ {{ A1 , A2' , A3 } , { A5' , A2' , A1 }}
120
119
"""
121
120
122
- def __init__ (self , clauses ) :
121
+ def __init__ (self , clauses : List [ Clause ]) -> None :
123
122
"""
124
123
Represent the number of clauses and the clauses themselves.
125
124
"""
126
125
self .clauses = [c for c in clauses ]
127
126
self .no_of_clauses = len (self .clauses )
128
127
129
- def __str__ (self ):
128
+ def __str__ (self ) -> str :
130
129
"""
131
130
To print a formula as in CNF.
132
131
Variable formula holds the string representation.
133
132
"""
134
- formula = "{ "
135
- for i in range (0 , self .no_of_clauses ):
136
- formula += str (self .clauses [i ]) + " "
137
- if i != self .no_of_clauses - 1 :
138
- formula += ", "
133
+ formula = "{"
134
+ clause_repr = " , "
135
+ clauses_as_strings = [str (clause ) for clause in self .clauses ]
136
+
137
+ clause_repr = clause_repr .join (clauses_as_strings )
138
+
139
+ formula += clause_repr
139
140
formula += "}"
140
141
141
142
return formula
142
143
143
144
144
- def generate_clause ():
145
+ def generate_clause () -> Clause :
145
146
"""
146
147
Randomly generate a clause.
147
148
All literals have the name Ax, where x is an integer from 1 to 5.
@@ -161,11 +162,10 @@ def generate_clause():
161
162
else :
162
163
literals .append (var_name )
163
164
i += 1
164
- clause = Clause (literals )
165
- return clause
165
+ return Clause (literals )
166
166
167
167
168
- def generate_formula ():
168
+ def generate_formula () -> Formula :
169
169
"""
170
170
Randomly generate a formula.
171
171
"""
@@ -179,40 +179,41 @@ def generate_formula():
179
179
else :
180
180
clauses .append (clause )
181
181
i += 1
182
- formula = Formula (set (clauses ))
183
- return formula
182
+ return Formula (set (clauses ))
184
183
185
184
186
- def generate_parameters (formula ):
185
+ def generate_parameters (formula : Formula ) -> ( List [ Clause ], List [ str ] ):
187
186
"""
188
187
Return the clauses and symbols from a formula.
189
188
A symbol is the uncomplemented form of a literal.
190
189
For example,
191
190
Symbol of A3 is A3.
192
191
Symbol of A5' is A5.
193
192
194
- >>> c1 = Clause(["A1", "A2'", "A3"])
195
- >>> c2 = Clause(["A5'", "A2'", "A1"])
193
+ >>> clause1 = Clause(["A1", "A2'", "A3"])
194
+ >>> clause2 = Clause(["A5'", "A2'", "A1"])
196
195
197
- >>> f = Formula([c1, c2 ])
198
- >>> c, s = generate_parameters(f )
199
- >>> l = [str(i) for i in c ]
200
- >>> print(l )
196
+ >>> formula = Formula([clause1, clause2 ])
197
+ >>> clauses, symbols = generate_parameters(formula )
198
+ >>> clauses_list = [str(i) for i in clauses ]
199
+ >>> print(clauses_list )
201
200
["{ A1 , A2' , A3 }", "{ A5' , A2' , A1 }"]
202
- >>> print(s )
201
+ >>> print(symbols )
203
202
['A1', 'A2', 'A3', 'A5']
204
203
"""
205
204
clauses = formula .clauses
206
205
symbols_set = []
207
206
for clause in formula .clauses :
208
- for literal in clause .literals . keys () :
207
+ for literal in clause .literals :
209
208
symbol = literal [:2 ]
210
209
if symbol not in symbols_set :
211
210
symbols_set .append (symbol )
212
211
return clauses , symbols_set
213
212
214
213
215
- def find_pure_symbols (clauses , symbols , model ):
214
+ def find_pure_symbols (
215
+ clauses : List [Clause ], symbols : List [str ], model : Dict [str , bool ]
216
+ ) -> (List [str ], Dict [str , bool ]):
216
217
"""
217
218
Return pure symbols and their values to satisfy clause.
218
219
Pure symbols are symbols in a formula that exist only
@@ -226,15 +227,15 @@ def find_pure_symbols(clauses, symbols, model):
226
227
3. Assign value True or False depending on whether the symbols occurs
227
228
in normal or complemented form respectively.
228
229
229
- >>> c1 = Clause(["A1", "A2'", "A3"])
230
- >>> c2 = Clause(["A5'", "A2'", "A1"])
230
+ >>> clause1 = Clause(["A1", "A2'", "A3"])
231
+ >>> clause2 = Clause(["A5'", "A2'", "A1"])
231
232
232
- >>> f = Formula([c1, c2 ])
233
- >>> c, s = generate_parameters(f )
233
+ >>> formula = Formula([clause1, clause2 ])
234
+ >>> clauses, symbols = generate_parameters(formula )
234
235
235
236
>>> model = {}
236
- >>> p, v = find_pure_symbols(c, s , model)
237
- >>> print(p, v )
237
+ >>> pure_symbols, values = find_pure_symbols(clauses, symbols , model)
238
+ >>> print(pure_symbols, values )
238
239
['A1', 'A2', 'A3', 'A5'] {'A1': True, 'A2': False, 'A3': True, 'A5': False}
239
240
"""
240
241
pure_symbols = []
@@ -244,7 +245,7 @@ def find_pure_symbols(clauses, symbols, model):
244
245
for clause in clauses :
245
246
if clause .evaluate (model ) is True :
246
247
continue
247
- for literal in clause .literals . keys () :
248
+ for literal in clause .literals :
248
249
literals .append (literal )
249
250
250
251
for s in symbols :
@@ -264,7 +265,9 @@ def find_pure_symbols(clauses, symbols, model):
264
265
return pure_symbols , assignment
265
266
266
267
267
- def find_unit_clauses (clauses , model ):
268
+ def find_unit_clauses (
269
+ clauses : List [Clause ], model : Dict [str , bool ]
270
+ ) -> (List [str ], Dict [str , bool ]):
268
271
"""
269
272
Returns the unit symbols and their values to satisfy clause.
270
273
Unit symbols are symbols in a formula that are:
@@ -276,17 +279,17 @@ def find_unit_clauses(clauses, model):
276
279
3. Assign True or False depending on whether the symbols occurs in
277
280
normal or complemented form respectively.
278
281
279
- >>> c1 = Clause(["A4", "A3", "A5'", "A1", "A3'"])
280
- >>> c2 = Clause(["A4"])
281
- >>> c3 = Clause(["A3"])
282
+ >>> clause1 = Clause(["A4", "A3", "A5'", "A1", "A3'"])
283
+ >>> clause2 = Clause(["A4"])
284
+ >>> clause3 = Clause(["A3"])
282
285
283
- >>> f = Formula([c1, c2, c3 ])
284
- >>> c, s = generate_parameters(f )
286
+ >>> formula = Formula([clause1, clause2, clause3 ])
287
+ >>> clauses, symbols = generate_parameters(formula )
285
288
286
289
>>> model = {}
287
- >>> u, v = find_unit_clauses(c , model)
290
+ >>> unit_clauses, values = find_unit_clauses(clauses , model)
288
291
289
- >>> print(u, v )
292
+ >>> print(unit_clauses, values )
290
293
['A4', 'A3'] {'A4': True, 'A3': True}
291
294
"""
292
295
unit_symbols = []
@@ -306,16 +309,15 @@ def find_unit_clauses(clauses, model):
306
309
assignment = dict ()
307
310
for i in unit_symbols :
308
311
symbol = i [:2 ]
309
- if len (i ) == 2 :
310
- assignment [symbol ] = True
311
- else :
312
- assignment [symbol ] = False
312
+ assignment [symbol ] = len (i ) == 2
313
313
unit_symbols = [i [:2 ] for i in unit_symbols ]
314
314
315
315
return unit_symbols , assignment
316
316
317
317
318
- def dpll_algorithm (clauses , symbols , model ):
318
+ def dpll_algorithm (
319
+ clauses : List [Clause ], symbols : List [str ], model : Dict [str , bool ]
320
+ ) -> (bool , Dict [str , bool ]):
319
321
"""
320
322
Returns the model if the formula is satisfiable, else None
321
323
This has the following steps:
0 commit comments