python-sat 1.9.dev7__cp313-cp313-win_amd64.whl → 1.9.dev12__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.

Potentially problematic release.


This version of python-sat might be problematic. Click here for more details.

Files changed (26) hide show
  1. pycard.cp313-win_amd64.pyd +0 -0
  2. pyformula.cp313-win_amd64.pyd +0 -0
  3. pysat/__init__.py +1 -1
  4. pysat/examples/rc2.py +6 -4
  5. pysat/formula.py +224 -106
  6. pysolvers.cp313-win_amd64.pyd +0 -0
  7. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/rc2.py +6 -4
  8. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev12.dist-info}/METADATA +1 -1
  9. python_sat-1.9.dev12.dist-info/RECORD +50 -0
  10. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev12.dist-info}/WHEEL +1 -1
  11. python_sat-1.9.dev7.dist-info/RECORD +0 -50
  12. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/approxmc.py +0 -0
  13. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/bbscan.py +0 -0
  14. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/bica.py +0 -0
  15. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/fm.py +0 -0
  16. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/genhard.py +0 -0
  17. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/lbx.py +0 -0
  18. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/lsu.py +0 -0
  19. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/mcsls.py +0 -0
  20. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/models.py +0 -0
  21. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/musx.py +0 -0
  22. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/optux.py +0 -0
  23. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/primer.py +0 -0
  24. {python_sat-1.9.dev7.data → python_sat-1.9.dev12.data}/scripts/unigen.py +0 -0
  25. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev12.dist-info}/licenses/LICENSE.txt +0 -0
  26. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev12.dist-info}/top_level.txt +0 -0
Binary file
Binary file
pysat/__init__.py CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  # current version
12
12
  #==============================================================================
13
- VERSION = (1, 9, 'dev', 7)
13
+ VERSION = (1, 9, 'dev', 12)
14
14
 
15
15
 
16
16
  # PEP440 Format
pysat/examples/rc2.py CHANGED
@@ -134,7 +134,6 @@ from __future__ import print_function
134
134
  import bisect
135
135
  import collections
136
136
  import getopt
137
- import itertools
138
137
  from math import copysign
139
138
  import os
140
139
  from pysat.formula import CNFPlus, WCNFPlus, IDPool
@@ -740,9 +739,12 @@ class RC2(object):
740
739
  self.minw = min(map(lambda l: self.wght[l], self.core))
741
740
 
742
741
  # dividing the core into two parts
743
- iter1, iter2 = itertools.tee(self.core)
744
- self.core_sels = list(l for l in iter1 if l in self.sels_set)
745
- self.core_sums = list(l for l in iter2 if l not in self.sels_set)
742
+ self.core_sels, self.core_sums = [], []
743
+ for l in self.core:
744
+ if l in self.sels_set:
745
+ self.core_sels.append(l)
746
+ else:
747
+ self.core_sums.append(l)
746
748
 
747
749
  def process_core(self):
748
750
  """
pysat/formula.py CHANGED
@@ -810,6 +810,13 @@ class Formula(object):
810
810
  :type type: :class:`FormulaType`
811
811
  """
812
812
 
813
+ # Formula.__new__ may return an existing structurally identical
814
+ # formula; by default, Python still invokes __init__ in that case,
815
+ # which is harmful; if an identical object exists, we should
816
+ # immediately return
817
+ if hasattr(self, 'type'):
818
+ return
819
+
813
820
  assert 'type' in kwargs, 'No \'type\' of the formula is provided'
814
821
  self.type = kwargs['type']
815
822
 
@@ -883,11 +890,11 @@ class Formula(object):
883
890
  @staticmethod
884
891
  def _get_key(*args, **kwargs):
885
892
  """
886
- The method is used to extract and return a list of attributes to
887
- serve as a key associated with the formula requested by a user.
888
- The flattened result will contain string, i.e. ``repr()``,
889
- representation of all the attributes. The method is meant to be
890
- internal and not to be used by formula users.
893
+ The method is used to extract and return an immutable structural
894
+ key associated with the formula requested by a user. The key is
895
+ composed of tuples, frozensets, and scalar values rather than
896
+ string representations. The method is meant to be internal and
897
+ not to be used by formula users.
891
898
  """
892
899
 
893
900
  def _hashable(entity):
@@ -918,7 +925,6 @@ class Formula(object):
918
925
  if isinstance(value, Iterable) and value:
919
926
  items.extend(_flatten(value, prefix=new_key, sep=sep))
920
927
  else:
921
-
922
928
  items.append((new_key, value))
923
929
 
924
930
  # finally, it is a simple non-empty object
@@ -945,58 +951,136 @@ class Formula(object):
945
951
  elif item[0] != 'merge':
946
952
  subfs.append(item)
947
953
  else:
