python-sat 1.8.dev18__tar.gz → 1.8.dev19__tar.gz
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.
- {python-sat-1.8.dev18/python_sat.egg-info → python_sat-1.8.dev19}/PKG-INFO +1 -1
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/bica.py +5 -5
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/__init__.py +1 -1
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/formula.py +78 -74
- {python-sat-1.8.dev18 → python_sat-1.8.dev19/python_sat.egg-info}/PKG-INFO +1 -1
- python_sat-1.8.dev19/tests/test_formula_unique.py +101 -0
- python-sat-1.8.dev18/tests/test_formula_unique.py +0 -38
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/LICENSE.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/MANIFEST.in +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/README.rst +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/allies/__init__.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/allies/approxmc.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/allies/unigen.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/bitwise.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/card.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/clset.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/common.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/itot.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/ladder.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/mto.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/pairwise.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/ptypes.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/pycard.cc +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/seqcounter.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/sortcard.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/cardenc/utils.hh +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/__init__.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/fm.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/genhard.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/hitman.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/lbx.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/lsu.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/mcsls.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/models.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/musx.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/optux.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/primer.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/rc2.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/examples/usage.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/_fileio.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/_utils.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/card.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/engines.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/pb.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/process.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/pysat/solvers.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/python_sat.egg-info/SOURCES.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/python_sat.egg-info/dependency_links.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/python_sat.egg-info/requires.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/python_sat.egg-info/top_level.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/requirements.txt +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/setup.cfg +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/setup.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/cadical103.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/cadical153.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/cadical170.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/cadical195.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/glucose30.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/glucose41.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/glucose421.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/lingeling.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/maplechrono.zip +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/maplecm.zip +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/maplesat.zip +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/mergesat3.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/minicard.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/minisat22.tar.gz +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/minisatgh.zip +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/cadical103.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/cadical153.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/cadical195.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/glucose30.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/glucose41.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/glucose421.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/gluecard30.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/gluecard41.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/lingeling.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/maplechrono.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/maplecm.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/maplesat.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/mergesat3.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/minicard.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/minisat22.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/patches/minisatgh.patch +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/prepare.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/solvers/pysolvers.cc +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_accum_stats.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_atmost.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_atmost1.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_atmostk.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_boolengine.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_clausification.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_cnf.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_equals1.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_process.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_propagate.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_unique_model.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_unique_mus.py +0 -0
- {python-sat-1.8.dev18 → python_sat-1.8.dev19}/tests/test_warmstart.py +0 -0
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
navigation to determine the Southern Celestial Pole.)
|
|
52
52
|
|
|
53
53
|
.. [1] Alexey Ignatiev, Alessandro Previti, Joao Marques-Silva.
|
|
54
|
-
*SAT-Based Formula Simplification*. SAT 2015. pp.
|
|
54
|
+
*SAT-Based Formula Simplification*. SAT 2015. pp. 287-298
|
|
55
55
|
|
|
56
56
|
.. [2] Willard V. Quine. *The Problem of Simplifying Truth Functions*.
|
|
57
57
|
American Mathematical Monthly 59(8). 1952. pp. 521-531
|
|
@@ -262,10 +262,10 @@ class Bica:
|
|
|
262
262
|
|
|
263
263
|
"""
|
|
264
264
|
|
|
265
|
-
def __init__(self, formula, negated=None, target='cnf', psolver='
|
|
265
|
+
def __init__(self, formula, negated=None, target='cnf', psolver='cd19',
|
|
266
266
|
padapt=False, pdcalls=False, pexhaust=False, pminz=False,
|
|
267
267
|
ppuresat=False, psearch='lin', punsorted=False, ptrim=False,
|
|
268
|
-
osolver='
|
|
268
|
+
osolver='mgh', oadapt=False, odcalls=False, oexhaust=False,
|
|
269
269
|
ominz=False, onodisj=False, opuresat=False, ounsorted=False,
|
|
270
270
|
otrim=False, weighted=False, verbose=0):
|
|
271
271
|
"""
|
|
@@ -538,7 +538,7 @@ def parse_options():
|
|
|
538
538
|
ominz = False
|
|
539
539
|
nodisj = False
|
|
540
540
|
psolver = 'cd19'
|
|
541
|
-
osolver = '
|
|
541
|
+
osolver = 'mgh'
|
|
542
542
|
ppuresat = False
|
|
543
543
|
opuresat = False
|
|
544
544
|
punsorted = False
|
|
@@ -638,7 +638,7 @@ def usage():
|
|
|
638
638
|
print(' -s, --psolver SAT solver to use [Primer]')
|
|
639
639
|
print(' Available values: cd, cd15, cd19, g3, g41, g42, lgl, mcb, mcm, mpl, m22, mc, mg3, mgh (default = cd19)')
|
|
640
640
|
print(' -S, --osolver SAT solver to use [OptUx]')
|
|
641
|
-
print(' Available values: cd, cd15, cd19, g3, g41, g42, lgl, mcb, mcm, mpl, m22, mc, mg3, mgh (default =
|
|
641
|
+
print(' Available values: cd, cd15, cd19, g3, g41, g42, lgl, mcb, mcm, mpl, m22, mc, mg3, mgh (default = mgh)')
|
|
642
642
|
print(' -t, --ptrim=<int> How many times to trim unsatisfiable cores [Primer]')
|
|
643
643
|
print(' Available values: [0 .. INT_MAX] (default = 0)')
|
|
644
644
|
print(' -T, --otrim=<int> How many times to trim unsatisfiable cores [OptUx]')
|
|
@@ -879,45 +879,26 @@ class Formula(object):
|
|
|
879
879
|
if type(collection) in (tuple, list, set):
|
|
880
880
|
collection = tuple(filter(lambda x: x or x == False, collection))
|
|
881
881
|
|
|
882
|
-
|
|
883
|
-
if
|
|
884
|
-
|
|
885
|
-
items.append((prefix, repr(sorted(collection, key=lambda x: hash(x)))))
|
|
882
|
+
for item in collection:
|
|
883
|
+
if isinstance(item, Iterable):
|
|
884
|
+
items.extend(_flatten(item, prefix=prefix))
|
|
886
885
|
else:
|
|
887
|
-
|
|
888
|
-
if _hashable(item):
|
|
889
|
-
# it is a hashable iterable; it is better to sort it
|
|
890
|
-
if isinstance(item, Iterable):
|
|
891
|
-
item = sorted(item, key=lambda x: hash(x))
|
|
892
|
-
|
|
893
|
-
items.append((prefix, repr(item)))
|
|
894
|
-
elif isinstance(item, Iterable):
|
|
895
|
-
items.extend(_flatten(item, prefix=prefix))
|
|
896
|
-
else:
|
|
897
|
-
raise FormulaError('No key can be computed for this formula object')
|
|
898
|
-
elif collection:
|
|
899
|
-
items.extend(_flatten(collection[0], prefix=prefix))
|
|
886
|
+
items.append((prefix, item))
|
|
900
887
|
|
|
901
888
|
# next, checking if it is a dictionary
|
|
902
889
|
elif isinstance(collection, dict):
|
|
903
890
|
for key in collection.keys():
|
|
904
891
|
value = collection[key]
|
|
905
892
|
new_key = prefix + sep + key if prefix else key
|
|
906
|
-
if value and
|
|
907
|
-
|
|
908
|
-
if isinstance(value, Iterable):
|
|
909
|
-
value = sorted(value, key=lambda x: hash(x))
|
|
910
|
-
|
|
911
|
-
items.append((new_key, repr(value)))
|
|
912
|
-
elif isinstance(value, Iterable):
|
|
913
|
-
if value:
|
|
914
|
-
items.extend(_flatten(value, new_key, sep=sep))
|
|
893
|
+
if isinstance(value, Iterable) and value:
|
|
894
|
+
items.extend(_flatten(value, prefix=new_key, sep=sep))
|
|
915
895
|
else:
|
|
916
|
-
|
|
896
|
+
|
|
897
|
+
items.append((new_key, value))
|
|
917
898
|
|
|
918
899
|
# finally, it is a simple non-empty object
|
|
919
900
|
elif collection or collection == False:
|
|
920
|
-
items.append((prefix,
|
|
901
|
+
items.append((prefix, collection))
|
|
921
902
|
|
|
922
903
|
return items
|
|
923
904
|
|
|
@@ -929,46 +910,68 @@ class Formula(object):
|
|
|
929
910
|
args[0] = tuple(args[0][1:])
|
|
930
911
|
|
|
931
912
|
# flattening all the inputs
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
913
|
+
items = _flatten(args) + _flatten(kwargs)
|
|
914
|
+
ftype, subfs, extra = None, [], []
|
|
915
|
+
|
|
916
|
+
# ignoring everything except subformulas and the type
|
|
917
|
+
for item in items:
|
|
918
|
+
if item[0] == 'type':
|
|
919
|
+
ftype = item
|
|
920
|
+
elif item[0] != 'merge':
|
|
921
|
+
subfs.append(item)
|
|
922
|
+
else:
|
|
923
|
+
extra = [('merge', repr(item[1]))]
|
|
924
|
+
|
|
925
|
+
# the ugly part:
|
|
926
|
+
# reconstructing the key pairs, depending on the type of Formula
|
|
927
|
+
if ftype[1] == FormulaType.ATOM:
|
|
928
|
+
assert len(subfs) == 1, 'A single object is required for an Atom formula'
|
|
929
|
+
subfs[0] = ('object', repr(subfs[0][1]))
|
|
930
|
+
elif ftype[1] == FormulaType.NEG:
|
|
931
|
+
assert len(subfs) == 1, 'A single subformula is required for a Neg formula'
|
|
932
|
+
subfs[0] = ('subformula', id(subfs[0][1]))
|
|
933
|
+
elif ftype[1] == FormulaType.IMPL:
|
|
934
|
+
assert len(subfs) == 2, 'Two subformulas are required for an Implies formula'
|
|
935
|
+
if subfs[0][0] == '' and subfs[1][0] == '':
|
|
936
|
+
subfs[0] = ('left', id(subfs[0][1]))
|
|
937
|
+
subfs[1] = ('right', id(subfs[1][1]))
|
|
938
|
+
elif subfs[1][0] == 'left':
|
|
939
|
+
subfs[0] = ('right', id(subfs[0][1]))
|
|
940
|
+
elif subfs[1][0] == 'right':
|
|
941
|
+
subfs[0] = ('left', id(subfs[0][1]))
|
|
942
|
+
elif ftype[1] == FormulaType.ITE:
|
|
943
|
+
assert len(subfs) == 3, 'Three subformulas are required for an ITE formula'
|
|
944
|
+
if subfs[0][0] == '' and subfs[1][0] == '' and subfs[2][0] == '':
|
|
945
|
+
subfs[0] = ('cond', id(subfs[0][1]))
|
|
946
|
+
subfs[1] = ('cons1', id(subfs[1][1]))
|
|
947
|
+
subfs[2] = ('cons2', id(subfs[2][1]))
|
|
948
|
+
elif subfs[0][0] == subfs[1][0] == '':
|
|
949
|
+
if subfs[2][0] == 'cond':
|
|
950
|
+
subfs[0] = ('cons1', id(subfs[0][1]))
|
|
951
|
+
subfs[1] = ('cons2', id(subfs[1][1]))
|
|
952
|
+
elif subfs[2][0] == 'cons1':
|
|
953
|
+
subfs[0] = ('cond', id(subfs[0][1]))
|
|
954
|
+
subfs[1] = ('cons2', id(subfs[1][1]))
|
|
955
|
+
elif subfs[2][0] == 'cons2':
|
|
956
|
+
subfs[0] = ('cond', id(subfs[0][1]))
|
|
957
|
+
subfs[1] = ('cons1', id(subfs[1][1]))
|
|
958
|
+
elif subfs[0] == '':
|
|
959
|
+
if 'cond' not in (subfs[1][0], subfs[2][0]):
|
|
960
|
+
subfs[0] = ('cond', id(subfs[0][0]))
|
|
961
|
+
elif 'cons1' not in (subfs[1][0], subfs[2][0]):
|
|
962
|
+
subfs[0] = ('cons1', id(subfs[0][0]))
|
|
963
|
+
elif 'cons2' not in (subfs[1][0], subfs[2][0]):
|
|
964
|
+
subfs[0] = ('cons2', id(subfs[0][0]))
|
|
965
|
+
else:
|
|
966
|
+
# these are commutative connectives; we need to sort the arguments
|
|
967
|
+
assert len(subfs) >= 1, 'At least one subformula is required for an And/Equals/Or/XOr formula'
|
|
968
|
+
subfs = sorted(map(lambda p: (p[0], repr(id(p[1]))), subfs))
|
|
969
|
+
|
|
970
|
+
if not extra:
|
|
971
|
+
extra = [('merge', repr(False))]
|
|
972
|
+
|
|
973
|
+
# the key is a string combining all the parts
|
|
974
|
+
return ' '.join([f'{repr(p[0])}:{repr(p[1])}' for p in [ftype] + subfs + extra])
|
|
972
975
|
|
|
973
976
|
def __hash__(self):
|
|
974
977
|
"""
|
|
@@ -1126,7 +1129,7 @@ class Formula(object):
|
|
|
1126
1129
|
b)``.
|
|
1127
1130
|
"""
|
|
1128
1131
|
|
|
1129
|
-
return XOr(self, other)
|
|
1132
|
+
return XOr(self, other, merge=True)
|
|
1130
1133
|
|
|
1131
1134
|
def __ixor__(self, other):
|
|
1132
1135
|
"""
|
|
@@ -1135,7 +1138,7 @@ class Formula(object):
|
|
|
1135
1138
|
``a`` to a new object ``XOr(a, b)``.
|
|
1136
1139
|
"""
|
|
1137
1140
|
|
|
1138
|
-
return XOr(self, other)
|
|
1141
|
+
return XOr(self, other, merge=True)
|
|
1139
1142
|
|
|
1140
1143
|
def __iter__(self):
|
|
1141
1144
|
"""
|
|
@@ -1547,7 +1550,7 @@ class And(Formula):
|
|
|
1547
1550
|
"And[And[Atom('x'), Atom('y')], Atom('z')]"
|
|
1548
1551
|
>>> repr(a2)
|
|
1549
1552
|
"And[Atom('x'), Atom('y'), Atom('z')]"
|
|
1550
|
-
>>> repr(
|
|
1553
|
+
>>> repr(a3)
|
|
1551
1554
|
"And[Atom('x'), Atom('y'), Atom('z')]"
|
|
1552
1555
|
>>>
|
|
1553
1556
|
>>> id(a1) == id(a2)
|
|
@@ -2648,8 +2651,9 @@ class XOr(Formula):
|
|
|
2648
2651
|
def __init__(self, *args, **kwargs):
|
|
2649
2652
|
"""
|
|
2650
2653
|
Initialiser. Expects a list of arguments signifying the operands
|
|
2651
|
-
of the
|
|
2652
|
-
argument ``merge=True``, which will enable merging
|
|
2654
|
+
of the exclusive disjunction. Additionally, a user may set a
|
|
2655
|
+
keyword argument ``merge=True``, which will enable merging
|
|
2656
|
+
sub-operands.
|
|
2653
2657
|
"""
|
|
2654
2658
|
|
|
2655
2659
|
super(XOr, self).__init__(type=FormulaType.XOR)
|
|
@@ -2663,7 +2667,7 @@ class XOr(Formula):
|
|
|
2663
2667
|
self.merged = False
|
|
2664
2668
|
|
|
2665
2669
|
if len(self.subformulas) < 2:
|
|
2666
|
-
raise FormulaError('
|
|
2670
|
+
raise FormulaError('XOr requires at least 2 arguments')
|
|
2667
2671
|
|
|
2668
2672
|
def __del__(self):
|
|
2669
2673
|
"""
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from pysat.formula import *
|
|
2
|
+
from itertools import permutations
|
|
3
|
+
|
|
4
|
+
def test_atom_uniqueness():
|
|
5
|
+
x1, x2 = Atom('x'), Atom(object='x') # same atom
|
|
6
|
+
z = Atom('z') # a different atom
|
|
7
|
+
|
|
8
|
+
assert x1 is x2, 'Atoms should be the same object'
|
|
9
|
+
assert x1 is not z, 'Atoms should be different objects'
|
|
10
|
+
|
|
11
|
+
def test_2and_uniqueness():
|
|
12
|
+
x1, x2 = Atom('x'), Atom('x') # same atom
|
|
13
|
+
y = Atom('y') # a different atom
|
|
14
|
+
|
|
15
|
+
a = And(x1, y)
|
|
16
|
+
b = And(y, x1)
|
|
17
|
+
c = And(x2, y)
|
|
18
|
+
d = And(y, x2)
|
|
19
|
+
|
|
20
|
+
assert id(a) == id(b) == id(c) == id(d), 'All 2-and\'s should be the same object'
|
|
21
|
+
|
|
22
|
+
def test_3and_uniqueness():
|
|
23
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
24
|
+
|
|
25
|
+
a = And(x, y, z)
|
|
26
|
+
|
|
27
|
+
for comb in permutations([x, y, z]):
|
|
28
|
+
assert And(*comb) is a, 'All 3-and\'s should be the same object'
|
|
29
|
+
assert And(comb) is a, 'All 3-and\'s should be the same object'
|
|
30
|
+
|
|
31
|
+
def test_3or_uniqueness():
|
|
32
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
33
|
+
|
|
34
|
+
a = Or(x, y, z)
|
|
35
|
+
|
|
36
|
+
for comb in permutations([x, y, z]):
|
|
37
|
+
assert Or(*comb) is a, 'All 3-and\'s should be the same object'
|
|
38
|
+
assert Or(comb) is a, 'All 3-and\'s should be the same object'
|
|
39
|
+
|
|
40
|
+
def test_impl_uniqueness():
|
|
41
|
+
x, y = Atom('x'), Atom('y')
|
|
42
|
+
|
|
43
|
+
a = x >> y
|
|
44
|
+
b = y >> x
|
|
45
|
+
|
|
46
|
+
a2 = Implies(x, y)
|
|
47
|
+
|
|
48
|
+
assert a is a2, 'Non-unique implication is detected'
|
|
49
|
+
assert a is not b, 'Implication is not commutative'
|
|
50
|
+
|
|
51
|
+
def test_ite_uniqueness():
|
|
52
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
53
|
+
|
|
54
|
+
a = ITE(x, y, z)
|
|
55
|
+
|
|
56
|
+
for comb in permutations([x, y, z]):
|
|
57
|
+
if comb == (x, y, z):
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
assert ITE(*comb) is not a, 'ITE is not commutative'
|
|
61
|
+
|
|
62
|
+
def test_xor_uniqueness():
|
|
63
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
64
|
+
|
|
65
|
+
a = XOr(x, y, z, merge=True)
|
|
66
|
+
b = XOr(x, y, z, merge=False)
|
|
67
|
+
|
|
68
|
+
for comb in permutations([x, y, z]):
|
|
69
|
+
assert XOr(*comb, merge=True) is a, 'All 3-xor\'s should be the same object'
|
|
70
|
+
|
|
71
|
+
for comb in permutations([x, y, z]):
|
|
72
|
+
assert XOr(*comb, merge=False) is b, 'All 3-xor\'s should be the same object'
|
|
73
|
+
assert XOr(*comb) is b, 'All 3-xor\'s should be the same object'
|
|
74
|
+
|
|
75
|
+
def test_equals_uniqueness():
|
|
76
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
77
|
+
|
|
78
|
+
a = Equals(x, y, z, merge=True)
|
|
79
|
+
b = Equals(x, y, z, merge=False)
|
|
80
|
+
|
|
81
|
+
for comb in permutations([x, y, z]):
|
|
82
|
+
assert Equals(*comb, merge=True) is a, 'All 3-equality\'s should be the same object'
|
|
83
|
+
|
|
84
|
+
for comb in permutations([x, y, z]):
|
|
85
|
+
assert Equals(*comb, merge=False) is b, 'All 3-equality\'s should be the same object'
|
|
86
|
+
assert Equals(*comb) is b, 'All 3-equality\'s should be the same object'
|
|
87
|
+
|
|
88
|
+
def test_complex():
|
|
89
|
+
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
90
|
+
|
|
91
|
+
f1 = XOr(x, y, z, merge=False)
|
|
92
|
+
g1 = Or(f1, z, x, merge=True)
|
|
93
|
+
h1 = And(y, g1, x, merge=True)
|
|
94
|
+
|
|
95
|
+
f2 = XOr(z, y, x, merge=False)
|
|
96
|
+
g2 = Or(x, f2, z, merge=True)
|
|
97
|
+
h2 = And(x, g2, y, merge=True)
|
|
98
|
+
|
|
99
|
+
assert f1 is f2, 'Complex uniqueness fail: step 1'
|
|
100
|
+
assert g1 is g2, 'Complex uniqueness fail: step 2'
|
|
101
|
+
assert h1 is h2, 'Complex uniqueness fail: step 3'
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from pysat.formula import *
|
|
2
|
-
from itertools import permutations
|
|
3
|
-
|
|
4
|
-
def test_atom_uniqueness():
|
|
5
|
-
x1, x2 = Atom('x'), Atom('x') # same atom
|
|
6
|
-
z = Atom('z') # a different atom
|
|
7
|
-
|
|
8
|
-
assert x1 is x2, 'Atoms should be the same object'
|
|
9
|
-
assert x1 is not z, 'Atoms should be different objects'
|
|
10
|
-
|
|
11
|
-
def test_2and_uniqueness():
|
|
12
|
-
x1, x2 = Atom('x'), Atom('x') # same atom
|
|
13
|
-
y = Atom('y') # a different atom
|
|
14
|
-
|
|
15
|
-
a = And(x1, y)
|
|
16
|
-
b = And(y, x1)
|
|
17
|
-
c = And(x2, y)
|
|
18
|
-
d = And(y, x2)
|
|
19
|
-
|
|
20
|
-
assert id(a) == id(b) == id(c) == id(d), 'All 2-and\'s should be the same object'
|
|
21
|
-
|
|
22
|
-
def test_3and_uniqueness():
|
|
23
|
-
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
24
|
-
|
|
25
|
-
a = And(x, y, z)
|
|
26
|
-
|
|
27
|
-
for comb in permutations([x, y, z]):
|
|
28
|
-
assert And(*comb) is a, 'All 3-and\'s should be the same object'
|
|
29
|
-
assert And(comb) is a, 'All 3-and\'s should be the same object'
|
|
30
|
-
|
|
31
|
-
def test_3or_uniqueness():
|
|
32
|
-
x, y, z = Atom('x'), Atom('y'), Atom('z')
|
|
33
|
-
|
|
34
|
-
a = Or(x, y, z)
|
|
35
|
-
|
|
36
|
-
for comb in permutations([x, y, z]):
|
|
37
|
-
assert Or(*comb) is a, 'All 3-and\'s should be the same object'
|
|
38
|
-
assert Or(comb) is a, 'All 3-and\'s should be the same object'
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|