-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsat.py
112 lines (98 loc) · 3.76 KB
/
sat.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
#!/usr/bin/env python
"""
Solves SAT instance by reading from stdin using an iterative or recursive
watchlist-based backtracking algorithm. Iterative algorithm is used by default,
unless the --recursive flag is given. Empty lines and lines starting with a #
will be ignored.
"""
from __future__ import division
from __future__ import print_function
from argparse import ArgumentParser
from argparse import FileType
from sys import stdin
from sys import stdout
from sys import stderr
from satinstance import SATInstance
from solvers.watchlist import setup_watchlist
from solvers import recursive_sat
from solvers import iterative_sat
__author__ = 'Sahand Saba'
def generate_assignmnets(instance, solver, verbose=False):
"""
Returns a generator that generates all the satisfying assignments for a
given SAT instance, using algorithm given by alg.
"""
n = len(instance.variables)
watchlist = setup_watchlist(instance)
if not watchlist:
return ()
assignment = [None] * n
return solver.solve(instance, watchlist, assignment, 0, verbose)
def run_solver(input_file, output_file, solver, brief, verbose, output_all,
starting_with):
"""
Run the given solver for the given file-like input object and write the
output to the given output file-like object.
"""
instance = SATInstance.from_file(input_file)
assignments = generate_assignmnets(instance, solver, verbose)
count = 0
for assignment in assignments:
count += 1
if verbose:
print('Found satisfying assignment #{}:'.format(count),
file=stderr)
assignment_str = instance.assignment_to_string(
assignment,
brief=brief,
starting_with=starting_with
)
output_file.write(assignment_str + '\n')
if not output_all:
break
if verbose and count == 0:
print('No satisfying assignment exists.', file=stderr)
def main():
args = parse_args()
with args.input:
with args.output:
run_solver(args.input, args.output, args.solver, args.brief,
args.verbose, args.all, args.starting_with)
def parse_args():
parser = ArgumentParser(description=__doc__)
parser.add_argument('-v',
'--verbose',
help='verbose output.',
action='store_true')
parser.add_argument('-a',
'--all',
help='output all possible solutions.',
action='store_true')
parser.add_argument('-b',
'--brief',
help=('brief output:'
' only outputs variables assigned true.'),
action='store_true')
parser.add_argument('--starting_with',
help=('only output variables with names'
' starting with the given string.'),
default='')
parser.add_argument('--iterative',
help='use the iterative algorithm.',
action='store_const',
dest='solver',
default=recursive_sat,
const=iterative_sat)
parser.add_argument('-i',
'--input',
help='read from given file instead of stdin.',
type=FileType('r'),
default=stdin)
parser.add_argument('-o',
'--output',
help='write to given file instead of default stdout.',
type=FileType('w'),
default=stdout)
return parser.parse_args()
if __name__ == '__main__':
main()