python-sat 1.9.dev7__cp313-cp313-win_amd64.whl → 1.9.dev8__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 (25) 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 +202 -106
  6. pysolvers.cp313-win_amd64.pyd +0 -0
  7. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/rc2.py +6 -4
  8. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev8.dist-info}/METADATA +1 -1
  9. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev8.dist-info}/RECORD +25 -25
  10. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/approxmc.py +0 -0
  11. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/bbscan.py +0 -0
  12. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/bica.py +0 -0
  13. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/fm.py +0 -0
  14. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/genhard.py +0 -0
  15. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/lbx.py +0 -0
  16. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/lsu.py +0 -0
  17. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/mcsls.py +0 -0
  18. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/models.py +0 -0
  19. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/musx.py +0 -0
  20. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/optux.py +0 -0
  21. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/primer.py +0 -0
  22. {python_sat-1.9.dev7.data → python_sat-1.9.dev8.data}/scripts/unigen.py +0 -0
  23. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev8.dist-info}/WHEEL +0 -0
  24. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev8.dist-info}/licenses/LICENSE.txt +0 -0
  25. {python_sat-1.9.dev7.dist-info → python_sat-1.9.dev8.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', 8)
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
@@ -883,11 +883,11 @@ class Formula(object):
883
883
  @staticmethod
884
884
  def _get_key(*args, **kwargs):
885
885
  """
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.
886
+ The method is used to extract and return an immutable structural
887
+ key associated with the formula requested by a user. The key is
888
+ composed of tuples, frozensets, and scalar values rather than
889
+ string representations. The method is meant to be internal and
890
+ not to be used by formula users.
891
891
  """
892
892
 
893
893
  def _hashable(entity):
@@ -918,7 +918,6 @@ class Formula(object):
918
918
  if isinstance(value, Iterable) and value:
919
919
  items.extend(_flatten(value, prefix=new_key, sep=sep))
920
920
  else:
921
-
922
921
  items.append((new_key, value))
923
922
 
924
923
  # finally, it is a simple non-empty object
@@ -945,58 +944,121 @@ class Formula(object):
945
944
  elif item[0] != 'merge':
946
945
  subfs.append(item)
947
946
  else:
948
- extra = [('merge', repr(item[1]))]
947
+ extra = [('merge', item[1])]
948
+
949
+ def _object_key(obj):
950
+ """
951
+ Get a hashable key for an atom object.
952
+ """
953
+
954
+ if type(obj) in (bool, int, float, str, bytes, type(None)):
955
+ return ('val', type(obj), obj)
956
+ if type(obj) in (tuple, list):
957
+ return ('seq', tuple(_object_key(item) for item in obj))
958
+ if type(obj) in (set, frozenset):
959
+ return ('set', frozenset(_object_key(item) for item in obj))
960
+ if isinstance(obj, dict):
961
+ return ('map', frozenset((_object_key(key), _object_key(val)) for key, val in obj.items()))
962
+ try:
963
+ hash(obj)
964
+ except TypeError:
965
+ return ('identity', type(obj), id(obj))
966
+ return ('obj', type(obj), obj)
967
+
968
+ def _formula_key(form):
969
+ """
970
+ Get a structural key without a formula's merge flag.
971
+ """
972
+
973
+ if not isinstance(form, Formula):
974
+ return ('identity', type(form), id(form))
975
+
976
+ if form.type == FormulaType.CNF:
977
+ # CNF and CNFPlus are mutable containers and deliberately
978
+ # bypass Formula's unique-object constructor; using their
979
+ # object identity as it looks like the cheapest option
980
+ return ('cnf-object', type(form), id(form))
981
+
982
+ if form.type == FormulaType.ATOM:
983
+ return (FormulaType.ATOM, _object_key(form.object))
984
+ if form.type == FormulaType.NEG:
985
+ return (FormulaType.NEG, _formula_key(form.subformula))
986
+ if form.type == FormulaType.IMPL:
987
+ return (FormulaType.IMPL, _formula_key(form.left),
988
+ _formula_key(form.right))
989
+ if form.type == FormulaType.ITE:
990
+ return (FormulaType.ITE, _formula_key(form.cond),
991
+ _formula_key(form.cons1),
992
+ _formula_key(form.cons2))
993
+
994
+ counts = collections.Counter(_formula_key(subform) for subform in form.subformulas)
995
+ return (form.type, frozenset(counts.items()))
996
+
997
+ def _merged_operands(operands, formula_type):
998
+ """Flatten same-type operands for a merged connective."""
999
+ result = []
1000
+ for operand in operands:
1001
+ if isinstance(operand, Formula) and operand.type == formula_type:
1002
+ result.extend(_merged_operands(operand.subformulas,
1003
+ formula_type))
1004
+ else:
1005
+ result.append(_formula_key(operand))
1006
+ return result
949
1007
 
950
- # the ugly part:
951
- # reconstructing the key pairs, depending on the type of Formula
952
- if ftype[1] == FormulaType.ATOM:
1008
+ # Reconstruct a structural key depending on the Formula type.
1009
+ formula_type = ftype[1]
1010
+ if formula_type == FormulaType.ATOM:
953
1011
  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:
1012
+ return (formula_type, _object_key(subfs[0][1]))
1013
+
1014
+ if formula_type == FormulaType.NEG:
956
1015
  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:
1016
+ return (formula_type, _formula_key(subfs[0][1]))
1017
+
1018
+ if formula_type == FormulaType.IMPL:
959
1019
  assert len(subfs) == 2, 'Two subformulas are required for an Implies formula'
960
1020
  if subfs[0][0] == '' and subfs[1][0] == '':
961
- subfs[0] = ('left', id(subfs[0][1]))
962
- subfs[1] = ('right', id(subfs[1][1]))
1021
+ operands = [('left', subfs[0][1]), ('right', subfs[1][1])]
963
1022
  elif subfs[1][0] == 'left':
964
- subfs[0] = ('right', id(subfs[0][1]))
1023
+ operands = [('right', subfs[0][1]), subfs[1]]
965
1024
  elif subfs[1][0] == 'right':
966
- subfs[0] = ('left', id(subfs[0][1]))
967
- elif ftype[1] == FormulaType.ITE:
1025
+ operands = [('left', subfs[0][1]), subfs[1]]
1026
+ else:
1027
+ operands = subfs
1028
+ role_order = {'left': 0, 'right': 1}
1029
+ return (formula_type, tuple( (label, _formula_key(value)) for \
1030
+ label, value in sorted(operands,
1031
+ key=lambda pair: role_order[pair[0]])))
1032
+
1033
+ if formula_type == FormulaType.ITE:
968
1034
  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]))