948
- extra = [('merge', repr(item[1]))]
954
+ extra = [('merge', item[1])]
955
+
956
+ def _object_key(obj):
957
+ """
958
+ Get a hashable key for an atom object.
959
+ """
960
+
961
+ if type(obj) in (bool, int, float, str, bytes, type(None)):
962
+ return ('val', type(obj), obj)
963
+ if type(obj) in (tuple, list):
964
+ return ('seq', tuple(_object_key(item) for item in obj))
965
+ if type(obj) in (set, frozenset):
966
+ return ('set', frozenset(_object_key(item) for item in obj))
967
+ if isinstance(obj, dict):
968
+ return ('map', frozenset((_object_key(key), _object_key(val)) for key, val in obj.items()))
969
+ try:
970
+ hash(obj)
971
+ except TypeError:
972
+ return ('identity', type(obj), id(obj))
973
+ return ('obj', type(obj), obj)
974
+
975
+ def _formula_key_uncached(form):
976
+ """
977
+ Get a structural key without a formula's merge flag.
978
+ """
979
+
980
+ if not isinstance(form, Formula):
981
+ return ('identity', type(form), id(form))
982
+
983
+ if form.type == FormulaType.CNF:
984
+ # CNF and CNFPlus are mutable containers and deliberately
985
+ # bypass Formula's unique-object constructor; using their
986
+ # object identity as it looks like the cheapest option
987
+ return ('cnf-object', type(form), id(form))
988
+
989
+ if form.type == FormulaType.ATOM:
990
+ return (FormulaType.ATOM, _object_key(form.object))
991
+ if form.type == FormulaType.NEG:
992
+ return (FormulaType.NEG, _formula_key(form.subformula))
993
+ if form.type == FormulaType.IMPL:
994
+ return (FormulaType.IMPL, _formula_key(form.left),
995
+ _formula_key(form.right))
996
+ if form.type == FormulaType.ITE:
997
+ return (FormulaType.ITE, _formula_key(form.cond),
998
+ _formula_key(form.cons1),
999
+ _formula_key(form.cons2))
1000
+
1001
+ counts = collections.Counter(_formula_key(subform) for subform in form.subformulas)
1002
+ return (form.type, frozenset(counts.items()))
1003
+
1004
+ def _formula_key(form):
1005
+ """
1006
+ Get a cached structural key for an immutable formula.
1007
+ """
1008
+
1009
+ if isinstance(form, Formula):
1010
+ key = getattr(form, '_key_cache', None)
1011
+ if key is None:
1012
+ key = _formula_key_uncached(form)
1013
+ form._key_cache = key
1014
+
1015
+ return key
1016
+
1017
+ return _formula_key_uncached(form)
1018
+
1019
+ def _merged_operands(operands, formula_type):
1020
+ """Flatten same-type operands for a merged connective."""
1021
+ result = []
1022
+ for operand in operands:
1023
+ if isinstance(operand, Formula) and operand.type == formula_type:
1024
+ result.extend(_merged_operands(operand.subformulas,
1025
+ formula_type))
1026
+ else:
1027
+ result.append(_formula_key(operand))
1028
+ return result
949
1029
 
950
- # the ugly part:
951
- # reconstructing the key pairs, depending on the type of Formula
952
- if ftype[1] == FormulaType.ATOM:
1030
+ # Reconstruct a structural key depending on the Formula type.
1031
+ formula_type = ftype[1]
1032
+ if formula_type == FormulaType.ATOM:
953
1033
  assert len(subfs) == 1, 'A single object is required for an Atom formula'
954
- subfs[0] = ('object', repr(subfs[0][1]))
955
- elif ftype[1] == FormulaType.NEG:
1034
+ return (formula_type, _object_key(subfs[0][1]))
1035
+
1036
+ if formula_type == FormulaType.NEG:
956
1037
  assert len(subfs) == 1, 'A single subformula is required for a Neg formula'
957
- subfs[0] = ('subformula', id(subfs[0][1]))
958
- elif ftype[1] == FormulaType.IMPL:
1038
+ return (formula_type, _formula_key(subfs[0][1]))
1039
+
1040
+ if formula_type == FormulaType.IMPL:
959
1041
  assert len(subfs) == 2, 'Two subformulas are required for an Implies formula'
960
1042
  if subfs[0][0] == '' and subfs[1][0] == '':
961
- subfs[0] = ('left', id(subfs[0][1]))
962
- subfs[1] = ('right', id(subfs[1][1]))
1043
+ operands = [('left', subfs[0][1]), ('right', subfs[1][1])]
963
1044
  elif subfs[1][0] == 'left':
964
- subfs[0] = ('right', id(subfs[0][1]))
1045
+ operands = [('right', subfs[0][1]), subfs[1]]
965
1046
  elif subfs[1][0] == 'right':
966
- subfs[0] = ('left', id(subfs[0][1]))
967
- elif ftype[1] == FormulaType.ITE:
1047
+ operands = [('left', subfs[0][1]), subfs[1]]
1048
+ else:
1049
+ operands = subfs
1050
+ role_order = {'left': 0, 'right': 1}
1051
+ return (formula_type, tuple( (label, _formula_key(value)) for \
1052
+ label, value in sorted(operands,
1053
+ key=lambda pair: role_order[pair[0]])))
1054
+
1055
+ if formula_type == FormulaType.ITE:
968
1056
  assert len(subfs) == 3, 'Three subformulas are required for an ITE formula'
969
- if subfs[0][0] == '' and subfs[1][0] == '' and subfs[2][0] == '':
970
- subfs[0] = ('cond', id(subfs[0][1]))
971
- subfs[1] = ('cons1', id(subfs[1][1]))
972
- subfs[2] = ('cons2', id(subfs[2][1]))
1057
+ if all(item[0] == '' for item in subfs):
1058
+ subfs = [('cond', subfs[0][1]), ('cons1', subfs[1][1]), ('cons2', subfs[2][1])]
973
1059
  elif subfs[0][0] == subfs[1][0] == '':
