python-sat 1.8.dev23__cp312-cp312-macosx_11_0_arm64.whl → 1.8.dev24__cp312-cp312-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of python-sat might be problematic. Click here for more details.
- pycard.cpython-312-darwin.so +0 -0
- pysat/__init__.py +1 -1
- pysat/_fileio.py +1 -1
- pysat/examples/bbscan.py +91 -97
- pysolvers.cpython-312-darwin.so +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/bbscan.py +91 -97
- {python_sat-1.8.dev23.dist-info → python_sat-1.8.dev24.dist-info}/METADATA +1 -1
- {python_sat-1.8.dev23.dist-info → python_sat-1.8.dev24.dist-info}/RECORD +24 -24
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/approxmc.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/bica.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/fm.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/genhard.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/lbx.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/lsu.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/mcsls.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/models.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/musx.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/optux.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/primer.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/rc2.py +0 -0
- {python_sat-1.8.dev23.data → python_sat-1.8.dev24.data}/scripts/unigen.py +0 -0
- {python_sat-1.8.dev23.dist-info → python_sat-1.8.dev24.dist-info}/WHEEL +0 -0
- {python_sat-1.8.dev23.dist-info → python_sat-1.8.dev24.dist-info}/licenses/LICENSE.txt +0 -0
- {python_sat-1.8.dev23.dist-info → python_sat-1.8.dev24.dist-info}/top_level.txt +0 -0
pycard.cpython-312-darwin.so
CHANGED
|
Binary file
|
pysat/__init__.py
CHANGED
pysat/_fileio.py
CHANGED
pysat/examples/bbscan.py
CHANGED
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
>>> cnf = CNF(from_file='formula.wcnf.xz')
|
|
74
74
|
>>>
|
|
75
75
|
>>> # creating BBScan and running it
|
|
76
|
-
>>> with BBScan(cnf, solver='g3',
|
|
76
|
+
>>> with BBScan(cnf, solver='g3', rotate=True) as bbscan:
|
|
77
77
|
... bbone = bbscan.compute(algorithm='core')
|
|
78
78
|
...
|
|
79
79
|
... # outputting the results
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
... print(bbone)
|
|
82
82
|
[1, -3]
|
|
83
83
|
|
|
84
|
-
Each of the available algorithms can be augmented with
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
Each of the available algorithms can be augmented with a simple heuristic
|
|
85
|
+
aiming at reducing satisfying assignments and, thus, filtering out
|
|
86
|
+
unnecessary literals: namely, filtering rotatable literals. The heuristic
|
|
87
|
+
is described in the aforementioned paper.
|
|
88
88
|
|
|
89
89
|
Note that most of the methods of the class :class:`BBScan` are made
|
|
90
90
|
private. Therefore, the tool provides a minimalistic interface via which a
|
|
@@ -113,44 +113,42 @@ class BBScan:
|
|
|
113
113
|
"""
|
|
114
114
|
A solver for computing all backbone literals of a given Boolean
|
|
115
115
|
formula. It implements 6 algorithms for backbone computation described
|
|
116
|
-
in [1]_ augmented with
|
|
117
|
-
process.
|
|
116
|
+
in [1]_ augmented with a heuristic that can be speed up the process.
|
|
118
117
|
|
|
119
118
|
Note that the input formula can be a :class:`.CNF` object but also any
|
|
120
119
|
object of class :class:`.Formula`, thus the tool can used for
|
|
121
120
|
computing backbone literals of non-clausal formulas.
|
|
122
121
|
|
|
123
122
|
A user can select one of the SAT solvers available at hand
|
|
124
|
-
(``'glucose3'`` is used by default). The optional
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
(``'glucose3'`` is used by default). The optional heuristic can be
|
|
124
|
+
also specified as a Boolean input arguments ``rotate`` (turned off by
|
|
125
|
+
default).
|
|
127
126
|
|
|
128
127
|
The list of initialiser's arguments is as follows:
|
|
129
128
|
|
|
130
129
|
:param formula: input formula whose backbone is sought
|
|
131
130
|
:param solver: SAT oracle name
|
|
132
|
-
:param lift: apply literal lifting heuristic
|
|
133
131
|
:param rotate: apply rotatable literal filtering
|
|
134
132
|
:param verbose: verbosity level
|
|
135
133
|
|
|
136
134
|
:type formula: :class:`.Formula` or :class:`.CNF`
|
|
137
135
|
:type solver: str
|
|
138
|
-
:type lift: bool
|
|
139
136
|
:type rotate: bool
|
|
140
137
|
:type verbose: int
|
|
141
138
|
"""
|
|
142
139
|
|
|
143
|
-
def __init__(self, formula, solver='g3',
|
|
140
|
+
def __init__(self, formula, solver='g3', rotate=False, verbose=0):
|
|
144
141
|
"""
|
|
145
142
|
Constructor.
|
|
146
143
|
"""
|
|
147
144
|
|
|
148
145
|
self.formula = formula
|
|
146
|
+
self.focuscl = list(range(len(formula.clauses))) if rotate else []
|
|
149
147
|
self.verbose = verbose
|
|
150
148
|
self.oracle = None
|
|
151
149
|
|
|
152
150
|
# implicant reduction heuristics
|
|
153
|
-
self.
|
|
151
|
+
self.rotate = rotate
|
|
154
152
|
|
|
155
153
|
# basic stats
|
|
156
154
|
self.calls, self.filtered = 0, 0
|
|
@@ -230,12 +228,26 @@ class BBScan:
|
|
|
230
228
|
"""
|
|
231
229
|
|
|
232
230
|
self.calls += 1
|
|
231
|
+
trivial = []
|
|
233
232
|
|
|
234
233
|
if self.oracle.solve():
|
|
235
|
-
self.model = self.oracle.get_model()
|
|
234
|
+
self.model = set(self.oracle.get_model())
|
|
236
235
|
if focus_on is not None:
|
|
237
|
-
model
|
|
238
|
-
|
|
236
|
+
self.model &= set(focus_on)
|
|
237
|
+
|
|
238
|
+
# if filtering rotatable literals is requested then
|
|
239
|
+
# we should be clever about the clauses to traverse
|
|
240
|
+
if self.rotate:
|
|
241
|
+
self.focuscl = []
|
|
242
|
+
for i, cl in enumerate(self.formula):
|
|
243
|
+
for l in cl:
|
|
244
|
+
if l in self.model:
|
|
245
|
+
if len(cl) == 1:
|
|
246
|
+
trivial.append(l)
|
|
247
|
+
self.model.remove(l)
|
|
248
|
+
else:
|
|
249
|
+
self.focuscl.append(i)
|
|
250
|
+
break
|
|
239
251
|
else:
|
|
240
252
|
raise ValueError('Unsatisfiable formula')
|
|
241
253
|
|
|
@@ -258,50 +270,36 @@ class BBScan:
|
|
|
258
270
|
else:
|
|
259
271
|
assert 0, f'Unknown algorithm: {algorithm}'
|
|
260
272
|
|
|
261
|
-
return sorted(result, key=lambda l: abs(l))
|
|
262
|
-
|
|
263
|
-
def _get_implicant(self, model):
|
|
264
|
-
"""
|
|
265
|
-
Simple literal lifting used to reduce a given model.
|
|
266
|
-
"""
|
|
267
|
-
|
|
268
|
-
res, model = set(), set(model)
|
|
269
|
-
|
|
270
|
-
# traversing the clauses and collecting all literals
|
|
271
|
-
# that satisfy at least one clause of the formula
|
|
272
|
-
for cl in self.formula:
|
|
273
|
-
res |= set([l for l in cl if l in model])
|
|
274
|
-
|
|
275
|
-
return list(res)
|
|
273
|
+
return sorted(trivial + result, key=lambda l: abs(l))
|
|
276
274
|
|
|
277
275
|
def _filter_rotatable(self, model):
|
|
278
276
|
"""
|
|
279
277
|
Filter out rotatable literals.
|
|
280
278
|
"""
|
|
281
279
|
|
|
282
|
-
|
|
280
|
+
def get_unit(cl):
|
|
281
|
+
# this is supposed to be a faster alternative to the
|
|
282
|
+
# complete clause traversal with a conditional inside
|
|
283
|
+
unit = None
|
|
284
|
+
for l in cl:
|
|
285
|
+
if l in model:
|
|
286
|
+
if unit:
|
|
287
|
+
return
|
|
288
|
+
else:
|
|
289
|
+
unit = l
|
|
290
|
+
return unit
|
|
291
|
+
|
|
292
|
+
# result of this procedure
|
|
293
|
+
units = set([])
|
|
283
294
|
|
|
284
295
|
# determining unit literals
|
|
285
|
-
for
|
|
286
|
-
|
|
287
|
-
if
|
|
288
|
-
units.add(
|
|
296
|
+
for i in self.focuscl:
|
|
297
|
+
unit = get_unit(self.formula.clauses[i])
|
|
298
|
+
if unit:
|
|
299
|
+
units.add(unit)
|
|
289
300
|
|
|
290
301
|
self.filtered += len(model) - len(units)
|
|
291
|
-
return
|
|
292
|
-
|
|
293
|
-
def _process_model(self, model):
|
|
294
|
-
"""
|
|
295
|
-
Heuristically reduce a model.
|
|
296
|
-
"""
|
|
297
|
-
|
|
298
|
-
if self.lift:
|
|
299
|
-
model = self._get_implicant(model)
|
|
300
|
-
|
|
301
|
-
if self.rotate:
|
|
302
|
-
model = self._filter_rotatable(model)
|
|
303
|
-
|
|
304
|
-
return model
|
|
302
|
+
return units
|
|
305
303
|
|
|
306
304
|
def _compute_enum(self, focus_on=None):
|
|
307
305
|
"""
|
|
@@ -312,7 +310,7 @@ class BBScan:
|
|
|
312
310
|
print('c using enumeration-based algorithm')
|
|
313
311
|
|
|
314
312
|
# initial backbone estimate contains all literals
|
|
315
|
-
bbone =
|
|
313
|
+
bbone = self.model if focus_on is None else focus_on
|
|
316
314
|
|
|
317
315
|
while bbone:
|
|
318
316
|
# counting the number of calls
|
|
@@ -322,15 +320,14 @@ class BBScan:
|
|
|
322
320
|
if not self.oracle.solve():
|
|
323
321
|
break
|
|
324
322
|
|
|
325
|
-
coex = set(self.oracle.get_model())
|
|
326
|
-
self.model = [l for l in bbone if l in coex]
|
|
327
|
-
self.model = self._process_model(self.model)
|
|
328
|
-
|
|
329
323
|
# updating backbone estimate - intersection
|
|
330
|
-
bbone &= set(self.
|
|
324
|
+
bbone &= set(self.oracle.get_model())
|
|
325
|
+
|
|
326
|
+
if self.rotate:
|
|
327
|
+
bbone = self._filter_rotatable(bbone)
|
|
331
328
|
|
|
332
329
|
# blocking the previously found implicant
|
|
333
|
-
self.oracle.add_clause([-l for l in
|
|
330
|
+
self.oracle.add_clause([-l for l in bbone])
|
|
334
331
|
|
|
335
332
|
return list(bbone)
|
|
336
333
|
|
|
@@ -342,6 +339,8 @@ class BBScan:
|
|
|
342
339
|
if self.verbose:
|
|
343
340
|
print('c using iterative algorithm')
|
|
344
341
|
|
|
342
|
+
# initial estimate
|
|
343
|
+
# using sets for model and assumps to save filtering time
|
|
345
344
|
bbone, model = [], self.model if focus_on is None else focus_on
|
|
346
345
|
|
|
347
346
|
while model:
|
|
@@ -357,9 +356,10 @@ class BBScan:
|
|
|
357
356
|
else:
|
|
358
357
|
# it isn't and we've got a counterexample
|
|
359
358
|
# => using it to filter out more literals
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
359
|
+
model &= set(self.oracle.get_model())
|
|
360
|
+
|
|
361
|
+
if self.rotate:
|
|
362
|
+
model = self._filter_rotatable(model)
|
|
363
363
|
|
|
364
364
|
return bbone
|
|
365
365
|
|
|
@@ -372,7 +372,7 @@ class BBScan:
|
|
|
372
372
|
print('c using complement of backbone estimate algorithm')
|
|
373
373
|
|
|
374
374
|
# initial estimate
|
|
375
|
-
bbone =
|
|
375
|
+
bbone = self.model if focus_on is None else focus_on
|
|
376
376
|
|
|
377
377
|
# iterating until we find the backbone or determine there is none
|
|
378
378
|
while bbone:
|
|
@@ -385,23 +385,23 @@ class BBScan:
|
|
|
385
385
|
if self.oracle.solve() == False:
|
|
386
386
|
break
|
|
387
387
|
else:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
388
|
+
bbone &= set(self.oracle.get_model())
|
|
389
|
+
|
|
390
|
+
if self.rotate:
|
|
391
|
+
bbone = self._filter_rotatable(bbone)
|
|
392
392
|
|
|
393
393
|
return list(bbone)
|
|
394
394
|
|
|
395
395
|
def _compute_chunking(self, chunk_size=100, focus_on=None):
|
|
396
396
|
"""
|
|
397
|
-
|
|
397
|
+
Chunking algorithm.
|
|
398
398
|
"""
|
|
399
399
|
|
|
400
400
|
if self.verbose:
|
|
401
401
|
print('c using chunking algorithm, with chunk size:', chunk_size)
|
|
402
402
|
|
|
403
403
|
# initial estimate
|
|
404
|
-
bbone, model = [], self.model if focus_on is None else focus_on
|
|
404
|
+
bbone, model = [], list(self.model if focus_on is None else focus_on)
|
|
405
405
|
|
|
406
406
|
# we are going to use clause selectors
|
|
407
407
|
vpool = IDPool(start_from=self.formula.nv + 1)
|
|
@@ -427,7 +427,9 @@ class BBScan:
|
|
|
427
427
|
else:
|
|
428
428
|
coex = set(self.oracle.get_model())
|
|
429
429
|
model = [l for l in model if l in coex]
|
|
430
|
-
|
|
430
|
+
|
|
431
|
+
if self.rotate:
|
|
432
|
+
model = list(self._filter_rotatable(set(model)))
|
|
431
433
|
|
|
432
434
|
return bbone
|
|
433
435
|
|
|
@@ -440,21 +442,24 @@ class BBScan:
|
|
|
440
442
|
print('c using core-based algorithm')
|
|
441
443
|
|
|
442
444
|
# initial estimate
|
|
445
|
+
# using sets for model and assumps to save filtering time
|
|
443
446
|
bbone, model = [], self.model if focus_on is None else focus_on
|
|
444
447
|
|
|
445
448
|
# iterating until we find the backbone or determine there is none
|
|
446
449
|
while model:
|
|
447
450
|
# flipping all the literals
|
|
448
|
-
assumps =
|
|
451
|
+
assumps = {-l for l in model}
|
|
449
452
|
|
|
450
453
|
# getting unsatisfiable cores with them
|
|
451
454
|
while True:
|
|
452
455
|
self.calls += 1
|
|
453
456
|
|
|
454
457
|
if self.oracle.solve(assumptions=assumps):
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
model &= set(self.oracle.get_model())
|
|
459
|
+
|
|
460
|
+
if self.rotate:
|
|
461
|
+
model = self._filter_rotatable(model)
|
|
462
|
+
|
|
458
463
|
break
|
|
459
464
|
|
|
460
465
|
else:
|
|
@@ -464,18 +469,12 @@ class BBScan:
|
|
|
464
469
|
self.oracle.add_clause([-core[0]])
|
|
465
470
|
|
|
466
471
|
# remove from the working model
|
|
467
|
-
|
|
468
|
-
if indx < len(model) - 1:
|
|
469
|
-
model[indx] = model.pop()
|
|
470
|
-
else:
|
|
471
|
-
model.pop()
|
|
472
|
+
model.remove(-core[0])
|
|
472
473
|
|
|
473
474
|
# filtering out unnecessary flipped literals
|
|
474
|
-
|
|
475
|
-
assumps = [l for l in assumps if l not in core]
|
|
475
|
+
assumps -= set(core)
|
|
476
476
|
|
|
477
477
|
if not assumps:
|
|
478
|
-
# resorting to the iterative traversal algorithm
|
|
479
478
|
self.model = model
|
|
480
479
|
return bbone + self._compute_iter()
|
|
481
480
|
|
|
@@ -490,7 +489,7 @@ class BBScan:
|
|
|
490
489
|
print('c using core-based chunking, with chunk size:', chunk_size)
|
|
491
490
|
|
|
492
491
|
# initial estimate
|
|
493
|
-
bbone, model = [], self.model if focus_on is None else focus_on
|
|
492
|
+
bbone, model = [], list(self.model if focus_on is None else focus_on)
|
|
494
493
|
|
|
495
494
|
# we are going to use clause selectors
|
|
496
495
|
vpool = IDPool(start_from=self.formula.nv + 1)
|
|
@@ -501,7 +500,7 @@ class BBScan:
|
|
|
501
500
|
size = min(chunk_size, len(model))
|
|
502
501
|
|
|
503
502
|
# flipping all the literals
|
|
504
|
-
assumps, skipped =
|
|
503
|
+
assumps, skipped = {-model.pop() for i in range(size)}, set()
|
|
505
504
|
|
|
506
505
|
# getting unsatisfiable cores with them
|
|
507
506
|
while True:
|
|
@@ -510,7 +509,9 @@ class BBScan:
|
|
|
510
509
|
if self.oracle.solve(assumptions=assumps):
|
|
511
510
|
coex = set(self.oracle.get_model())
|
|
512
511
|
model = [l for l in model if l in coex]
|
|
513
|
-
|
|
512
|
+
|
|
513
|
+
if self.rotate:
|
|
514
|
+
model = list(self._filter_rotatable(set(model)))
|
|
514
515
|
|
|
515
516
|
if skipped:
|
|
516
517
|
bbone += self._compute_iter(focus_on=skipped)
|
|
@@ -526,11 +527,10 @@ class BBScan:
|
|
|
526
527
|
self.oracle.add_clause([-core[0]])
|
|
527
528
|
else:
|
|
528
529
|
# all removed literals are going to be tested later
|
|
529
|
-
skipped
|
|
530
|
+
skipped |= {-l for l in core}
|
|
530
531
|
|
|
531
532
|
# filtering out unnecessary flipped literals
|
|
532
|
-
|
|
533
|
-
assumps = [l for l in assumps if l not in core]
|
|
533
|
+
assumps -= set(core)
|
|
534
534
|
|
|
535
535
|
if not assumps:
|
|
536
536
|
# resorting to the iterative traversal algorithm
|
|
@@ -561,11 +561,10 @@ def parse_options():
|
|
|
561
561
|
|
|
562
562
|
try:
|
|
563
563
|
opts, args = getopt.getopt(sys.argv[1:],
|
|
564
|
-
'a:c:
|
|
564
|
+
'a:c:hrs:v',
|
|
565
565
|
['algo=',
|
|
566
566
|
'chunk=',
|
|
567
567
|
'help',
|
|
568
|
-
'lift',
|
|
569
568
|
'rotate',
|
|
570
569
|
'solver=',
|
|
571
570
|
'verbose'])
|
|
@@ -576,7 +575,6 @@ def parse_options():
|
|
|
576
575
|
|
|
577
576
|
algo = 'iter'
|
|
578
577
|
chunk = 100
|
|
579
|
-
lift = False
|
|
580
578
|
rotate = False
|
|
581
579
|
solver = 'g3'
|
|
582
580
|
verbose = 0
|
|
@@ -594,8 +592,6 @@ def parse_options():
|
|
|
594
592
|
elif opt in ('-h', '--help'):
|
|
595
593
|
usage()
|
|
596
594
|
sys.exit(0)
|
|
597
|
-
elif opt in ('-l', '--lift'):
|
|
598
|
-
lift = True
|
|
599
595
|
elif opt in ('-r', '--rotate'):
|
|
600
596
|
rotate = True
|
|
601
597
|
elif opt in ('-s', '--solver'):
|
|
@@ -605,7 +601,7 @@ def parse_options():
|
|
|
605
601
|
else:
|
|
606
602
|
assert False, 'Unhandled option: {0} {1}'.format(opt, arg)
|
|
607
603
|
|
|
608
|
-
return algo, chunk,
|
|
604
|
+
return algo, chunk, rotate, solver, verbose, args
|
|
609
605
|
|
|
610
606
|
|
|
611
607
|
#
|
|
@@ -622,7 +618,6 @@ def usage():
|
|
|
622
618
|
print(' -c, --chunk=<int,float> Chunk size for chunking algorithms')
|
|
623
619
|
print(' Available values: [1 .. INT_MAX] or (0 .. 1] (default: 100)')
|
|
624
620
|
print(' -h, --help Show this message')
|
|
625
|
-
print(' -l, --lift Apply literal lifting for heuristic model reduction')
|
|
626
621
|
print(' -r, --rotate Heuristically filter out rotatable literals')
|
|
627
622
|
print(' -s, --solver=<string> SAT solver to use')
|
|
628
623
|
print(' Available values: cd15, cd19, g3, g4, lgl, mcb, mcm, mpl, m22, mc, mgh (default: g3)')
|
|
@@ -632,7 +627,7 @@ def usage():
|
|
|
632
627
|
#
|
|
633
628
|
#==============================================================================
|
|
634
629
|
if __name__ == '__main__':
|
|
635
|
-
algo, chunk,
|
|
630
|
+
algo, chunk, rotate, solver, verbose, files = parse_options()
|
|
636
631
|
|
|
637
632
|
if files:
|
|
638
633
|
# read CNF from file
|
|
@@ -645,8 +640,7 @@ if __name__ == '__main__':
|
|
|
645
640
|
len(formula.clauses)))
|
|
646
641
|
|
|
647
642
|
# computing the backbone
|
|
648
|
-
with BBScan(formula, solver=solver,
|
|
649
|
-
verbose=verbose) as bbscan:
|
|
643
|
+
with BBScan(formula, solver=solver, rotate=rotate, verbose=verbose) as bbscan:
|
|
650
644
|
try:
|
|
651
645
|
bbone = bbscan.compute(algorithm=algo, chunk_size=chunk)
|
|
652
646
|
|
pysolvers.cpython-312-darwin.so
CHANGED
|
Binary file
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
>>> cnf = CNF(from_file='formula.wcnf.xz')
|
|
74
74
|
>>>
|
|
75
75
|
>>> # creating BBScan and running it
|
|
76
|
-
>>> with BBScan(cnf, solver='g3',
|
|
76
|
+
>>> with BBScan(cnf, solver='g3', rotate=True) as bbscan:
|
|
77
77
|
... bbone = bbscan.compute(algorithm='core')
|
|
78
78
|
...
|
|
79
79
|
... # outputting the results
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
... print(bbone)
|
|
82
82
|
[1, -3]
|
|
83
83
|
|
|
84
|
-
Each of the available algorithms can be augmented with
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
Each of the available algorithms can be augmented with a simple heuristic
|
|
85
|
+
aiming at reducing satisfying assignments and, thus, filtering out
|
|
86
|
+
unnecessary literals: namely, filtering rotatable literals. The heuristic
|
|
87
|
+
is described in the aforementioned paper.
|
|
88
88
|
|
|
89
89
|
Note that most of the methods of the class :class:`BBScan` are made
|
|
90
90
|
private. Therefore, the tool provides a minimalistic interface via which a
|
|
@@ -113,44 +113,42 @@ class BBScan:
|
|
|
113
113
|
"""
|
|
114
114
|
A solver for computing all backbone literals of a given Boolean
|
|
115
115
|
formula. It implements 6 algorithms for backbone computation described
|
|
116
|
-
in [1]_ augmented with
|
|
117
|
-
process.
|
|
116
|
+
in [1]_ augmented with a heuristic that can be speed up the process.
|
|
118
117
|
|
|
119
118
|
Note that the input formula can be a :class:`.CNF` object but also any
|
|
120
119
|
object of class :class:`.Formula`, thus the tool can used for
|
|
121
120
|
computing backbone literals of non-clausal formulas.
|
|
122
121
|
|
|
123
122
|
A user can select one of the SAT solvers available at hand
|
|
124
|
-
(``'glucose3'`` is used by default). The optional
|
|
125
|
-
|
|
126
|
-
|
|
123
|
+
(``'glucose3'`` is used by default). The optional heuristic can be
|
|
124
|
+
also specified as a Boolean input arguments ``rotate`` (turned off by
|
|
125
|
+
default).
|
|
127
126
|
|
|
128
127
|
The list of initialiser's arguments is as follows:
|
|
129
128
|
|
|
130
129
|
:param formula: input formula whose backbone is sought
|
|
131
130
|
:param solver: SAT oracle name
|
|
132
|
-
:param lift: apply literal lifting heuristic
|
|
133
131
|
:param rotate: apply rotatable literal filtering
|
|
134
132
|
:param verbose: verbosity level
|
|
135
133
|
|
|
136
134
|
:type formula: :class:`.Formula` or :class:`.CNF`
|
|
137
135
|
:type solver: str
|
|
138
|
-
:type lift: bool
|
|
139
136
|
:type rotate: bool
|
|
140
137
|
:type verbose: int
|
|
141
138
|
"""
|
|
142
139
|
|
|
143
|
-
def __init__(self, formula, solver='g3',
|
|
140
|
+
def __init__(self, formula, solver='g3', rotate=False, verbose=0):
|
|
144
141
|
"""
|
|
145
142
|
Constructor.
|
|
146
143
|
"""
|
|
147
144
|
|
|
148
145
|
self.formula = formula
|
|
146
|
+
self.focuscl = list(range(len(formula.clauses))) if rotate else []
|
|
149
147
|
self.verbose = verbose
|
|
150
148
|
self.oracle = None
|
|
151
149
|
|
|
152
150
|
# implicant reduction heuristics
|
|
153
|
-
self.
|
|
151
|
+
self.rotate = rotate
|
|
154
152
|
|
|
155
153
|
# basic stats
|
|
156
154
|
self.calls, self.filtered = 0, 0
|
|
@@ -230,12 +228,26 @@ class BBScan:
|
|
|
230
228
|
"""
|
|
231
229
|
|
|
232
230
|
self.calls += 1
|
|
231
|
+
trivial = []
|
|
233
232
|
|
|
234
233
|
if self.oracle.solve():
|
|
235
|
-
self.model = self.oracle.get_model()
|
|
234
|
+
self.model = set(self.oracle.get_model())
|
|
236
235
|
if focus_on is not None:
|
|
237
|
-
model
|
|
238
|
-
|
|
236
|
+
self.model &= set(focus_on)
|
|
237
|
+
|
|
238
|
+
# if filtering rotatable literals is requested then
|
|
239
|
+
# we should be clever about the clauses to traverse
|
|
240
|
+
if self.rotate:
|
|
241
|
+
self.focuscl = []
|
|
242
|
+
for i, cl in enumerate(self.formula):
|
|
243
|
+
for l in cl:
|
|
244
|
+
if l in self.model:
|
|
245
|
+
if len(cl) == 1:
|
|
246
|
+
trivial.append(l)
|
|
247
|
+
self.model.remove(l)
|
|
248
|
+
else:
|
|
249
|
+
self.focuscl.append(i)
|
|
250
|
+
break
|
|
239
251
|
else:
|
|
240
252
|
raise ValueError('Unsatisfiable formula')
|
|
241
253
|
|
|
@@ -258,50 +270,36 @@ class BBScan:
|
|
|
258
270
|
else:
|
|
259
271
|
assert 0, f'Unknown algorithm: {algorithm}'
|
|
260
272
|
|
|
261
|
-
return sorted(result, key=lambda l: abs(l))
|
|
262
|
-
|
|
263
|
-
def _get_implicant(self, model):
|
|
264
|
-
"""
|
|
265
|
-
Simple literal lifting used to reduce a given model.
|
|
266
|
-
"""
|
|
267
|
-
|
|
268
|
-
res, model = set(), set(model)
|
|
269
|
-
|
|
270
|
-
# traversing the clauses and collecting all literals
|
|
271
|
-
# that satisfy at least one clause of the formula
|
|
272
|
-
for cl in self.formula:
|
|
273
|
-
res |= set([l for l in cl if l in model])
|
|
274
|
-
|
|
275
|
-
return list(res)
|
|
273
|
+
return sorted(trivial + result, key=lambda l: abs(l))
|
|
276
274
|
|
|
277
275
|
def _filter_rotatable(self, model):
|
|
278
276
|
"""
|
|
279
277
|
Filter out rotatable literals.
|
|
280
278
|
"""
|
|
281
279
|
|
|
282
|
-
|
|
280
|
+
def get_unit(cl):
|
|
281
|
+
# this is supposed to be a faster alternative to the
|
|
282
|
+
# complete clause traversal with a conditional inside
|
|
283
|
+
unit = None
|
|
284
|
+
for l in cl:
|
|
285
|
+
if l in model:
|
|
286
|
+
if unit:
|
|
287
|
+
return
|
|
288
|
+
else:
|
|
289
|
+
unit = l
|
|
290
|
+
return unit
|
|
291
|
+
|
|
292
|
+
# result of this procedure
|
|
293
|
+
units = set([])
|
|
283
294
|
|
|
284
295
|
# determining unit literals
|
|
285
|
-
for
|
|
286
|
-
|
|
287
|
-
if
|
|
288
|
-
units.add(
|
|
296
|
+
for i in self.focuscl:
|
|
297
|
+
unit = get_unit(self.formula.clauses[i])
|
|
298
|
+
if unit:
|
|
299
|
+
units.add(unit)
|
|
289
300
|
|
|
290
301
|
self.filtered += len(model) - len(units)
|
|
291
|
-
return
|
|
292
|
-
|
|
293
|
-
def _process_model(self, model):
|
|
294
|
-
"""
|
|
295
|
-
Heuristically reduce a model.
|
|
296
|
-
"""
|
|
297
|
-
|
|
298
|
-
if self.lift:
|
|
299
|
-
model = self._get_implicant(model)
|
|
300
|
-
|
|
301
|
-
if self.rotate:
|
|
302
|
-
model = self._filter_rotatable(model)
|
|
303
|
-
|
|
304
|
-
return model
|
|
302
|
+
return units
|
|
305
303
|
|
|
306
304
|
def _compute_enum(self, focus_on=None):
|
|
307
305
|
"""
|
|
@@ -312,7 +310,7 @@ class BBScan:
|
|
|
312
310
|
print('c using enumeration-based algorithm')
|
|
313
311
|
|
|
314
312
|
# initial backbone estimate contains all literals
|
|
315
|
-
bbone =
|
|
313
|
+
bbone = self.model if focus_on is None else focus_on
|
|
316
314
|
|
|
317
315
|
while bbone:
|
|
318
316
|
# counting the number of calls
|
|
@@ -322,15 +320,14 @@ class BBScan:
|
|
|
322
320
|
if not self.oracle.solve():
|
|
323
321
|
break
|
|
324
322
|
|
|
325
|
-
coex = set(self.oracle.get_model())
|
|
326
|
-
self.model = [l for l in bbone if l in coex]
|
|
327
|
-
self.model = self._process_model(self.model)
|
|
328
|
-
|
|
329
323
|
# updating backbone estimate - intersection
|
|
330
|
-
bbone &= set(self.
|
|
324
|
+
bbone &= set(self.oracle.get_model())
|
|
325
|
+
|
|
326
|
+
if self.rotate:
|
|
327
|
+
bbone = self._filter_rotatable(bbone)
|
|
331
328
|
|
|
332
329
|
# blocking the previously found implicant
|
|
333
|
-
self.oracle.add_clause([-l for l in
|
|
330
|
+
self.oracle.add_clause([-l for l in bbone])
|
|
334
331
|
|
|
335
332
|
return list(bbone)
|
|
336
333
|
|
|
@@ -342,6 +339,8 @@ class BBScan:
|
|
|
342
339
|
if self.verbose:
|
|
343
340
|
print('c using iterative algorithm')
|
|
344
341
|
|
|
342
|
+
# initial estimate
|
|
343
|
+
# using sets for model and assumps to save filtering time
|
|
345
344
|
bbone, model = [], self.model if focus_on is None else focus_on
|
|
346
345
|
|
|
347
346
|
while model:
|
|
@@ -357,9 +356,10 @@ class BBScan:
|
|
|
357
356
|
else:
|
|
358
357
|
# it isn't and we've got a counterexample
|
|
359
358
|
# => using it to filter out more literals
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
359
|
+
model &= set(self.oracle.get_model())
|
|
360
|
+
|
|
361
|
+
if self.rotate:
|
|
362
|
+
model = self._filter_rotatable(model)
|
|
363
363
|
|
|
364
364
|
return bbone
|
|
365
365
|
|
|
@@ -372,7 +372,7 @@ class BBScan:
|
|
|
372
372
|
print('c using complement of backbone estimate algorithm')
|
|
373
373
|
|
|
374
374
|
# initial estimate
|
|
375
|
-
bbone =
|
|
375
|
+
bbone = self.model if focus_on is None else focus_on
|
|
376
376
|
|
|
377
377
|
# iterating until we find the backbone or determine there is none
|
|
378
378
|
while bbone:
|
|
@@ -385,23 +385,23 @@ class BBScan:
|
|
|
385
385
|
if self.oracle.solve() == False:
|
|
386
386
|
break
|
|
387
387
|
else:
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
388
|
+
bbone &= set(self.oracle.get_model())
|
|
389
|
+
|
|
390
|
+
if self.rotate:
|
|
391
|
+
bbone = self._filter_rotatable(bbone)
|
|
392
392
|
|
|
393
393
|
return list(bbone)
|
|
394
394
|
|
|
395
395
|
def _compute_chunking(self, chunk_size=100, focus_on=None):
|
|
396
396
|
"""
|
|
397
|
-
|
|
397
|
+
Chunking algorithm.
|
|
398
398
|
"""
|
|
399
399
|
|
|
400
400
|
if self.verbose:
|
|
401
401
|
print('c using chunking algorithm, with chunk size:', chunk_size)
|
|
402
402
|
|
|
403
403
|
# initial estimate
|
|
404
|
-
bbone, model = [], self.model if focus_on is None else focus_on
|
|
404
|
+
bbone, model = [], list(self.model if focus_on is None else focus_on)
|
|
405
405
|
|
|
406
406
|
# we are going to use clause selectors
|
|
407
407
|
vpool = IDPool(start_from=self.formula.nv + 1)
|
|
@@ -427,7 +427,9 @@ class BBScan:
|
|
|
427
427
|
else:
|
|
428
428
|
coex = set(self.oracle.get_model())
|
|
429
429
|
model = [l for l in model if l in coex]
|
|
430
|
-
|
|
430
|
+
|
|
431
|
+
if self.rotate:
|
|
432
|
+
model = list(self._filter_rotatable(set(model)))
|
|
431
433
|
|
|
432
434
|
return bbone
|
|
433
435
|
|
|
@@ -440,21 +442,24 @@ class BBScan:
|
|
|
440
442
|
print('c using core-based algorithm')
|
|
441
443
|
|
|
442
444
|
# initial estimate
|
|
445
|
+
# using sets for model and assumps to save filtering time
|
|
443
446
|
bbone, model = [], self.model if focus_on is None else focus_on
|
|
444
447
|
|
|
445
448
|
# iterating until we find the backbone or determine there is none
|
|
446
449
|
while model:
|
|
447
450
|
# flipping all the literals
|
|
448
|
-
assumps =
|
|
451
|
+
assumps = {-l for l in model}
|
|
449
452
|
|
|
450
453
|
# getting unsatisfiable cores with them
|
|
451
454
|
while True:
|
|
452
455
|
self.calls += 1
|
|
453
456
|
|
|
454
457
|
if self.oracle.solve(assumptions=assumps):
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
+
model &= set(self.oracle.get_model())
|
|
459
|
+
|
|
460
|
+
if self.rotate:
|
|
461
|
+
model = self._filter_rotatable(model)
|
|
462
|
+
|
|
458
463
|
break
|
|
459
464
|
|
|
460
465
|
else:
|
|
@@ -464,18 +469,12 @@ class BBScan:
|
|
|
464
469
|
self.oracle.add_clause([-core[0]])
|
|
465
470
|
|
|
466
471
|
# remove from the working model
|
|
467
|
-
|
|
468
|
-
if indx < len(model) - 1:
|
|
469
|
-
model[indx] = model.pop()
|
|
470
|
-
else:
|
|
471
|
-
model.pop()
|
|
472
|
+
model.remove(-core[0])
|
|
472
473
|
|
|
473
474
|
# filtering out unnecessary flipped literals
|
|
474
|
-
|
|
475
|
-
assumps = [l for l in assumps if l not in core]
|
|
475
|
+
assumps -= set(core)
|
|
476
476
|
|
|
477
477
|
if not assumps:
|
|
478
|
-
# resorting to the iterative traversal algorithm
|
|
479
478
|
self.model = model
|
|
480
479
|
return bbone + self._compute_iter()
|
|
481
480
|
|
|
@@ -490,7 +489,7 @@ class BBScan:
|
|
|
490
489
|
print('c using core-based chunking, with chunk size:', chunk_size)
|
|
491
490
|
|
|
492
491
|
# initial estimate
|
|
493
|
-
bbone, model = [], self.model if focus_on is None else focus_on
|
|
492
|
+
bbone, model = [], list(self.model if focus_on is None else focus_on)
|
|
494
493
|
|
|
495
494
|
# we are going to use clause selectors
|
|
496
495
|
vpool = IDPool(start_from=self.formula.nv + 1)
|
|
@@ -501,7 +500,7 @@ class BBScan:
|
|
|
501
500
|
size = min(chunk_size, len(model))
|
|
502
501
|
|
|
503
502
|
# flipping all the literals
|
|
504
|
-
assumps, skipped =
|
|
503
|
+
assumps, skipped = {-model.pop() for i in range(size)}, set()
|
|
505
504
|
|
|
506
505
|
# getting unsatisfiable cores with them
|
|
507
506
|
while True:
|
|
@@ -510,7 +509,9 @@ class BBScan:
|
|
|
510
509
|
if self.oracle.solve(assumptions=assumps):
|
|
511
510
|
coex = set(self.oracle.get_model())
|
|
512
511
|
model = [l for l in model if l in coex]
|
|
513
|
-
|
|
512
|
+
|
|
513
|
+
if self.rotate:
|
|
514
|
+
model = list(self._filter_rotatable(set(model)))
|
|
514
515
|
|
|
515
516
|
if skipped:
|
|
516
517
|
bbone += self._compute_iter(focus_on=skipped)
|
|
@@ -526,11 +527,10 @@ class BBScan:
|
|
|
526
527
|
self.oracle.add_clause([-core[0]])
|
|
527
528
|
else:
|
|
528
529
|
# all removed literals are going to be tested later
|
|
529
|
-
skipped
|
|
530
|
+
skipped |= {-l for l in core}
|
|
530
531
|
|
|
531
532
|
# filtering out unnecessary flipped literals
|
|
532
|
-
|
|
533
|
-
assumps = [l for l in assumps if l not in core]
|
|
533
|
+
assumps -= set(core)
|
|
534
534
|
|
|
535
535
|
if not assumps:
|
|
536
536
|
# resorting to the iterative traversal algorithm
|
|
@@ -561,11 +561,10 @@ def parse_options():
|
|
|
561
561
|
|
|
562
562
|
try:
|
|
563
563
|
opts, args = getopt.getopt(sys.argv[1:],
|
|
564
|
-
'a:c:
|
|
564
|
+
'a:c:hrs:v',
|
|
565
565
|
['algo=',
|
|
566
566
|
'chunk=',
|
|
567
567
|
'help',
|
|
568
|
-
'lift',
|
|
569
568
|
'rotate',
|
|
570
569
|
'solver=',
|
|
571
570
|
'verbose'])
|
|
@@ -576,7 +575,6 @@ def parse_options():
|
|
|
576
575
|
|
|
577
576
|
algo = 'iter'
|
|
578
577
|
chunk = 100
|
|
579
|
-
lift = False
|
|
580
578
|
rotate = False
|
|
581
579
|
solver = 'g3'
|
|
582
580
|
verbose = 0
|
|
@@ -594,8 +592,6 @@ def parse_options():
|
|
|
594
592
|
elif opt in ('-h', '--help'):
|
|
595
593
|
usage()
|
|
596
594
|
sys.exit(0)
|
|
597
|
-
elif opt in ('-l', '--lift'):
|
|
598
|
-
lift = True
|
|
599
595
|
elif opt in ('-r', '--rotate'):
|
|
600
596
|
rotate = True
|
|
601
597
|
elif opt in ('-s', '--solver'):
|
|
@@ -605,7 +601,7 @@ def parse_options():
|
|
|
605
601
|
else:
|
|
606
602
|
assert False, 'Unhandled option: {0} {1}'.format(opt, arg)
|
|
607
603
|
|
|
608
|
-
return algo, chunk,
|
|
604
|
+
return algo, chunk, rotate, solver, verbose, args
|
|
609
605
|
|
|
610
606
|
|
|
611
607
|
#
|
|
@@ -622,7 +618,6 @@ def usage():
|
|
|
622
618
|
print(' -c, --chunk=<int,float> Chunk size for chunking algorithms')
|
|
623
619
|
print(' Available values: [1 .. INT_MAX] or (0 .. 1] (default: 100)')
|
|
624
620
|
print(' -h, --help Show this message')
|
|
625
|
-
print(' -l, --lift Apply literal lifting for heuristic model reduction')
|
|
626
621
|
print(' -r, --rotate Heuristically filter out rotatable literals')
|
|
627
622
|
print(' -s, --solver=<string> SAT solver to use')
|
|
628
623
|
print(' Available values: cd15, cd19, g3, g4, lgl, mcb, mcm, mpl, m22, mc, mgh (default: g3)')
|
|
@@ -632,7 +627,7 @@ def usage():
|
|
|
632
627
|
#
|
|
633
628
|
#==============================================================================
|
|
634
629
|
if __name__ == '__main__':
|
|
635
|
-
algo, chunk,
|
|
630
|
+
algo, chunk, rotate, solver, verbose, files = parse_options()
|
|
636
631
|
|
|
637
632
|
if files:
|
|
638
633
|
# read CNF from file
|
|
@@ -645,8 +640,7 @@ if __name__ == '__main__':
|
|
|
645
640
|
len(formula.clauses)))
|
|
646
641
|
|
|
647
642
|
# computing the backbone
|
|
648
|
-
with BBScan(formula, solver=solver,
|
|
649
|
-
verbose=verbose) as bbscan:
|
|
643
|
+
with BBScan(formula, solver=solver, rotate=rotate, verbose=verbose) as bbscan:
|
|
650
644
|
try:
|
|
651
645
|
bbone = bbscan.compute(algorithm=algo, chunk_size=chunk)
|
|
652
646
|
|
|
@@ -1,29 +1,10 @@
|
|
|
1
|
-
pycard.cpython-312-darwin.so,sha256=
|
|
2
|
-
pysolvers.cpython-312-darwin.so,sha256=
|
|
3
|
-
python_sat-1.8.dev23.data/scripts/models.py,sha256=Ejojfty6n2REM2Di6aKoqQtQ_v_6MfHs7qkWLXruJuU,5728
|
|
4
|
-
python_sat-1.8.dev23.data/scripts/primer.py,sha256=HufdaErta1gd_gvvSOFyHdxTnPgIM0q6Z2PvV6u0mGM,23362
|
|
5
|
-
python_sat-1.8.dev23.data/scripts/lbx.py,sha256=PwvcU8eG2oaZpkNRLDsDOjTcOF0aS4CWg1MEuuK2_CA,23236
|
|
6
|
-
python_sat-1.8.dev23.data/scripts/musx.py,sha256=RO7eP6alQ8qDZTvI1co3xUoni1xRKb4sT9rm9Of0qGk,10933
|
|
7
|
-
python_sat-1.8.dev23.data/scripts/bica.py,sha256=Tc9RjYKO-Lj9GNQjXnM87PJ3Dx2f2bHd2V2Igb-B1FM,27085
|
|
8
|
-
python_sat-1.8.dev23.data/scripts/rc2.py,sha256=eVaXQCbFrOtM6SbGj1ivLHqFQHjxt8cjhoBicOD85Oo,69968
|
|
9
|
-
python_sat-1.8.dev23.data/scripts/bbscan.py,sha256=HlOkdZMGHaBiz4Rz37nyJPj-MasC3hpNnnROU12b3V8,22367
|
|
10
|
-
python_sat-1.8.dev23.data/scripts/fm.py,sha256=nWL-TtQst6YMaHS_5amNZzeLkOrWeuv4HgU7xrBDu5o,18123
|
|
11
|
-
python_sat-1.8.dev23.data/scripts/mcsls.py,sha256=STkPj4-WY6PaNklluGbfciZREJ--gXNMKZHQXohu4p8,22080
|
|
12
|
-
python_sat-1.8.dev23.data/scripts/optux.py,sha256=kR3CD3h1Fve08eMt1aU4Vq5eTygWOHNIoZc008KgSdM,27684
|
|
13
|
-
python_sat-1.8.dev23.data/scripts/lsu.py,sha256=dBW9gqzXR6xTLRzjeIhMVREaaiSvGAnIuzLIZRKqEuE,16185
|
|
14
|
-
python_sat-1.8.dev23.data/scripts/genhard.py,sha256=o8qSa7sksQxyhbRahmRBws3F6emQu3pe_rkxY_aXEkw,19004
|
|
15
|
-
python_sat-1.8.dev23.data/scripts/unigen.py,sha256=_tk18u_4Jg8tOhZe1CmPOHzbEJ-mJqs-mFzBfcupXuQ,16705
|
|
16
|
-
python_sat-1.8.dev23.data/scripts/approxmc.py,sha256=Y_aUYOqQ-S1ABrkzFZx4sh4dP7Ua7J9Gn47XsHcAdM8,13573
|
|
17
|
-
python_sat-1.8.dev23.dist-info/RECORD,,
|
|
18
|
-
python_sat-1.8.dev23.dist-info/WHEEL,sha256=V1loQ6TpxABu1APUg0MoTRBOzSKT5xVc3skizX-ovCU,136
|
|
19
|
-
python_sat-1.8.dev23.dist-info/top_level.txt,sha256=fgEEGhMLivlF1ExCX8Y3niWsr4pDPRb5HdaWjNtabFI,23
|
|
20
|
-
python_sat-1.8.dev23.dist-info/METADATA,sha256=VzlHWKec_KsWy4N2EgDaLstTj-d-4CbDNjU_jT3F7Gk,1739
|
|
21
|
-
python_sat-1.8.dev23.dist-info/licenses/LICENSE.txt,sha256=6QMvEzxqdPXEoiAZUBaZLeLF4hW2S81fjKz_THER0uQ,1109
|
|
1
|
+
pycard.cpython-312-darwin.so,sha256=eskEvQY2iqZknEYK4tRyHXyZ4XDKLg_2isNZ-OXXAKo,97856
|
|
2
|
+
pysolvers.cpython-312-darwin.so,sha256=OACSizfcdkzSf26Rkk2fp0Ux7x8NvHvRuhwjbEaYPrI,3369056
|
|
22
3
|
pysat/pb.py,sha256=fLmfzPPtmEFp-ufHlxyfL1YAVNmxWZdm_ARRdwxUib4,16686
|
|
23
|
-
pysat/_fileio.py,sha256=
|
|
4
|
+
pysat/_fileio.py,sha256=cmrqvhPXxC87lpvLlFDG7EWpusQOaqCGPMDfWhqT6dg,6373
|
|
24
5
|
pysat/formula.py,sha256=3ZhI1ePvlreXJ7nRKMIftRsllm9lDDfXWYMt7AA8nSc,202858
|
|
25
6
|
pysat/engines.py,sha256=PzcZJ4zFXDHfcSSHF7iPadtrwSVEt4t9B_cO5epwTZk,45182
|
|
26
|
-
pysat/__init__.py,sha256=
|
|
7
|
+
pysat/__init__.py,sha256=q4ytD1iDnO0YnCvacaurDV1OAzxUoOgDbus24YL7_88,670
|
|
27
8
|
pysat/solvers.py,sha256=00Y6yKNXvJOLA7l4aIDgueFbNM9lt3PkmT2OxB43aQ8,229975
|
|
28
9
|
pysat/card.py,sha256=Np6HK2LfD-7YuOP53jMAm6JIO1lPFu_jqJP18n03uvM,30066
|
|
29
10
|
pysat/process.py,sha256=8lNbpEKipFZjbQ9DCJPfdL8eZHx-ltNuu7h4geWWdJY,12739
|
|
@@ -39,10 +20,29 @@ pysat/examples/hitman.py,sha256=vHJEeSfoMQlDD3D3Poofaryv-k_dMH37XoqVXJUUuUg,2636
|
|
|
39
20
|
pysat/examples/bica.py,sha256=OGcGQGQnMepCCurwRbygokFgoDkI7eBhjmsYvr3FM1M,27098
|
|
40
21
|
pysat/examples/rc2.py,sha256=RnS_RLBryjTBk_jhYY1LV37DmOkeI0H-RV-OPC4d0fw,69981
|
|
41
22
|
pysat/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
-
pysat/examples/bbscan.py,sha256=
|
|
23
|
+
pysat/examples/bbscan.py,sha256=E4Y5j3Llr0-jIn-RDZIk-f02Sbujg4wX7uysoiFRnLg,22046
|
|
43
24
|
pysat/examples/fm.py,sha256=e_s6wNBstEeoMw9zYyyDRgkE-Hqa902Iy_CxCS961CE,18136
|
|
44
25
|
pysat/examples/mcsls.py,sha256=bP47P56OOP_uy0MuFA7TGxMdkAis7gX4E9AEEI0tSec,22093
|
|
45
26
|
pysat/examples/optux.py,sha256=8eYHO_uhL_4ugb-hRv2s6cnOwTurfqkpbdnK9T4iDtw,27697
|
|
46
27
|
pysat/examples/lsu.py,sha256=qyN2TvXG61EtMy-IrX5EYmLPM_iNOhtOkGTY5nHO_zo,16198
|
|
47
28
|
pysat/examples/genhard.py,sha256=DFXtSVQ4qn78y0-ZMr2D6gBCLizZSzgkvcbDsjqjnKI,19017
|
|
48
29
|
pysat/examples/usage.py,sha256=x9luw6pyKAAndlxAeUWFhS4aLSVmD2t_j_5uA9YddHg,2183
|
|
30
|
+
python_sat-1.8.dev24.dist-info/RECORD,,
|
|
31
|
+
python_sat-1.8.dev24.dist-info/WHEEL,sha256=V1loQ6TpxABu1APUg0MoTRBOzSKT5xVc3skizX-ovCU,136
|
|
32
|
+
python_sat-1.8.dev24.dist-info/top_level.txt,sha256=fgEEGhMLivlF1ExCX8Y3niWsr4pDPRb5HdaWjNtabFI,23
|
|
33
|
+
python_sat-1.8.dev24.dist-info/METADATA,sha256=R_7J8Y-D1s7n7ix1OlAGzu2MhAepsbob2QYQrl5vsQo,1739
|
|
34
|
+
python_sat-1.8.dev24.dist-info/licenses/LICENSE.txt,sha256=6QMvEzxqdPXEoiAZUBaZLeLF4hW2S81fjKz_THER0uQ,1109
|
|
35
|
+
python_sat-1.8.dev24.data/scripts/models.py,sha256=Ejojfty6n2REM2Di6aKoqQtQ_v_6MfHs7qkWLXruJuU,5728
|
|
36
|
+
python_sat-1.8.dev24.data/scripts/primer.py,sha256=HufdaErta1gd_gvvSOFyHdxTnPgIM0q6Z2PvV6u0mGM,23362
|
|
37
|
+
python_sat-1.8.dev24.data/scripts/lbx.py,sha256=PwvcU8eG2oaZpkNRLDsDOjTcOF0aS4CWg1MEuuK2_CA,23236
|
|
38
|
+
python_sat-1.8.dev24.data/scripts/musx.py,sha256=RO7eP6alQ8qDZTvI1co3xUoni1xRKb4sT9rm9Of0qGk,10933
|
|
39
|
+
python_sat-1.8.dev24.data/scripts/bica.py,sha256=Tc9RjYKO-Lj9GNQjXnM87PJ3Dx2f2bHd2V2Igb-B1FM,27085
|
|
40
|
+
python_sat-1.8.dev24.data/scripts/rc2.py,sha256=eVaXQCbFrOtM6SbGj1ivLHqFQHjxt8cjhoBicOD85Oo,69968
|
|
41
|
+
python_sat-1.8.dev24.data/scripts/bbscan.py,sha256=NpCCeJ0HAtQT41c06R2h_xYvkKgJtsCraCktUPmj7GQ,22033
|
|
42
|
+
python_sat-1.8.dev24.data/scripts/fm.py,sha256=nWL-TtQst6YMaHS_5amNZzeLkOrWeuv4HgU7xrBDu5o,18123
|
|
43
|
+
python_sat-1.8.dev24.data/scripts/mcsls.py,sha256=STkPj4-WY6PaNklluGbfciZREJ--gXNMKZHQXohu4p8,22080
|
|
44
|
+
python_sat-1.8.dev24.data/scripts/optux.py,sha256=kR3CD3h1Fve08eMt1aU4Vq5eTygWOHNIoZc008KgSdM,27684
|
|
45
|
+
python_sat-1.8.dev24.data/scripts/lsu.py,sha256=dBW9gqzXR6xTLRzjeIhMVREaaiSvGAnIuzLIZRKqEuE,16185
|
|
46
|
+
python_sat-1.8.dev24.data/scripts/genhard.py,sha256=o8qSa7sksQxyhbRahmRBws3F6emQu3pe_rkxY_aXEkw,19004
|
|
47
|
+
python_sat-1.8.dev24.data/scripts/unigen.py,sha256=_tk18u_4Jg8tOhZe1CmPOHzbEJ-mJqs-mFzBfcupXuQ,16705
|
|
48
|
+
python_sat-1.8.dev24.data/scripts/approxmc.py,sha256=Y_aUYOqQ-S1ABrkzFZx4sh4dP7Ua7J9Gn47XsHcAdM8,13573
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|