1035
+ if all(item[0] == '' for item in subfs):
1036
+ subfs = [('cond', subfs[0][1]), ('cons1', subfs[1][1]), ('cons2', subfs[2][1])]
973
1037
  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]))
1038
+ role = subfs[2][0]
1039
+ missing = [r for r in ('cond', 'cons1', 'cons2') if r != role]
1040
+ subfs = [(missing[0], subfs[0][1]), (missing[1], subfs[1][1]), subfs[2]]
1041
+ elif subfs[0][0] == '':
1042
+ roles = {item[0] for item in subfs[1:]}
1043
+ missing = next(r for r in ('cond', 'cons1', 'cons2') if r not in roles)
1044
+ subfs[0] = (missing, subfs[0][1])
1045
+
1046
+ role_order = {'cond': 0, 'cons1': 1, 'cons2': 2}
1047
+ return (formula_type, tuple((label, _formula_key(value)) for \
1048
+ label, value in sorted(subfs,
1049
+ key=lambda pair: role_order[pair[0]])))
1050
+
1051
+ # these are commutative connectives; representing operands as a
1052
+ # multiset so that argument order is irrelevant while duplicate
1053
+ # operands remain significant; a merged connective also flattens nested operands.
1054
+ assert len(subfs) >= 1, 'At least one subformula is required for an And/Equals/Or/XOr formula'
1055
+ merge = dict(extra).get('merge', False)
1056
+ operands = [value for _, value in subfs]
1057
+ if merge:
1058
+ operands = _merged_operands(operands, formula_type)
990
1059
  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])
