python-sat 1.9.dev2__cp313-cp313-win_amd64.whl → 1.9.dev4__cp313-cp313-win_amd64.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.
- pycard.cp313-win_amd64.pyd +0 -0
- pyformula.cp313-win_amd64.pyd +0 -0
- pysat/__init__.py +1 -1
- pysat/_fileio.py +15 -0
- pysat/examples/rc2.py +50 -23
- pysat/formula.py +84 -3
- pysat/integer.py +906 -245
- pysat/solvers.py +1898 -760
- pysolvers.cp313-win_amd64.pyd +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/rc2.py +50 -23
- {python_sat-1.9.dev2.dist-info → python_sat-1.9.dev4.dist-info}/METADATA +1 -1
- {python_sat-1.9.dev2.dist-info → python_sat-1.9.dev4.dist-info}/RECORD +28 -27
- {python_sat-1.9.dev2.dist-info → python_sat-1.9.dev4.dist-info}/WHEEL +1 -1
- {python_sat-1.9.dev2.dist-info → python_sat-1.9.dev4.dist-info}/top_level.txt +1 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/approxmc.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/bbscan.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/bica.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/fm.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/genhard.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/lbx.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/lsu.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/mcsls.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/models.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/musx.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/optux.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/primer.py +0 -0
- {python_sat-1.9.dev2.data → python_sat-1.9.dev4.data}/scripts/unigen.py +0 -0
- {python_sat-1.9.dev2.dist-info → python_sat-1.9.dev4.dist-info}/licenses/LICENSE.txt +0 -0
pycard.cp313-win_amd64.pyd
CHANGED
|
Binary file
|
|
Binary file
|
pysat/__init__.py
CHANGED
pysat/_fileio.py
CHANGED
|
@@ -74,6 +74,21 @@ except ImportError: # zstandard is introduced in Python 3.14
|
|
|
74
74
|
zstd_present = False
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
#
|
|
78
|
+
#==============================================================================
|
|
79
|
+
def read_all_text(fp):
|
|
80
|
+
"""
|
|
81
|
+
Read the entire contents of a file-like object and normalize the
|
|
82
|
+
result to text.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
data = fp.read()
|
|
86
|
+
|
|
87
|
+
if isinstance(data, bytes):
|
|
88
|
+
return data.decode('utf-8')
|
|
89
|
+
|
|
90
|
+
return data
|
|
91
|
+
|
|
77
92
|
|
|
78
93
|
#
|
|
79
94
|
#==============================================================================
|
pysat/examples/rc2.py
CHANGED
|
@@ -131,6 +131,7 @@
|
|
|
131
131
|
#
|
|
132
132
|
#==============================================================================
|
|
133
133
|
from __future__ import print_function
|
|
134
|
+
import bisect
|
|
134
135
|
import collections
|
|
135
136
|
import getopt
|
|
136
137
|
import itertools
|
|
@@ -810,8 +811,8 @@ class RC2(object):
|
|
|
810
811
|
handled by calling :func:`process_am1`.
|
|
811
812
|
"""
|
|
812
813
|
|
|
813
|
-
# literal connections
|
|
814
|
-
conns = collections.defaultdict(
|
|
814
|
+
# literal connections and selectors conflicting on their own
|
|
815
|
+
conns = collections.defaultdict(list)
|
|
815
816
|
confl = []
|
|
816
817
|
|
|
817
818
|
# prepare connections
|
|
@@ -819,26 +820,29 @@ class RC2(object):
|
|
|
819
820
|
st, props = self.oracle.propagate(assumptions=[l1], phase_saving=2)
|
|
820
821
|
if st:
|
|
821
822
|
for l2 in props:
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
conns[
|
|
823
|
+
l2 = -l2
|
|
824
|
+
if l2 in self.sels_set:
|
|
825
|
+
conns[l1].append(l2)
|
|
826
|
+
conns[l2].append(l1)
|
|
825
827
|
else:
|
|
826
828
|
# propagating this literal results in a conflict
|
|
827
829
|
confl.append(l1)
|
|
828
830
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
831
|
+
# sort (in-place) and deduplicate adjacency lists
|
|
832
|
+
for l in list(conns):
|
|
833
|
+
neigh = conns[l]
|
|
834
|
+
if neigh:
|
|
835
|
+
neigh.sort()
|
|
832
836
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
837
|
+
j = 1
|
|
838
|
+
for i in range(1, len(neigh)):
|
|
839
|
+
if neigh[i] != neigh[j - 1]:
|
|
840
|
+
neigh[j] = neigh[i]
|
|
841
|
+
j += 1
|
|
838
842
|
|
|
839
|
-
|
|
840
|
-
confl = list(confl)
|
|
843
|
+
del neigh[j:]
|
|
841
844
|
|
|
845
|
+
if confl:
|
|
842
846
|
# processing unit size cores
|
|
843
847
|
for l in confl:
|
|
844
848
|
self.core, self.minw = [l], self.wght[l]
|
|
@@ -849,24 +853,47 @@ class RC2(object):
|
|
|
849
853
|
print('c unit cores found: {0}; cost: {1}'.format(len(confl),
|
|
850
854
|
self.cost))
|
|
851
855
|
|
|
856
|
+
# the following graph manipulation requires
|
|
857
|
+
# fast membership checks for confl; making it a set
|
|
858
|
+
confl = set(confl)
|
|
859
|
+
|
|
860
|
+
# current degrees in the remaining graph;
|
|
861
|
+
# literals disconnected after removing conflicts are ignored
|
|
862
|
+
degree, lits = {}, set()
|
|
863
|
+
for l in conns:
|
|
864
|
+
if l not in confl:
|
|
865
|
+
d = sum(1 for l2 in conns[l] if l2 not in confl)
|
|
866
|
+
if d:
|
|
867
|
+
degree[l] = d
|
|
868
|
+
lits.add(l)
|
|
869
|
+
|
|
870
|
+
# detect AM1s on the original formula with conflicting selectors
|
|
871
|
+
# filtered out, similarly to the previous implementation
|
|
852
872
|
nof_am1 = 0
|
|
853
873
|
len_am1 = []
|
|
854
|
-
|
|
874
|
+
|
|
855
875
|
while lits:
|
|
856
|
-
am1 = [min(lits, key=lambda l:
|
|
876
|
+
am1 = [min(lits, key=lambda l: degree[l])]
|
|
857
877
|
|
|
858
|
-
for l in sorted(conns[am1[0]], key=lambda l:
|
|
878
|
+
for l in sorted(conns[am1[0]], key=lambda l: degree.get(l, 0)):
|
|
859
879
|
if l in lits:
|
|
860
880
|
for l_added in am1[1:]:
|
|
861
|
-
|
|
881
|
+
# adjacency lists are sorted, so we use
|
|
882
|
+
# binary search for clique membership tests
|
|
883
|
+
i = bisect.bisect_left(conns[l], l_added)
|
|
884
|
+
if i == len(conns[l]) or conns[l][i] != l_added:
|
|
862
885
|
break
|
|
863
886
|
else:
|
|
864
887
|
am1.append(l)
|
|
865
888
|
|
|
866
|
-
# updating remaining
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
889
|
+
# updating remaining literals and their degrees
|
|
890
|
+
am1_set = set(am1)
|
|
891
|
+
lits.difference_update(am1_set)
|
|
892
|
+
|
|
893
|
+
for l in am1:
|
|
894
|
+
for l2 in conns.get(l, []):
|
|
895
|
+
if l2 in lits:
|
|
896
|
+
degree[l2] -= 1
|
|
870
897
|
|
|
871
898
|
if len(am1) > 1:
|
|
872
899
|
# treat the new atmost1 relation
|
pysat/formula.py
CHANGED
|
@@ -271,7 +271,7 @@ import decimal
|
|
|
271
271
|
from enum import Enum
|
|
272
272
|
import itertools
|
|
273
273
|
import os
|
|
274
|
-
from pysat._fileio import FileObject
|
|
274
|
+
from pysat._fileio import FileObject, read_all_text
|
|
275
275
|
import sys
|
|
276
276
|
|
|
277
277
|
# checking whether or not py-aiger-cnf is available and working as expected
|
|
@@ -281,6 +281,13 @@ try:
|
|
|
281
281
|
except ImportError:
|
|
282
282
|
aiger_present = False
|
|
283
283
|
|
|
284
|
+
# checking whether or not native formula parser is available
|
|
285
|
+
pyformula_present = True
|
|
286
|
+
try:
|
|
287
|
+
import pyformula
|
|
288
|
+
except ImportError:
|
|
289
|
+
pyformula_present = False
|
|
290
|
+
|
|
284
291
|
try: # for Python2
|
|
285
292
|
from cStringIO import StringIO
|
|
286
293
|
except ImportError: # for Python3
|
|
@@ -3286,6 +3293,11 @@ class CNF(Formula, object):
|
|
|
3286
3293
|
... cnf2 = CNF(from_fp=fp)
|
|
3287
3294
|
"""
|
|
3288
3295
|
|
|
3296
|
+
if pyformula_present:
|
|
3297
|
+
self.nv, self.clauses, self.comments = pyformula.parse_cnf(
|
|
3298
|
+
read_all_text(file_pointer), comment_lead)
|
|
3299
|
+
return
|
|
3300
|
+
|
|
3289
3301
|
self.nv = 0
|
|
3290
3302
|
self.clauses = []
|
|
3291
3303
|
self.comments = []
|
|
@@ -3331,7 +3343,10 @@ class CNF(Formula, object):
|
|
|
3331
3343
|
3
|
|
3332
3344
|
"""
|
|
3333
3345
|
|
|
3334
|
-
|
|
3346
|
+
if pyformula_present:
|
|
3347
|
+
self.nv, self.clauses, self.comments = pyformula.parse_cnf(string, comment_lead)
|
|
3348
|
+
else:
|
|
3349
|
+
self.from_fp(StringIO(string), comment_lead)
|
|
3335
3350
|
|
|
3336
3351
|
def from_clauses(self, clauses, by_ref=False):
|
|
3337
3352
|
"""
|
|
@@ -4044,6 +4059,18 @@ class WCNF(object):
|
|
|
4044
4059
|
... cnf2 = WCNF(from_fp=fp)
|
|
4045
4060
|
"""
|
|
4046
4061
|
|
|
4062
|
+
if pyformula_present:
|
|
4063
|
+
self.nv, self.hard, self.soft, self.wght, self.topw, self.comments, negs = \
|
|
4064
|
+
pyformula.parse_wcnf(read_all_text(file_pointer), comment_lead)
|
|
4065
|
+
|
|
4066
|
+
if negs:
|
|
4067
|
+
self.normalize_negatives(negs)
|
|
4068
|
+
|
|
4069
|
+
if type(self.topw) == decimal.Decimal and self.topw.is_infinite():
|
|
4070
|
+
self.topw = 1 + sum(self.wght)
|
|
4071
|
+
|
|
4072
|
+
return
|
|
4073
|
+
|
|
4047
4074
|
def parse_wght(string):
|
|
4048
4075
|
if string == 'h':
|
|
4049
4076
|
return None
|
|
@@ -4171,7 +4198,17 @@ class WCNF(object):
|
|
|
4171
4198
|
3
|
|
4172
4199
|
"""
|
|
4173
4200
|
|
|
4174
|
-
|
|
4201
|
+
if pyformula_present:
|
|
4202
|
+
self.nv, self.hard, self.soft, self.wght, self.topw, self.comments, negs = \
|
|
4203
|
+
pyformula.parse_wcnf(string, comment_lead)
|
|
4204
|
+
|
|
4205
|
+
if negs:
|
|
4206
|
+
self.normalize_negatives(negs)
|
|
4207
|
+
|
|
4208
|
+
if type(self.topw) == decimal.Decimal and self.topw.is_infinite():
|
|
4209
|
+
self.topw = 1 + sum(self.wght)
|
|
4210
|
+
else:
|
|
4211
|
+
self.from_fp(StringIO(string), comment_lead)
|
|
4175
4212
|
|
|
4176
4213
|
def copy(self):
|
|
4177
4214
|
"""
|
|
@@ -4668,6 +4705,16 @@ class CNFPlus(CNF, object):
|
|
|
4668
4705
|
s = self.to_dimacs().replace('\n', '\\n')
|
|
4669
4706
|
return f'CNFPlus(from_string=\'{s}\')'
|
|
4670
4707
|
|
|
4708
|
+
def from_string(self, string, comment_lead=['c']):
|
|
4709
|
+
"""
|
|
4710
|
+
Read a CNF+ formula from a string.
|
|
4711
|
+
"""
|
|
4712
|
+
|
|
4713
|
+
if pyformula_present:
|
|
4714
|
+
self.nv, self.clauses, self.atmosts, self.comments = pyformula.parse_cnfplus(string, comment_lead)
|
|
4715
|
+
else:
|
|
4716
|
+
self.from_fp(StringIO(string), comment_lead)
|
|
4717
|
+
|
|
4671
4718
|
def from_fp(self, file_pointer, comment_lead=['c']):
|
|
4672
4719
|
"""
|
|
4673
4720
|
Read a CNF+ formula from a file pointer. A file pointer should be
|
|
@@ -4693,6 +4740,11 @@ class CNFPlus(CNF, object):
|
|
|
4693
4740
|
... cnf2 = CNFPlus(from_fp=fp)
|
|
4694
4741
|
"""
|
|
4695
4742
|
|
|
4743
|
+
if pyformula_present:
|
|
4744
|
+
self.nv, self.clauses, self.atmosts, self.comments = pyformula.parse_cnfplus(
|
|
4745
|
+
read_all_text(file_pointer), comment_lead)
|
|
4746
|
+
return
|
|
4747
|
+
|
|
4696
4748
|
self.nv = 0
|
|
4697
4749
|
self.clauses = []
|
|
4698
4750
|
self.atmosts = []
|
|
@@ -5196,6 +5248,23 @@ class WCNFPlus(WCNF, object):
|
|
|
5196
5248
|
s = self.to_dimacs().replace('\n', '\\n')
|
|
5197
5249
|
return f'WCNFPlus(from_string=\'{s}\')'
|
|
5198
5250
|
|
|
5251
|
+
def from_string(self, string, comment_lead=['c']):
|
|
5252
|
+
"""
|
|
5253
|
+
Read a WCNF+ formula from a string.
|
|
5254
|
+
"""
|
|
5255
|
+
|
|
5256
|
+
if pyformula_present:
|
|
5257
|
+
self.nv, self.hard, self.soft, self.wght, self.atms, self.topw, self.comments, negs = \
|
|
5258
|
+
pyformula.parse_wcnfplus(string, comment_lead)
|
|
5259
|
+
|
|
5260
|
+
if negs:
|
|
5261
|
+
self.normalize_negatives(negs)
|
|
5262
|
+
|
|
5263
|
+
if type(self.topw) == decimal.Decimal and self.topw.is_infinite():
|
|
5264
|
+
self.topw = 1 + sum(self.wght)
|
|
5265
|
+
else:
|
|
5266
|
+
self.from_fp(StringIO(string), comment_lead)
|
|
5267
|
+
|
|
5199
5268
|
def from_fp(self, file_pointer, comment_lead=['c']):
|
|
5200
5269
|
"""
|
|
5201
5270
|
Read a WCNF+ formula from a file pointer. A file pointer should be
|
|
@@ -5221,6 +5290,18 @@ class WCNFPlus(WCNF, object):
|
|
|
5221
5290
|
... cnf2 = WCNFPlus(from_fp=fp)
|
|
5222
5291
|
"""
|
|
5223
5292
|
|
|
5293
|
+
if pyformula_present:
|
|
5294
|
+
self.nv, self.hard, self.soft, self.wght, self.atms, self.topw, self.comments, negs = \
|
|
5295
|
+
pyformula.parse_wcnfplus(read_all_text(file_pointer), comment_lead)
|
|
5296
|
+
|
|
5297
|
+
if negs:
|
|
5298
|
+
self.normalize_negatives(negs)
|
|
5299
|
+
|
|
5300
|
+
if type(self.topw) == decimal.Decimal and self.topw.is_infinite():
|
|
5301
|
+
self.topw = 1 + sum(self.wght)
|
|
5302
|
+
|
|
5303
|
+
return
|
|
5304
|
+
|
|
5224
5305
|
def parse_wght(string):
|
|
5225
5306
|
if string == 'h':
|
|
5226
5307
|
return None
|