974
- if subfs[2][0] == 'cond':
975
- subfs[0] = ('cons1', id(subfs[0][1]))
976
- subfs[1] = ('cons2', id(subfs[1][1]))
977
- elif subfs[2][0] == 'cons1':
978
- subfs[0] = ('cond', id(subfs[0][1]))
979
- subfs[1] = ('cons2', id(subfs[1][1]))
980
- elif subfs[2][0] == 'cons2':
981
- subfs[0] = ('cond', id(subfs[0][1]))
982
- subfs[1] = ('cons1', id(subfs[1][1]))
983
- elif subfs[0] == '':
984
- if 'cond' not in (subfs[1][0], subfs[2][0]):
985
- subfs[0] = ('cond', id(subfs[0][0]))
986
- elif 'cons1' not in (subfs[1][0], subfs[2][0]):
987
- subfs[0] = ('cons1', id(subfs[0][0]))
988
- elif 'cons2' not in (subfs[1][0], subfs[2][0]):
989
- subfs[0] = ('cons2', id(subfs[0][0]))
1060
+ role = subfs[2][0]
1061
+ missing = [r for r in ('cond', 'cons1', 'cons2') if r != role]
1062
+ subfs = [(missing[0], subfs[0][1]), (missing[1], subfs[1][1]), subfs[2]]
1063
+ elif subfs[0][0] == '':
1064
+ roles = {item[0] for item in subfs[1:]}
1065
+ missing = next(r for r in ('cond', 'cons1', 'cons2') if r not in roles)
1066
+ subfs[0] = (missing, subfs[0][1])
1067
+
1068
+ role_order = {'cond': 0, 'cons1': 1, 'cons2': 2}
1069
+ return (formula_type, tuple((label, _formula_key(value)) for \
1070
+ label, value in sorted(subfs,
1071
+ key=lambda pair: role_order[pair[0]])))
1072
+
1073
+ # these are commutative connectives; representing operands as a
1074
+ # multiset so that argument order is irrelevant while duplicate
1075
+ # operands remain significant; a merged connective also flattens nested operands.
1076
+ assert len(subfs) >= 1, 'At least one subformula is required for an And/Equals/Or/XOr formula'
1077
+ merge = dict(extra).get('merge', False)
1078
+ operands = [value for _, value in subfs]
1079
+ if merge:
1080
+ operands = _merged_operands(operands, formula_type)
990
1081
  else:
991
- # these are commutative connectives; we need to sort the arguments
992
- assert len(subfs) >= 1, 'At least one subformula is required for an And/Equals/Or/XOr formula'
993
- subfs = sorted(map(lambda p: (p[0], repr(id(p[1]))), subfs))
994
-
995
- if not extra:
996
- extra = [('merge', repr(False))]
997
-
998
- # the key is a string combining all the parts
999
- return ' '.join([f'{repr(p[0])}:{repr(p[1])}' for p in [ftype] + subfs + extra])
1082
+ operands = [_formula_key(operand) for operand in operands]
1083
+ return (formula_type, frozenset(collections.Counter(operands).items()), merge)
1000
1084
 
1001
1085
  def __hash__(self):
1002
1086
  """
@@ -1708,50 +1792,83 @@ class And(Formula):
1708
1792
 
1709
1793
  def _clausify(self, name_required=True):
1710
1794
  """
1711
- Conjuction clausification.
1795
+ Conjunction clausification.
1712
1796
 
1713
1797
  If ``name_required`` is ``False``, the method recursively encodes
1714
- the subformulas and populates self's clauses with unit clauses,
1715
- each containing the auxiliary "name" of the corresponding
1716
- subformula, thus representing their conjunction.
1717
-
1718
- If ``name_required`` is set to ``True``, the method encodes the
1719
- conjunction using the standard logic: :math:`x \\equiv
1720
- \\bigwedge{y_i}`, if :math:`x` is the new auxiliary variable
1721
- encoding ``self`` and :math:`y_i` is the auxiliary variable
1722
- representing :math:`i`'s subformula.
1798
+ the subformulas expanding self's list of clauses and also
1799
+ populates self's clauses with unit clauses, each containing the
1800
+ auxiliary "name" of the corresponding subformula, thus
1801
+ representing their conjunction. However, :class:`CNF` formulas
1802
+ are expanded without introducing an intermediate Boolean name -
1803
+ instead, they contribute their clausal representations to the
1804
+ list of self's clauses unchanged.
1805
+
1806
+ If ``name_required`` is set to ``True``, the method introduces one
1807
+ name for the complete conjunction and encodes the equivalence
1808
+ between that name and the collected clauses.
1723
1809
 
1724
1810
  :param name_required: whether or not a Tseitin variable is needed
1725
- :param name_required: bool
1811
+ :type name_required: bool
1726
1812
  """
1727
1813
 
1728
1814
  save_clauses = bool(self.clauses)
1729
1815
 
1730
1816
  if not self.clauses:
1731
- # first, recursively encoding subformulas
1817
+ # recursively collect a clausal representation; CNF objects are
1818
+ # already clausal, so they do not need a Boolean name at this
1819
+ # level
1732
1820
  for sub in self.subformulas:
1733
- sub._clausify(name_required=True)
1734
-
1735
- # adding unit clauses
1736
- self.clauses.append([sub.name])
1821
+ if type(sub) is CNF:
1822
+ sub._clausify(name_required=False)
1823
+ self.clauses.extend(cl.copy() for cl in sub.clauses)
1824
+ else:
1825
+ sub._clausify(name_required=True)
1826
+ self.clauses.append([sub.name])
1737
1827
 
1738
- # introducing a new name for this formula if required
1828
+ # introducing a name is needed only when this conjunction is itself
1829
+ # used by another connective; encode each non-unit clause with its own
1830
+ # selector, then encode the conjunction of those selectors with the
1831
+ # single name for this `And` formula
1739
1832
  if name_required and not self.name:
1740
- if save_clauses:
1741
- self.encoded = [clause.copy() for clause in self.clauses]
1742
- else:
1743
- self.encoded = self.clauses
1744
- self.clauses = []
1833
+ self.encoded, enclits = [], []
1745
1834
 
1746
- self.name = Formula._vpool[Formula._context].id(self)
1835
+ for cl in self.clauses:
1836
+ auxv = cl[0]
1837
+ if len(cl) > 1:
1838
+ auxv = Formula._vpool[Formula._context].id()
1839
+
1840
+ # direct implication
1841
+ for l in cl:
1842
+ self.encoded.append([-l, auxv])
1843
+
1844
+ # opposite implication
1845
+ self.encoded.append(cl + [-auxv])
1747
1846
 
1748
- cl = [self.name] # final clause (converse implication)
1749
- for i in range(len(self.encoded)):
1750
- cl.append(-self.encoded[i][0]) # updating final clause
1751
- self.encoded[i].append(-self.name) # updating direct implication
1847
+ # literals representing the clauses
1848
+ enclits.append(auxv)
1752
1849
 
1753
- # adding final clause
1754
- self.encoded.append(cl)
1850
+ # encoding the conjunction
1851
+ if len(enclits) > 1:
1852
+ self.name = Formula._vpool[Formula._context].id(self)
1853
+
1854
+ for lit in enclits:
1855
+ self.encoded.append([lit, -self.name])
1856
+ self.encoded.append([self.name] + [-lit for lit in enclits])
1857
+ elif len(enclits) == 1: # single clause - nothing left to encode
1858
+ self.name = enclits[0] # existing variable
1859
+
1860
+ # connecting it to the `And` object as its name
1861
+ Formula._vpool[Formula._context].obj2id[self] = self.name
1862
+ if self.name not in Formula._vpool[Formula._context].id2obj:
1863
+ Formula._vpool[Formula._context].id2obj[self.name] = self
1864
+ else:
1865
+ self.name = PYSAT_TRUE.name
1866
+
1867
+ # preserve clauses that existed before this call;
1868
+ # they are still needed if the same formula is later iterated as
1869
+ # an outermost formula
1870
+ if not save_clauses:
1871
+ self.clauses = []
1755
1872
 
1756
1873
  def _atoms(self, dest):
1757
1874
  """