1060
+ operands = [_formula_key(operand) for operand in operands]
1061
+ return (formula_type, frozenset(collections.Counter(operands).items()), merge)
1000
1062
 
1001
1063
  def __hash__(self):
1002
1064
  """
@@ -1708,50 +1770,83 @@ class And(Formula):
1708
1770
 
1709
1771
  def _clausify(self, name_required=True):
1710
1772
  """
1711
- Conjuction clausification.
1773
+ Conjunction clausification.
1712
1774
 
1713
1775
  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.
1776
+ the subformulas expanding self's list of clauses and also
1777
+ populates self's clauses with unit clauses, each containing the
1778
+ auxiliary "name" of the corresponding subformula, thus
1779
+ representing their conjunction. However, nested :class:`And` and
1780
+ :class:`CNF` formulas are expanded without introducing
1781
+ intermediate Boolean names - instead, they contribute their
1782
+ clausal representations to the list of self's clauses unchanged.
1783
+
1784
+ If ``name_required`` is set to ``True``, the method introduces one
1785
+ name for the complete conjunction and encodes the equivalence
1786
+ between that name and the collected clauses.
1723
1787
 
1724
1788
  :param name_required: whether or not a Tseitin variable is needed
1725
- :param name_required: bool
1789
+ :type name_required: bool
1726
1790
  """
1727
1791
 
1728
1792
  save_clauses = bool(self.clauses)
1729
1793
 
1730
1794
  if not self.clauses:
1731
- # first, recursively encoding subformulas
1795
+ # recursively collect a clausal representation; nested `And` and
1796
+ # `CNF` objects are conjunctions already, so they do not need a
1797
+ # Boolean name at this level.
1732
1798
  for sub in self.subformulas:
1733
- sub._clausify(name_required=True)
1734
-
1735
- # adding unit clauses
1736
- self.clauses.append([sub.name])
1799
+ if type(sub) in (And, CNF):
1800
+ sub._clausify(name_required=False)
1801
+ self.clauses.extend(clause.copy() for clause in sub.clauses)
1802
+ else:
1803
+ sub._clausify(name_required=True)
1804
+ self.clauses.append([sub.name])
1737
1805
 
1738
- # introducing a new name for this formula if required
1806
+ # introducing a name is needed only when this conjunction is itself
1807
+ # used by another connective; encode each non-unit clause with its own
1808
+ # selector, then encode the conjunction of those selectors with the
1809
+ # single name for this `And` formula
1739
1810
  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 = []
1811
+ self.encoded, enclits = [], []
1745
1812
 
1746
- self.name = Formula._vpool[Formula._context].id(self)
1813
+ for cl in self.clauses:
1814
+ auxv = cl[0]
1815
+ if len(cl) > 1:
1816
+ auxv = Formula._vpool[Formula._context].id()
1817
+
1818
+ # direct implication
1819
+ for l in cl:
1820
+ self.encoded.append([-l, auxv])
1821
+
1822
+ # opposite implication
1823
+ self.encoded.append(cl + [-auxv])
1824
+
1825
+ # literals representing the clauses
1826
+ enclits.append(auxv)
1827
+
1828
+ # encoding the conjunction
1829
+ if len(enclits) > 1:
1830
+ self.name = Formula._vpool[Formula._context].id(self)
1747
1831
 
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
1832
+ for lit in enclits:
1833
+ self.encoded.append([lit, -self.name])
1834
+ self.encoded.append([self.name] + [-lit for lit in enclits])
1835
+ elif len(enclits) == 1: # single clause - nothing left to encode
1836
+ self.name = enclits[0] # existing variable
1752
1837
 
1753
- # adding final clause
1754
- self.encoded.append(cl)
1838
+ # connecting it to the `And` object as its name
1839
+ Formula._vpool[Formula._context].obj2id[self] = self.name
1840
+ if self.name not in Formula._vpool[Formula._context].id2obj:
1841
+ Formula._vpool[Formula._context].id2obj[self.name] = self
1842
+ else:
1843
+ self.name = PYSAT_TRUE.name
1844
+
1845
+ # preserve clauses that existed before this call;
1846
+ # they are still needed if the same formula is later iterated as
1847
+ # an outermost formula
1848
+ if not save_clauses:
1849
+ self.clauses = []
1755
1850
 
1756
1851
  def _atoms(self, dest):
1757
1852
  """
