-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathSATSolver.py
113 lines (102 loc) · 3.24 KB
/
SATSolver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import sys
from copy import deepcopy
assign_true = set()
assign_false = set()
n_props, n_splits = 0, 0
def print_cnf(cnf):
s = ''
for i in cnf:
if len(i) > 0:
s += '(' + i.replace(' ', '+') + ')'
if s == '':
s = '()'
print(s)
def solve(cnf, literals):
print('\nCNF = ', end='')
print_cnf(cnf)
new_true = []
new_false = []
global assign_true, assign_false, n_props, n_splits
assign_true = set(assign_true)
assign_false = set(assign_false)
n_splits += 1
cnf = list(set(cnf))
units = [i for i in cnf if len(i)<3]
units = list(set(units))
if len(units):
for unit in units:
n_props += 1
if '!' in unit:
assign_false.add(unit[-1])
new_false.append(unit[-1])
i = 0
while True:
if unit in cnf[i]:
cnf.remove(cnf[i])
i -= 1
elif unit[-1] in cnf[i]:
cnf[i] = cnf[i].replace(unit[-1], '').strip()
i += 1
if i >= len(cnf):
break
else:
assign_true.add(unit)
new_true.append(unit)
i = 0
while True:
if '!'+unit in cnf[i]:
cnf[i] = cnf[i].replace('!'+unit, '').strip()
if ' ' in cnf[i]:
cnf[i] = cnf[i].replace(' ', ' ')
elif unit in cnf[i]:
cnf.remove(cnf[i])
i -= 1
i += 1
if i >= len(cnf):
break
print('Units =', units)
print('CNF after unit propogation = ', end = '')
print_cnf(cnf)
if len(cnf) == 0:
return True
if sum(len(clause)==0 for clause in cnf):
for i in new_true:
assign_true.remove(i)
for i in new_false:
assign_false.remove(i)
print('Null clause found, backtracking...')
return False
literals = [k for k in list(set(''.join(cnf))) if k.isalpha()]
x = literals[0]
if solve(deepcopy(cnf)+[x], deepcopy(literals)):
return True
elif solve(deepcopy(cnf)+['!'+x], deepcopy(literals)):
return True
else:
for i in new_true:
assign_true.remove(i)
for i in new_false:
assign_false.remove(i)
return False
def dpll():
global assign_true, assign_false, n_props, n_splits
input_cnf = open(sys.argv[1], 'r').read()
literals = [i for i in list(set(input_cnf)) if i.isalpha()]
cnf = input_cnf.splitlines()
if solve(cnf, literals):
print('\nNumber of Splits =', n_splits)
print('Unit Propogations =', n_props)
print('\nResult: SATISFIABLE')
print('Solution:')
for i in assign_true:
print('\t\t'+i, '= True')
for i in assign_false:
print('\t\t'+i, '= False')
else:
print('\nReached starting node!')
print('Number of Splitss =', n_splits)
print('Unit Propogations =', n_props)
print('\nResult: UNSATISFIABLE')
print()
if __name__=='__main__':
dpll()