@@ -1947,18 +2064,18 @@ class Or(Formula):
1947
2064
  Disjunction clausification.
1948
2065
 
1949
2066
  If ``name_required`` is ``False``, the method recursively encodes
1950
- the subformulas and populates self's clauses with unit clauses,
1951
- each containing the auxiliary "name" of the corresponding
1952
- subformula, thus representing their conjunction.
2067
+ the subformulas and populates self's clauses with a unit clause
2068
+ containing the auxiliary "name" of each corresponding subformula,
2069
+ thus representing their disjunction.
1953
2070
 
1954
2071
  If ``name_required`` is set to ``True``, the method encodes the
1955
- conjunction using the standard logic: :math:`x \\equiv
2072
+ disjunction using the standard logic: :math:`x \\equiv
1956
2073
  \\bigvee{y_i}`, if :math:`x` is the new auxiliary variable
1957
2074
  encoding ``self`` and :math:`y_i` is the auxiliary variable
1958
2075
  representing :math:`i`'s subformula.
1959
2076
 
1960
2077
  :param name_required: whether or not a Tseitin variable is needed
1961
- :param name_required: bool
2078
+ :type name_required: bool
1962
2079
  """
1963
2080
 
1964
2081
  save_clauses = bool(self.clauses)
@@ -2136,7 +2253,7 @@ class Neg(Formula):
2136
2253
  is equal to the negation of subformula's name.
2137
2254
 
2138
2255
  :param name_required: whether or not a Tseitin variable is needed
2139
- :param name_required: bool
2256
+ :type name_required: bool
2140
2257
  """
2141
2258
 
2142
2259
  if not self.clauses:
@@ -2307,7 +2424,7 @@ class Implies(Formula):
2307
2424
 
2308
2425
  If ``name_required`` is ``False``, the method recursively encodes
2309
2426
  the left and right subformulas giving them names, say, :math:`x`
2310
- and :math:`y` respectively and the populates self's clauses with a
2427
+ and :math:`y` respectively, and populates self's clauses with a
2311
2428
  single binary clause :math:`(\\neg{x}\\lor y)`.
2312
2429
 
2313
2430
  If ``name_required`` is set to ``True``, the method removes this
@@ -2315,7 +2432,7 @@ class Implies(Formula):
2315
2432
  Tseitin-encoding it, i.e. :math:`n \\equiv (\\neg{x}\\lor y)`.
2316
2433
 
2317
2434
  :param name_required: whether or not a Tseitin variable is needed
2318
- :param name_required: bool
2435
+ :type name_required: bool
2319
2436
  """
2320
2437
 
2321
2438
  save_clauses = bool(self.clauses)
@@ -2407,7 +2524,7 @@ class Equals(Formula):
2407
2524
  >>> from pysat.formula import *
2408
2525
  >>> a1 = Equals(Equals(Atom('x'), Atom('y')), Atom('z'))
2409
2526
  >>> a2 = Equals(Equals(Atom('x'), Atom('y')), Atom('z'), merge=True)
2410
- >>> a3 = Atom('x') == Atom('y') == Atom('z')
2527
+ >>> a3 = Atom('x') @ Atom('y') @ Atom('z')
2411
2528
  >>>
2412
2529
  >>> print(a1)
2413
2530
  (x @ y) @ z
@@ -2571,7 +2688,7 @@ class Equals(Formula):
2571
2688
  relating it with the names of subformulas.
2572
2689
 
2573
2690
  :param name_required: whether or not a Tseitin variable is needed
2574
- :param name_required: bool
2691
+ :type name_required: bool
2575
2692
  """
2576
2693
 
2577
2694
  save_clauses = bool(self.clauses)
@@ -2652,13 +2769,12 @@ class XOr(Formula):
2652
2769
 
2653
2770
  If an additional Boolean keyword argument ``merge`` is provided set to
2654
2771
  ``True``, the toolkit will try to flatten the current :class:`XOr`
2655
- formula merging its *equivalence* sub-operands into the list of
2656
- operands. For example, if ``XOr(XOr(x, y), z, merge=True)`` is called,
2657
- a new Formula object will be created with two operands: ``XOr(x, y)``
2658
- and ``z``, followed by merging ``x`` and ``y`` into the list of
2659
- root-level ``XOr``. This will result in a formula ``XOr(x, y, z)``.
2660
- Merging sub-operands is disabled by default if bitwise operations are
2661
- used to create ``XOr`` formulas.
2772
+ formula merging its *exclusive-disjunction* sub-operands into the
2773
+ list of operands. For example, if ``XOr(XOr(x, y), z, merge=True)`` is
2774
+ called, a new Formula object will be created with two operands:
2775
+ ``XOr(x, y)`` and ``z``, followed by merging ``x`` and ``y`` into the
2776
+ list of root-level ``XOr``. This will result in a formula
2777
+ ``XOr(x, y, z)``. Bitwise ``^`` operations also enable merging.
2662
2778
 
2663
2779
  Example:
2664
2780
 
@@ -2679,8 +2795,8 @@ class XOr(Formula):
2679
2795
  >>> id(a1) == id(a2)
2680
2796
  False
2681
2797
  >>>
2682
- >>> id(a1) == id(a3)
2683
- True # formulas a1 and a3 refer to the same object
2798
+ >>> id(a2) == id(a3)
2799
+ True # formulas a2 and a3 refer to the same object
2684
2800
 
2685
2801
  .. note::
2686
2802
 
@@ -2766,7 +2882,7 @@ class XOr(Formula):
2766
2882
  >>> a = x ^ y ^ z
2767
2883
  >>>
2768
2884
  >>> print(a.simplified(assumptions=[y]))
2769
- ~x ^ z
2885
+ ~(x ^ z)
2770
2886
  >>> print(a.simplified(assumptions=[~y]))
2771
2887
  x ^ z
2772
2888
  """
@@ -2817,7 +2933,7 @@ class XOr(Formula):
2817
2933
  variable for each pair of operands.
2818
2934
 
2819
2935
  :param name_required: whether or not a Tseitin variable is needed
2820
- :param name_required: bool
2936
+ :type name_required: bool
2821
2937
  """
2822
2938
 
2823
2939
  save_clauses = bool(self.clauses)
@@ -2943,7 +3059,7 @@ class ITE(Formula):
2943
3059
  >>> ite = ITE(x, y, z)
2944
3060
  >>>
2945
3061
  >>> print(ite)
2946
- >>> (x >> y) & (~x >> z)
3062
+ (x >> y) & (~x >> z)
2947
3063
  """
2948
3064
 
2949
3065
  def __new__(cls, *args, **kwargs):
@@ -3071,17 +3187,17 @@ class ITE(Formula):
3071
3187
 
3072
3188
  If ``name_required`` is ``False``, the method recursively encodes
3073
3189
  the ``cond``, ``cons1``, and ``cons2`` subformulas giving them
3074
- names, say, :math:`x`, :math:`y`, and :math:`z`, respectivela, and
3075
- the populates self's clauses with two binary clauses
3076
- :math:`(\\neg{x}\\lor y)` and :math:`(x \\lor y)`.
3190
+ names, say, :math:`x`, :math:`y`, and :math:`z`, respectively, and
3191
+ populates self's clauses with two binary clauses
3192
+ :math:`(\\neg{x}\\lor y)` and :math:`(x \\lor z)`.
3077
3193
 
3078
3194
  If ``name_required`` is set to ``True``, the method removes these
3079
3195
  clauses and instead gives a name to the ITE by Tseitin-encoding
3080
3196
  it, i.e. encoding :math:`n \\equiv \\left[(\\neg{x}\\lor
3081
- y)\\land(x\\lor y)\\right]`.
3197
+ y)\\land(x\\lor z)\\right]`.
3082
3198
 