@@ -1947,18 +2042,18 @@ class Or(Formula):
1947
2042
  Disjunction clausification.
1948
2043
 
1949
2044
  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.
2045
+ the subformulas and populates self's clauses with a unit clause
2046
+ containing the auxiliary "name" of each corresponding subformula,
2047
+ thus representing their disjunction.
1953
2048
 
1954
2049
  If ``name_required`` is set to ``True``, the method encodes the
1955
- conjunction using the standard logic: :math:`x \\equiv
2050
+ disjunction using the standard logic: :math:`x \\equiv
1956
2051
  \\bigvee{y_i}`, if :math:`x` is the new auxiliary variable
1957
2052
  encoding ``self`` and :math:`y_i` is the auxiliary variable
1958
2053
  representing :math:`i`'s subformula.
1959
2054
 
1960
2055
  :param name_required: whether or not a Tseitin variable is needed
1961
- :param name_required: bool
2056
+ :type name_required: bool
1962
2057
  """
1963
2058
 
1964
2059
  save_clauses = bool(self.clauses)
@@ -2136,7 +2231,7 @@ class Neg(Formula):
2136
2231
  is equal to the negation of subformula's name.
2137
2232
 
2138
2233
  :param name_required: whether or not a Tseitin variable is needed
2139
- :param name_required: bool
2234
+ :type name_required: bool
2140
2235
  """
2141
2236
 
2142
2237
  if not self.clauses:
@@ -2307,7 +2402,7 @@ class Implies(Formula):
2307
2402
 
2308
2403
  If ``name_required`` is ``False``, the method recursively encodes
2309
2404
  the left and right subformulas giving them names, say, :math:`x`
2310
- and :math:`y` respectively and the populates self's clauses with a
2405
+ and :math:`y` respectively, and populates self's clauses with a
2311
2406
  single binary clause :math:`(\\neg{x}\\lor y)`.
2312
2407
 
2313
2408
  If ``name_required`` is set to ``True``, the method removes this
@@ -2315,7 +2410,7 @@ class Implies(Formula):
2315
2410
  Tseitin-encoding it, i.e. :math:`n \\equiv (\\neg{x}\\lor y)`.
2316
2411
 
2317
2412
  :param name_required: whether or not a Tseitin variable is needed
2318
- :param name_required: bool
2413
+ :type name_required: bool
2319
2414
  """
2320
2415
 
2321
2416
  save_clauses = bool(self.clauses)
@@ -2407,7 +2502,7 @@ class Equals(Formula):
2407
2502
  >>> from pysat.formula import *
2408
2503
  >>> a1 = Equals(Equals(Atom('x'), Atom('y')), Atom('z'))
2409
2504
  >>> a2 = Equals(Equals(Atom('x'), Atom('y')), Atom('z'), merge=True)
2410
- >>> a3 = Atom('x') == Atom('y') == Atom('z')
2505
+ >>> a3 = Atom('x') @ Atom('y') @ Atom('z')
2411
2506
  >>>
2412
2507
  >>> print(a1)
2413
2508
  (x @ y) @ z
@@ -2571,7 +2666,7 @@ class Equals(Formula):
2571
2666
  relating it with the names of subformulas.
2572
2667
 
2573
2668
  :param name_required: whether or not a Tseitin variable is needed
2574
- :param name_required: bool
2669
+ :type name_required: bool
2575
2670
  """
2576
2671
 
2577
2672
  save_clauses = bool(self.clauses)
@@ -2652,13 +2747,12 @@ class XOr(Formula):
2652
2747
 
2653
2748
  If an additional Boolean keyword argument ``merge`` is provided set to
2654
2749
  ``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.
2750
+ formula merging its *exclusive-disjunction* sub-operands into the
2751
+ list of operands. For example, if ``XOr(XOr(x, y), z, merge=True)`` is
2752
+ called, a new Formula object will be created with two operands:
2753
+ ``XOr(x, y)`` and ``z``, followed by merging ``x`` and ``y`` into the
2754
+ list of root-level ``XOr``. This will result in a formula
2755
+ ``XOr(x, y, z)``. Bitwise ``^`` operations also enable merging.
2662
2756
 
2663
2757
  Example:
2664
2758
 
@@ -2679,8 +2773,8 @@ class XOr(Formula):
2679
2773
  >>> id(a1) == id(a2)
2680
2774
  False
2681
2775
  >>>
2682
- >>> id(a1) == id(a3)
2683
- True # formulas a1 and a3 refer to the same object
2776
+ >>> id(a2) == id(a3)
2777
+ True # formulas a2 and a3 refer to the same object
2684
2778
 
2685
2779
  .. note::
2686
2780
 
@@ -2766,7 +2860,7 @@ class XOr(Formula):
2766
2860
  >>> a = x ^ y ^ z
2767
2861
  >>>
2768
2862
  >>> print(a.simplified(assumptions=[y]))
2769
- ~x ^ z
2863
+ ~(x ^ z)
2770
2864
  >>> print(a.simplified(assumptions=[~y]))
2771
2865
  x ^ z
2772
2866
  """
@@ -2817,7 +2911,7 @@ class XOr(Formula):
2817
2911
  variable for each pair of operands.
2818
2912
 
2819
2913
  :param name_required: whether or not a Tseitin variable is needed
2820
- :param name_required: bool
2914
+ :type name_required: bool
2821
2915
  """
2822
2916
 
2823
2917
  save_clauses = bool(self.clauses)
@@ -2943,7 +3037,7 @@ class ITE(Formula):
2943
3037
  >>> ite = ITE(x, y, z)
2944
3038
  >>>
2945
3039
  >>> print(ite)
2946
- >>> (x >> y) & (~x >> z)
3040
+ (x >> y) & (~x >> z)
2947
3041
  """
2948
3042
 
2949
3043
  def __new__(cls, *args, **kwargs):
@@ -3071,17 +3165,17 @@ class ITE(Formula):
3071
3165
 
3072
3166
  If ``name_required`` is ``False``, the method recursively encodes
3073
3167
  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)`.