3083
3199
  :param name_required: whether or not a Tseitin variable is needed
3084
- :param name_required: bool
3200
+ :type name_required: bool
3085
3201
  """
3086
3202
 
3087
3203
  save_clauses = bool(self.clauses)
@@ -3136,7 +3252,7 @@ class ITE(Formula):
3136
3252
  """
3137
3253
  Informal representation of the ``ITE`` formula. Returns a string
3138
3254
  representation of the subformulas as two implications connected
3139
- with the conjuction symbol ``' & '``
3255
+ with the conjunction symbol ``' & '``
3140
3256
  """
3141
3257
 
3142
3258
  cons1 = '{0} >> {1}'.format(f'{str(self.cond)}' if self.cond.type in (FormulaType.ATOM, FormulaType.NEG) else f'({str(self.cond)})',
@@ -3898,7 +4014,7 @@ class CNF(Formula, object):
3898
4014
  for lit in enclits:
3899
4015
  clauses.append([-self.name, lit])
3900
4016
  clauses.append([self.name] + [-lit for lit in enclits])
3901
- else: # single clause - nothing left to encode
4017
+ elif len(enclits) == 1: # single clause - nothing left to encode
3902
4018
  self.name = enclits[0] # existing variable
3903
4019
 
3904
4020
  # connecting it to the CNF object as its name
@@ -3907,6 +4023,8 @@ class CNF(Formula, object):
3907
4023
 
3908
4024
  # just in case, marking all ids below self.name as occupied
3909
4025
  Formula._vpool[Formula._context].occupy(1, self.name)
4026
+ else:
4027
+ self.name = PYSAT_TRUE.name
3910
4028
 
3911
4029
  self.encoded = clauses
3912
4030
  self.auxvars = auxvars
Binary file
@@ -134,7 +134,6 @@ from __future__ import print_function
134
134
  import bisect
135
135
  import collections
136
136
  import getopt
137
- import itertools
138
137
  from math import copysign
139
138
  import os
140
139
  from pysat.formula import CNFPlus, WCNFPlus, IDPool
@@ -740,9 +739,12 @@ class RC2(object):
740
739
  self.minw = min(map(lambda l: self.wght[l], self.core))
741
740
 
742
741
  # dividing the core into two parts
743
- iter1, iter2 = itertools.tee(self.core)
744
- self.core_sels = list(l for l in iter1 if l in self.sels_set)
745
- self.core_sums = list(l for l in iter2 if l not in self.sels_set)
742
+ self.core_sels, self.core_sums = [], []
743
+ for l in self.core:
744
+ if l in self.sels_set:
745
+ self.core_sels.append(l)
746
+ else:
747
+ self.core_sums.append(l)
746
748
 
747
749
  def process_core(self):
748
750
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.9.dev7
3
+ Version: 1.9.dev12
4
4
  Summary: A Python library for prototyping with SAT oracles
5
5
  Home-page: https://github.com/pysathq/pysat
6
6
  Author: Alexey Ignatiev, Joao Marques-Silva, Antonio Morgado
@@ -0,0 +1,50 @@
1
+ pycard.cp313-win_amd64.pyd,sha256=D53SVLi3JhMdEfqTkJO1bgTsDVhh_lfdJoB8-XKEIHA,71680
2
+ pyformula.cp313-win_amd64.pyd,sha256=J7eXIRP8RrOdwbynbwkc4oEnMQIP0HsnBDFN3BzaAfI,31232
3
+ pysolvers.cp313-win_amd64.pyd,sha256=sjflLpYHydwda4Y6amRmn0WI66Ui8ZdWe4S_ECq4OYE,3340288
4
+ pysat/__init__.py,sha256=NUV138GbmWkxc-cwJx_fsLTx9ps9VuNoI2fx0C9Pf5Q,681
5
+ pysat/_fileio.py,sha256=pXRGGAaP7U8r3bpn5ShseCSHROXqi7ygaYe6T6QORto,6700
6
+ pysat/_utils.py,sha256=4cv40p70FKvjCTKq8GqzS_jlxF74cp_lojTZSim_qJE,1340
7
+ pysat/card.py,sha256=rav3_t_mCzbLw8SAdXcOh-PNbFtaATVSAJzpbygqiQ4,30066
8
+ pysat/engines.py,sha256=yAYA_PzIGr_uRF85M7kL2bipjpLbY7jdfFKTdY-yW8I,46364
9
+ pysat/formula.py,sha256=zmAceFu7gpvopLWfpXSZVH9jaQY_5FOGt03lrse3X1Y,215477
10
+ pysat/integer.py,sha256=um6FXUzmBHUFlWXNKs0xLh9Jss3jiEin2Er_U41KtkA,90203
11
+ pysat/pb.py,sha256=DMy8UfbbpfJo5cTZul9W1o_mlr-B0lCIEseZjrQYd8A,17816
12
+ pysat/process.py,sha256=8lNbpEKipFZjbQ9DCJPfdL8eZHx-ltNuu7h4geWWdJY,12739
13
+ pysat/solvers.py,sha256=JTZU2O-rrmUKDRNq0vLm0wtXIGsftwhGxxQZdGiij34,277199
14
+ pysat/allies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ pysat/allies/approxmc.py,sha256=LtUss6PiqmgvFwLTe4KUHmhavdzlotRii2UUOSb9gTU,13586
16
+ pysat/allies/unigen.py,sha256=qOGc_WwcIi-AgFSJDBhhY2n6Q6UeYVMpMPuem4-Vf6c,16718
17
+ pysat/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ pysat/examples/bbscan.py,sha256=E4Y5j3Llr0-jIn-RDZIk-f02Sbujg4wX7uysoiFRnLg,22046
19
+ pysat/examples/bica.py,sha256=OGcGQGQnMepCCurwRbygokFgoDkI7eBhjmsYvr3FM1M,27098
20
+ pysat/examples/fm.py,sha256=e_s6wNBstEeoMw9zYyyDRgkE-Hqa902Iy_CxCS961CE,18136
21
+ pysat/examples/genhard.py,sha256=DFXtSVQ4qn78y0-ZMr2D6gBCLizZSzgkvcbDsjqjnKI,19017
22
+ pysat/examples/hitman.py,sha256=vHJEeSfoMQlDD3D3Poofaryv-k_dMH37XoqVXJUUuUg,26360
23
+ pysat/examples/lbx.py,sha256=InMjqY-9UvWKznIXOEwfBsM4spfkduDld6gUkr1jCqo,23249
24
+ pysat/examples/lsu.py,sha256=qyN2TvXG61EtMy-IrX5EYmLPM_iNOhtOkGTY5nHO_zo,16198
25
+ pysat/examples/mcsls.py,sha256=bP47P56OOP_uy0MuFA7TGxMdkAis7gX4E9AEEI0tSec,22093
26
+ pysat/examples/models.py,sha256=cdIR8iOrYu2ibqfcb_kEKXQMCfmFiz7cvZ3y1dur3Qw,5741
27
+ pysat/examples/musx.py,sha256=hswVGkjm95lhOyrtl1e4ouDyNSy-hWvQ05084Xnck9I,10946
28
+ pysat/examples/optux.py,sha256=8eYHO_uhL_4ugb-hRv2s6cnOwTurfqkpbdnK9T4iDtw,27697
29
+ pysat/examples/primer.py,sha256=0OeV9R6mWyIr2BKIitkrfgY3q2XE-sV1ZLSiybGRFXw,23375
30
+ pysat/examples/rc2.py,sha256=7-FuygxAbgNYb9QmKsNhkK5EG5OW8mpHOpoA8GnDs28,76998
31
+ pysat/examples/usage.py,sha256=x9luw6pyKAAndlxAeUWFhS4aLSVmD2t_j_5uA9YddHg,2183
32
+ python_sat-1.9.dev12.data/scripts/approxmc.py,sha256=h6aMnSpIaYXkTMq-tCSzNWwKb0AG-vTH4vuLWGn5Q4s,13958
33
+ python_sat-1.9.dev12.data/scripts/bbscan.py,sha256=xGxklG6Gc_UBaM8QvEJDOtQhEamxAncfsd65E-0JcAc,22696
34
+ python_sat-1.9.dev12.data/scripts/bica.py,sha256=q6fQGsFp1EaaYRZGBsDFOIJPVScr5k42XFskBzW69mA,27776
35
+ python_sat-1.9.dev12.data/scripts/fm.py,sha256=ek1QDsuxiq1zm1PBLbrSXXEE89RP9_DYwVNnyB3eO4s,18650
36
+ python_sat-1.9.dev12.data/scripts/genhard.py,sha256=YswufT272W4xTJrSBlOC2ucJx4RK4ntfRv73rASrx30,19520
37
+ python_sat-1.9.dev12.data/scripts/lbx.py,sha256=rCQ6zH_DXoVjBrzhZHSDJMfP92-hz2JVwh6e4m44AUc,23874
38
+ python_sat-1.9.dev12.data/scripts/lsu.py,sha256=cAATg2x0Cu1LC8KszMctHqywjq7pygkb9vWNBrbUEZs,16681
39
+ python_sat-1.9.dev12.data/scripts/mcsls.py,sha256=cTJQMIO-4iho412wG0JhvhqXWy81U0RQV8wwOgkri3Q,22690
40
+ python_sat-1.9.dev12.data/scripts/models.py,sha256=UmMmklExzyXAIhh-0i038nQb7hTK6CbdV1M6m2GxxSI,5917
41
+ python_sat-1.9.dev12.data/scripts/musx.py,sha256=LwK10YuQ8pIf1TJwp0HKp54O0hdk8zBy3TIfGsF1yW0,11277
42
+ python_sat-1.9.dev12.data/scripts/optux.py,sha256=t20YBZH4_axTkRMapq-DL-fq-9tBybPWo0pkhIyGhDw,28394
43
+ python_sat-1.9.dev12.data/scripts/primer.py,sha256=iE9Vy0XyeySIY-7-L_VMwRahsIVCEmm9k04OhLwDvuw,23982
44
+ python_sat-1.9.dev12.data/scripts/rc2.py,sha256=vvB7GlzssovGtnyk-COK-1bxmPh4zpj8Y7GqQa9dC9U,79020
45
+ python_sat-1.9.dev12.data/scripts/unigen.py,sha256=e-HC2UxWA8MTN90VslkHX1ZlTPjdhI4etzkn6G8YAX4,17140
46
+ python_sat-1.9.dev12.dist-info/licenses/LICENSE.txt,sha256=6QMvEzxqdPXEoiAZUBaZLeLF4hW2S81fjKz_THER0uQ,1109
47
+ python_sat-1.9.dev12.dist-info/METADATA,sha256=sJK6NIR39c2zlQYICi7dM1ZNAHAc91t0iQTGNIBJCUI,1784
48
+ python_sat-1.9.dev12.dist-info/WHEEL,sha256=0LUNoHxLvcpw9db_x0XozE5jW73-_GOAO7fDDJ4Xt4Q,101
49
+ python_sat-1.9.dev12.dist-info/top_level.txt,sha256=0SLg3yVqNpeiqOwFcAo3OxXhqAnflCmb5Fjl6gsl-Do,33
50
+ python_sat-1.9.dev12.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (83.0.0)
2
+ Generator: setuptools (84.0.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp313-cp313-win_amd64
5
5
 
@@ -1,50 +0,0 @@
1
- pycard.cp313-win_amd64.pyd,sha256=7mLtentpGvV6ABZrYrgLQu3LdLh4tQKZE3EVwIlI2fM,71680
2
- pyformula.cp313-win_amd64.pyd,sha256=mYBsZFS_fkmpzy4maUvyjyiF3s7qE88-4BgFCvzUOh0,31232
3
- pysolvers.cp313-win_amd64.pyd,sha256=EBm6zbuUAMxU-omqOSlP7-HGPVpn_as19HM2RSnsct0,3340288
4
- pysat/__init__.py,sha256=4zSEPAX1iKQpFV3wsG_VVidiuVQN4i9k2Q7X-2hFQWw,680
5
- pysat/_fileio.py,sha256=pXRGGAaP7U8r3bpn5ShseCSHROXqi7ygaYe6T6QORto,6700
6
- pysat/_utils.py,sha256=4cv40p70FKvjCTKq8GqzS_jlxF74cp_lojTZSim_qJE,1340
7
- pysat/card.py,sha256=rav3_t_mCzbLw8SAdXcOh-PNbFtaATVSAJzpbygqiQ4,30066
8
- pysat/engines.py,sha256=yAYA_PzIGr_uRF85M7kL2bipjpLbY7jdfFKTdY-yW8I,46364
9
- pysat/formula.py,sha256=tHltOuKQ5L7nefYlKDzPU0fWXol6-YUU1lexihNBRV4,210252
10
- pysat/integer.py,sha256=um6FXUzmBHUFlWXNKs0xLh9Jss3jiEin2Er_U41KtkA,90203
11
- pysat/pb.py,sha256=DMy8UfbbpfJo5cTZul9W1o_mlr-B0lCIEseZjrQYd8A,17816
12
- pysat/process.py,sha256=8lNbpEKipFZjbQ9DCJPfdL8eZHx-ltNuu7h4geWWdJY,12739
13
- pysat/solvers.py,sha256=JTZU2O-rrmUKDRNq0vLm0wtXIGsftwhGxxQZdGiij34,277199
14
- pysat/allies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- pysat/allies/approxmc.py,sha256=LtUss6PiqmgvFwLTe4KUHmhavdzlotRii2UUOSb9gTU,13586
16
- pysat/allies/unigen.py,sha256=qOGc_WwcIi-AgFSJDBhhY2n6Q6UeYVMpMPuem4-Vf6c,16718
17
- pysat/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- pysat/examples/bbscan.py,sha256=E4Y5j3Llr0-jIn-RDZIk-f02Sbujg4wX7uysoiFRnLg,22046
19
- pysat/examples/bica.py,sha256=OGcGQGQnMepCCurwRbygokFgoDkI7eBhjmsYvr3FM1M,27098
20
- pysat/examples/fm.py,sha256=e_s6wNBstEeoMw9zYyyDRgkE-Hqa902Iy_CxCS961CE,18136
21
- pysat/examples/genhard.py,sha256=DFXtSVQ4qn78y0-ZMr2D6gBCLizZSzgkvcbDsjqjnKI,19017
22
- pysat/examples/hitman.py,sha256=vHJEeSfoMQlDD3D3Poofaryv-k_dMH37XoqVXJUUuUg,26360
23
- pysat/examples/lbx.py,sha256=InMjqY-9UvWKznIXOEwfBsM4spfkduDld6gUkr1jCqo,23249
24
- pysat/examples/lsu.py,sha256=qyN2TvXG61EtMy-IrX5EYmLPM_iNOhtOkGTY5nHO_zo,16198
25
- pysat/examples/mcsls.py,sha256=bP47P56OOP_uy0MuFA7TGxMdkAis7gX4E9AEEI0tSec,22093
26
- pysat/examples/models.py,sha256=cdIR8iOrYu2ibqfcb_kEKXQMCfmFiz7cvZ3y1dur3Qw,5741
27
- pysat/examples/musx.py,sha256=hswVGkjm95lhOyrtl1e4ouDyNSy-hWvQ05084Xnck9I,10946
28
- pysat/examples/optux.py,sha256=8eYHO_uhL_4ugb-hRv2s6cnOwTurfqkpbdnK9T4iDtw,27697
29
- pysat/examples/primer.py,sha256=0OeV9R6mWyIr2BKIitkrfgY3q2XE-sV1ZLSiybGRFXw,23375
30
- pysat/examples/rc2.py,sha256=i1sH8ukXng56Vx-KnA2GiOvC_aCa_vFRVGoTMJoZjW4,76984
31
- pysat/examples/usage.py,sha256=x9luw6pyKAAndlxAeUWFhS4aLSVmD2t_j_5uA9YddHg,2183
32
- python_sat-1.9.dev7.data/scripts/approxmc.py,sha256=h6aMnSpIaYXkTMq-tCSzNWwKb0AG-vTH4vuLWGn5Q4s,13958
33
- python_sat-1.9.dev7.data/scripts/bbscan.py,sha256=xGxklG6Gc_UBaM8QvEJDOtQhEamxAncfsd65E-0JcAc,22696
34
- python_sat-1.9.dev7.data/scripts/bica.py,sha256=q6fQGsFp1EaaYRZGBsDFOIJPVScr5k42XFskBzW69mA,27776
35
- python_sat-1.9.dev7.data/scripts/fm.py,sha256=ek1QDsuxiq1zm1PBLbrSXXEE89RP9_DYwVNnyB3eO4s,18650
36
- python_sat-1.9.dev7.data/scripts/genhard.py,sha256=YswufT272W4xTJrSBlOC2ucJx4RK4ntfRv73rASrx30,19520
37
- python_sat-1.9.dev7.data/scripts/lbx.py,sha256=rCQ6zH_DXoVjBrzhZHSDJMfP92-hz2JVwh6e4m44AUc,23874
38
- python_sat-1.9.dev7.data/scripts/lsu.py,sha256=cAATg2x0Cu1LC8KszMctHqywjq7pygkb9vWNBrbUEZs,16681
39
- python_sat-1.9.dev7.data/scripts/mcsls.py,sha256=cTJQMIO-4iho412wG0JhvhqXWy81U0RQV8wwOgkri3Q,22690
40
- python_sat-1.9.dev7.data/scripts/models.py,sha256=UmMmklExzyXAIhh-0i038nQb7hTK6CbdV1M6m2GxxSI,5917
41
- python_sat-1.9.dev7.data/scripts/musx.py,sha256=LwK10YuQ8pIf1TJwp0HKp54O0hdk8zBy3TIfGsF1yW0,11277
42
- python_sat-1.9.dev7.data/scripts/optux.py,sha256=t20YBZH4_axTkRMapq-DL-fq-9tBybPWo0pkhIyGhDw,28394
43
- python_sat-1.9.dev7.data/scripts/primer.py,sha256=iE9Vy0XyeySIY-7-L_VMwRahsIVCEmm9k04OhLwDvuw,23982
44
- python_sat-1.9.dev7.data/scripts/rc2.py,sha256=yJL34GQclQakHH_Ksgt431Xwi7lmTZtiRI0VClHlirU,79004
45
- python_sat-1.9.dev7.data/scripts/unigen.py,sha256=e-HC2UxWA8MTN90VslkHX1ZlTPjdhI4etzkn6G8YAX4,17140
46
- python_sat-1.9.dev7.dist-info/licenses/LICENSE.txt,sha256=6QMvEzxqdPXEoiAZUBaZLeLF4hW2S81fjKz_THER0uQ,1109
47
- python_sat-1.9.dev7.dist-info/METADATA,sha256=TqwyTig9BSaYLrlVOU5AO7FduVX6kp4G9WuGfjbqOEs,1783
48
- python_sat-1.9.dev7.dist-info/WHEEL,sha256=AP_wkikJcUkDPUGvTNydv7g0R7BhW1u_fVHNKW7TJyI,101
49
- python_sat-1.9.dev7.dist-info/top_level.txt,sha256=0SLg3yVqNpeiqOwFcAo3OxXhqAnflCmb5Fjl6gsl-Do,33
50
- python_sat-1.9.dev7.dist-info/RECORD,,