3168
+ names, say, :math:`x`, :math:`y`, and :math:`z`, respectively, and
3169
+ populates self's clauses with two binary clauses
3170
+ :math:`(\\neg{x}\\lor y)` and :math:`(x \\lor z)`.
3077
3171
 
3078
3172
  If ``name_required`` is set to ``True``, the method removes these
3079
3173
  clauses and instead gives a name to the ITE by Tseitin-encoding
3080
3174
  it, i.e. encoding :math:`n \\equiv \\left[(\\neg{x}\\lor
3081
- y)\\land(x\\lor y)\\right]`.
3175
+ y)\\land(x\\lor z)\\right]`.
3082
3176
 
3083
3177
  :param name_required: whether or not a Tseitin variable is needed
3084
- :param name_required: bool
3178
+ :type name_required: bool
3085
3179
  """
3086
3180
 
3087
3181
  save_clauses = bool(self.clauses)
@@ -3136,7 +3230,7 @@ class ITE(Formula):
3136
3230
  """
3137
3231
  Informal representation of the ``ITE`` formula. Returns a string
3138
3232
  representation of the subformulas as two implications connected
3139
- with the conjuction symbol ``' & '``
3233
+ with the conjunction symbol ``' & '``
3140
3234
  """
3141
3235
 
3142
3236
  cons1 = '{0} >> {1}'.format(f'{str(self.cond)}' if self.cond.type in (FormulaType.ATOM, FormulaType.NEG) else f'({str(self.cond)})',
@@ -3898,7 +3992,7 @@ class CNF(Formula, object):
3898
3992
  for lit in enclits:
3899
3993
  clauses.append([-self.name, lit])
3900
3994
  clauses.append([self.name] + [-lit for lit in enclits])
3901
- else: # single clause - nothing left to encode
3995
+ elif len(enclits) == 1: # single clause - nothing left to encode
3902
3996
  self.name = enclits[0] # existing variable
3903
3997
 
3904
3998
  # connecting it to the CNF object as its name
@@ -3907,6 +4001,8 @@ class CNF(Formula, object):
3907
4001
 
3908
4002
  # just in case, marking all ids below self.name as occupied
3909
4003
  Formula._vpool[Formula._context].occupy(1, self.name)
4004
+ else:
4005
+ self.name = PYSAT_TRUE.name
3910
4006
 
3911
4007
  self.encoded = clauses
3912
4008
  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.dev8
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
@@ -1,12 +1,12 @@
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
1
+ pycard.cp313-win_amd64.pyd,sha256=_voIGCx_18yyEut1hwFyQQOXXx0cpK7SUk9XUk1FeJg,71680
2
+ pyformula.cp313-win_amd64.pyd,sha256=IM84nhDX6glnVN5r00up53DLBbEcnvYiu0_obtp1IhU,31232
3
+ pysolvers.cp313-win_amd64.pyd,sha256=euQwMYwmZ2b0O2vmc0kt9TaoL5FtGz14WOQmtA858d0,3340288
4
+ pysat/__init__.py,sha256=QTCb8kNOCtmIuJySA5yDeowVukzE_yj5qxdVTBdzgaM,680
5
5
  pysat/_fileio.py,sha256=pXRGGAaP7U8r3bpn5ShseCSHROXqi7ygaYe6T6QORto,6700
6
6
  pysat/_utils.py,sha256=4cv40p70FKvjCTKq8GqzS_jlxF74cp_lojTZSim_qJE,1340
7
7
  pysat/card.py,sha256=rav3_t_mCzbLw8SAdXcOh-PNbFtaATVSAJzpbygqiQ4,30066
8
8
  pysat/engines.py,sha256=yAYA_PzIGr_uRF85M7kL2bipjpLbY7jdfFKTdY-yW8I,46364
9
- pysat/formula.py,sha256=tHltOuKQ5L7nefYlKDzPU0fWXol6-YUU1lexihNBRV4,210252
9
+ pysat/formula.py,sha256=qCT-1__FtpTNemKFnixKOEi7Pwt3EIUnY_3TgQUcDWw,214793
10
10
  pysat/integer.py,sha256=um6FXUzmBHUFlWXNKs0xLh9Jss3jiEin2Er_U41KtkA,90203
11
11
  pysat/pb.py,sha256=DMy8UfbbpfJo5cTZul9W1o_mlr-B0lCIEseZjrQYd8A,17816
12
12
  pysat/process.py,sha256=8lNbpEKipFZjbQ9DCJPfdL8eZHx-ltNuu7h4geWWdJY,12739
@@ -27,24 +27,24 @@ pysat/examples/models.py,sha256=cdIR8iOrYu2ibqfcb_kEKXQMCfmFiz7cvZ3y1dur3Qw,5741
27
27
  pysat/examples/musx.py,sha256=hswVGkjm95lhOyrtl1e4ouDyNSy-hWvQ05084Xnck9I,10946
28
28
  pysat/examples/optux.py,sha256=8eYHO_uhL_4ugb-hRv2s6cnOwTurfqkpbdnK9T4iDtw,27697
29
29
  pysat/examples/primer.py,sha256=0OeV9R6mWyIr2BKIitkrfgY3q2XE-sV1ZLSiybGRFXw,23375
30
- pysat/examples/rc2.py,sha256=i1sH8ukXng56Vx-KnA2GiOvC_aCa_vFRVGoTMJoZjW4,76984
30
+ pysat/examples/rc2.py,sha256=7-FuygxAbgNYb9QmKsNhkK5EG5OW8mpHOpoA8GnDs28,76998
31
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,,
32
+ python_sat-1.9.dev8.data/scripts/approxmc.py,sha256=h6aMnSpIaYXkTMq-tCSzNWwKb0AG-vTH4vuLWGn5Q4s,13958
33
+ python_sat-1.9.dev8.data/scripts/bbscan.py,sha256=xGxklG6Gc_UBaM8QvEJDOtQhEamxAncfsd65E-0JcAc,22696
34
+ python_sat-1.9.dev8.data/scripts/bica.py,sha256=q6fQGsFp1EaaYRZGBsDFOIJPVScr5k42XFskBzW69mA,27776
35
+ python_sat-1.9.dev8.data/scripts/fm.py,sha256=ek1QDsuxiq1zm1PBLbrSXXEE89RP9_DYwVNnyB3eO4s,18650
36
+ python_sat-1.9.dev8.data/scripts/genhard.py,sha256=YswufT272W4xTJrSBlOC2ucJx4RK4ntfRv73rASrx30,19520
37
+ python_sat-1.9.dev8.data/scripts/lbx.py,sha256=rCQ6zH_DXoVjBrzhZHSDJMfP92-hz2JVwh6e4m44AUc,23874
38
+ python_sat-1.9.dev8.data/scripts/lsu.py,sha256=cAATg2x0Cu1LC8KszMctHqywjq7pygkb9vWNBrbUEZs,16681
39
+ python_sat-1.9.dev8.data/scripts/mcsls.py,sha256=cTJQMIO-4iho412wG0JhvhqXWy81U0RQV8wwOgkri3Q,22690
40
+ python_sat-1.9.dev8.data/scripts/models.py,sha256=UmMmklExzyXAIhh-0i038nQb7hTK6CbdV1M6m2GxxSI,5917
41
+ python_sat-1.9.dev8.data/scripts/musx.py,sha256=LwK10YuQ8pIf1TJwp0HKp54O0hdk8zBy3TIfGsF1yW0,11277
42
+ python_sat-1.9.dev8.data/scripts/optux.py,sha256=t20YBZH4_axTkRMapq-DL-fq-9tBybPWo0pkhIyGhDw,28394
43
+ python_sat-1.9.dev8.data/scripts/primer.py,sha256=iE9Vy0XyeySIY-7-L_VMwRahsIVCEmm9k04OhLwDvuw,23982
44
+ python_sat-1.9.dev8.data/scripts/rc2.py,sha256=vvB7GlzssovGtnyk-COK-1bxmPh4zpj8Y7GqQa9dC9U,79020
45
+ python_sat-1.9.dev8.data/scripts/unigen.py,sha256=e-HC2UxWA8MTN90VslkHX1ZlTPjdhI4etzkn6G8YAX4,17140
46
+ python_sat-1.9.dev8.dist-info/licenses/LICENSE.txt,sha256=6QMvEzxqdPXEoiAZUBaZLeLF4hW2S81fjKz_THER0uQ,1109
47
+ python_sat-1.9.dev8.dist-info/METADATA,sha256=G0u3A0QEHYeubjJ5xFClVKTkS7cNKvB_3FtDjjXfaTw,1783
48
+ python_sat-1.9.dev8.dist-info/WHEEL,sha256=AP_wkikJcUkDPUGvTNydv7g0R7BhW1u_fVHNKW7TJyI,101
49
+ python_sat-1.9.dev8.dist-info/top_level.txt,sha256=0SLg3yVqNpeiqOwFcAo3OxXhqAnflCmb5Fjl6gsl-Do,33
50
+ python_sat-1.9.dev8.dist-info/RECORD,,