python-sat 1.8.dev24__tar.gz → 1.8.dev25__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.
Files changed (100) hide show
  1. {python_sat-1.8.dev24/python_sat.egg-info → python_sat-1.8.dev25}/PKG-INFO +1 -1
  2. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/__init__.py +1 -1
  3. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/formula.py +28 -3
  4. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/pb.py +33 -12
  5. {python_sat-1.8.dev24 → python_sat-1.8.dev25/python_sat.egg-info}/PKG-INFO +1 -1
  6. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/SOURCES.txt +2 -0
  7. python_sat-1.8.dev25/tests/test_encode_pb_conditional.py +54 -0
  8. python_sat-1.8.dev25/tests/test_idpool.py +27 -0
  9. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/LICENSE.txt +0 -0
  10. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/MANIFEST.in +0 -0
  11. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/README.rst +0 -0
  12. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/__init__.py +0 -0
  13. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/approxmc.py +0 -0
  14. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/unigen.py +0 -0
  15. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/bitwise.hh +0 -0
  16. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/card.hh +0 -0
  17. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/clset.hh +0 -0
  18. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/common.hh +0 -0
  19. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/itot.hh +0 -0
  20. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/ladder.hh +0 -0
  21. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/mto.hh +0 -0
  22. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/pairwise.hh +0 -0
  23. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/ptypes.hh +0 -0
  24. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/pycard.cc +0 -0
  25. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/seqcounter.hh +0 -0
  26. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/sortcard.hh +0 -0
  27. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/utils.hh +0 -0
  28. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/__init__.py +0 -0
  29. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/bbscan.py +0 -0
  30. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/bica.py +0 -0
  31. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/fm.py +0 -0
  32. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/genhard.py +0 -0
  33. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/hitman.py +0 -0
  34. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/lbx.py +0 -0
  35. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/lsu.py +0 -0
  36. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/mcsls.py +0 -0
  37. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/models.py +0 -0
  38. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/musx.py +0 -0
  39. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/optux.py +0 -0
  40. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/primer.py +0 -0
  41. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/rc2.py +0 -0
  42. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/usage.py +0 -0
  43. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/_fileio.py +0 -0
  44. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/_utils.py +0 -0
  45. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/card.py +0 -0
  46. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/engines.py +0 -0
  47. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/process.py +0 -0
  48. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/solvers.py +0 -0
  49. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/dependency_links.txt +0 -0
  50. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/requires.txt +0 -0
  51. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/top_level.txt +0 -0
  52. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/requirements.txt +0 -0
  53. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/setup.cfg +0 -0
  54. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/setup.py +0 -0
  55. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical103.tar.gz +0 -0
  56. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical153.tar.gz +0 -0
  57. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical195.tar.gz +0 -0
  58. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose30.tar.gz +0 -0
  59. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose41.tar.gz +0 -0
  60. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose421.tar.gz +0 -0
  61. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/lingeling.tar.gz +0 -0
  62. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplechrono.zip +0 -0
  63. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplecm.zip +0 -0
  64. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplesat.zip +0 -0
  65. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/mergesat3.tar.gz +0 -0
  66. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minicard.tar.gz +0 -0
  67. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minisat22.tar.gz +0 -0
  68. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minisatgh.zip +0 -0
  69. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical103.patch +0 -0
  70. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical153.patch +0 -0
  71. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical195.patch +0 -0
  72. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose30.patch +0 -0
  73. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose41.patch +0 -0
  74. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose421.patch +0 -0
  75. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/gluecard30.patch +0 -0
  76. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/gluecard41.patch +0 -0
  77. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/lingeling.patch +0 -0
  78. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplechrono.patch +0 -0
  79. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplecm.patch +0 -0
  80. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplesat.patch +0 -0
  81. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/mergesat3.patch +0 -0
  82. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minicard.patch +0 -0
  83. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minisat22.patch +0 -0
  84. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minisatgh.patch +0 -0
  85. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/prepare.py +0 -0
  86. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/pysolvers.cc +0 -0
  87. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_accum_stats.py +0 -0
  88. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmost.py +0 -0
  89. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmost1.py +0 -0
  90. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmostk.py +0 -0
  91. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_boolengine.py +0 -0
  92. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_clausification.py +0 -0
  93. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_cnf.py +0 -0
  94. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_equals1.py +0 -0
  95. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_formula_unique.py +0 -0
  96. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_process.py +0 -0
  97. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_propagate.py +0 -0
  98. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_unique_model.py +0 -0
  99. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_unique_mus.py +0 -0
  100. {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_warmstart.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.8.dev24
3
+ Version: 1.8.dev25
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
@@ -10,7 +10,7 @@
10
10
 
11
11
  # current version
12
12
  #==============================================================================
13
- VERSION = (1, 8, 'dev', 24)
13
+ VERSION = (1, 8, 'dev', 25)
14
14
 
15
15
 
16
16
  # PEP440 Format
@@ -297,19 +297,28 @@ class IDPool(object):
297
297
  necessary the top variable ID can be accessed directly using the
298
298
  ``top`` variable.
299
299
 
300
+ The final parameter ``with_neg``, if set to ``True``, indicates that
301
+ the *negation* of an object assigned a variable ID ``n`` is to be
302
+ represented using the negative integer ``-n``. For this to work, the
303
+ object must have the method ``__neg__()`` implemented. This behaviour
304
+ is disabled by default.
305
+
300
306
  :param start_from: the smallest ID to assign.
301
307
  :param occupied: a list of occupied intervals.
308
+ :param with_neg: whether to support automatic negation handling
302
309
 
303
310
  :type start_from: int
304
311
  :type occupied: list(list(int))
312
+ :type with_neg: bool
305
313
  """
306
314
 
307
- def __init__(self, start_from=1, occupied=[]):
315
+ def __init__(self, start_from=1, occupied=[], with_neg=False):
308
316
  """
309
317
  Constructor.
310
318
  """
311
319
 
312
- self.restart(start_from=start_from, occupied=occupied)
320
+ self.restart(start_from=start_from, occupied=occupied,
321
+ with_neg=with_neg)
313
322
 
314
323
  def __repr__(self):
315
324
  """
@@ -318,7 +327,7 @@ class IDPool(object):
318
327
 
319
328
  return f'IDPool(start_from={self.top+1}, occupied={self._occupied})'
320
329
 
321
- def restart(self, start_from=1, occupied=[]):
330
+ def restart(self, start_from=1, occupied=[], with_neg=False):
322
331
  """
323
332
  Restart the manager from scratch. The arguments replicate those of
324
333
  the constructor of :class:`IDPool`.
@@ -337,6 +346,10 @@ class IDPool(object):
337
346
  # (if for whatever reason necessary)
338
347
  self.id2obj = {}
339
348
 
349
+ # flag to indicate whether this IDPool object
350
+ # should support automatic negation handling
351
+ self.with_neg = with_neg
352
+
340
353
  def id(self, obj=None):
341
354
  """
342
355
  The method is to be used to assign an integer variable ID for a
@@ -385,6 +398,11 @@ class IDPool(object):
385
398
 
386
399
  if vid not in self.id2obj:
387
400
  self.id2obj[vid] = obj
401
+
402
+ # adding the object's negation, if required and supported
403
+ if self.with_neg and hasattr(obj, '__neg__'):
404
+ self.obj2id[-obj] = -vid
405
+ self.id2obj[-vid] = -obj
388
406
  else:
389
407
  # no object is provided => simply return a new ID
390
408
  vid = self._next()
@@ -1022,6 +1040,13 @@ class Formula(object):
1022
1040
  return Neg(self)
1023
1041
  return self.subformula
1024
1042
 
1043
+ def __neg__(self):
1044
+ """
1045
+ Negation operator. Takes the same effect as ``__invert__()``.
1046
+ """
1047
+
1048
+ return self.__invert__()
1049
+
1025
1050
  def __and__(self, other):
1026
1051
  """
1027
1052
  Logical conjunction operator overloaded for class
@@ -137,6 +137,8 @@ class EncType(object):
137
137
  cases, this invokes the ``bdd`` encoder).
138
138
  """
139
139
 
140
+ assert pblib_present, 'Package \'pypblib\' is unavailable. Check your installation.'
141
+
140
142
  best = 0
141
143
  bdd = 1
142
144
  seqcounter = 2
@@ -242,7 +244,7 @@ class PBEnc(object):
242
244
 
243
245
  @classmethod
244
246
  def _encode(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
245
- encoding=EncType.best, comparator='<'):
247
+ encoding=EncType.best, comparator='<', conditionals=None):
246
248
  """
247
249
  This is the method that wraps the encoder of PyPBLib. Although the
248
250
  method can be invoked directly, a user is expected to call one of
@@ -310,7 +312,9 @@ class PBEnc(object):
310
312
  top_id = vpool.top
311
313
 
312
314
  # choosing the maximum id among the current top and the list of literals
313
- top_id = max(map(lambda x: abs(x), lits + [top_id if top_id != None else 0]))
315
+ if conditionals is None:
316
+ conditionals = []
317
+ top_id = max(map(lambda x: abs(x), conditionals + lits + [top_id if top_id != None else 0]))
314
318
 
315
319
  # native representation
316
320
  if encoding == 6:
@@ -331,8 +335,13 @@ class PBEnc(object):
331
335
  # pseudo-Boolean constraint and variable manager
332
336
  constr = pblib.PBConstraint([pblib.WeightedLit(*wl) for wl in wlits],
333
337
  EncType._to_pbcmp[comparator], bound)
338
+
334
339
  varmgr = pblib.AuxVarManager(top_id + 1)
335
340
 
341
+ # add optional conditionals
342
+ if len(conditionals) > 0:
343
+ constr.add_conditionals(conditionals)
344
+
336
345
  # encoder configuration
337
346
  config = pblib.PBConfig()
338
347
  config.set_PB_Encoder(EncType._to_pbenc[encoding])
@@ -358,7 +367,7 @@ class PBEnc(object):
358
367
 
359
368
  @classmethod
360
369
  def leq(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
361
- encoding=EncType.best):
370
+ encoding=EncType.best, conditionals=None):
362
371
  """
363
372
  This method can be used for creating a CNF encoding of a LEQ
364
373
  (weighted AtMostK) constraint, i.e. of
@@ -374,12 +383,18 @@ class PBEnc(object):
374
383
  ``EncType.best``, i.e. it is up to the PBLib encoder to choose the
375
384
  encoding type.
376
385
 
386
+ The final optional argument is ``conditionals``, where a list of
387
+ literals can be passed to be used as the antecedent for the PB
388
+ constraint, which makes it *"reified"*. If the argument is set to
389
+ ``None``, the constraint won't be reified.
390
+
377
391
  :param lits: a list of literals in the sum.
378
392
  :param weights: a list of weights
379
393
  :param bound: the value of bound :math:`k`.
380
394
  :param top_id: top variable identifier used so far.
381
395
  :param vpool: variable pool for counting the number of variables.
382
396
  :param encoding: identifier of the encoding to use.
397
+ :param conditionals: a list of variables that imply this constraint.
383
398
 
384
399
  :type lits: iterable(int)
385
400
  :type weights: iterable(int)
@@ -387,26 +402,29 @@ class PBEnc(object):
387
402
  :type top_id: integer or None
388
403
  :type vpool: :class:`.IDPool`
389
404
  :type encoding: integer
405
+ :type conditionals: list(int) or None
390
406
 
391
407
  :rtype: :class:`pysat.formula.CNFPlus`
392
408
  """
393
409
 
394
410
  return cls._encode(lits, weights=weights, bound=bound, top_id=top_id,
395
- vpool=vpool, encoding=encoding, comparator='<')
411
+ vpool=vpool, encoding=encoding, comparator='<',
412
+ conditionals=conditionals)
396
413
 
397
414
  @classmethod
398
415
  def atmost(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
399
- encoding=EncType.best):
416
+ encoding=EncType.best, conditionals=None):
400
417
  """
401
418
  A synonim for :meth:`PBEnc.leq`.
402
419
  """
403
420
 
404
421
  return cls.leq(lits, weights=weights, bound=bound, top_id=top_id,
405
- vpool=vpool, encoding=encoding)
422
+ vpool=vpool, encoding=encoding,
423
+ conditionals=conditionals)
406
424
 
407
425
  @classmethod
408
426
  def geq(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
409
- encoding=EncType.best):
427
+ encoding=EncType.best, conditionals=None):
410
428
  """
411
429
  This method can be used for creating a CNF encoding of a GEQ
412
430
  (weighted AtLeastK) constraint, i.e. of
@@ -416,21 +434,23 @@ class PBEnc(object):
416
434
  """
417
435
 
418
436
  return cls._encode(lits, weights=weights, bound=bound, top_id=top_id,
419
- vpool=vpool, encoding=encoding, comparator='>')
437
+ vpool=vpool, encoding=encoding, comparator='>',
438
+ conditionals=conditionals)
420
439
 
421
440
  @classmethod
422
441
  def atleast(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
423
- encoding=EncType.best):
442
+ encoding=EncType.best, conditionals=None):
424
443
  """
425
444
  A synonym for :meth:`PBEnc.geq`.
426
445
  """
427
446
 
428
447
  return cls.geq(lits, weights=weights, bound=bound, top_id=top_id,
429
- vpool=vpool, encoding=encoding)
448
+ vpool=vpool, encoding=encoding,
449
+ conditionals=conditionals)
430
450
 
431
451
  @classmethod
432
452
  def equals(cls, lits, weights=None, bound=1, top_id=None, vpool=None,
433
- encoding=EncType.best):
453
+ encoding=EncType.best, conditionals=None):
434
454
  """
435
455
  This method can be used for creating a CNF encoding of a weighted
436
456
  EqualsK constraint, i.e. of :math:`\\sum_{i=1}^{n}{a_i\\cdot x_i}=
@@ -439,4 +459,5 @@ class PBEnc(object):
439
459
  """
440
460
 
441
461
  return cls._encode(lits, weights=weights, bound=bound, top_id=top_id,
442
- vpool=vpool, encoding=encoding, comparator='=')
462
+ vpool=vpool, encoding=encoding, comparator='=',
463
+ conditionals=conditionals)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.8.dev24
3
+ Version: 1.8.dev25
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
@@ -88,8 +88,10 @@ tests/test_atmostk.py
88
88
  tests/test_boolengine.py
89
89
  tests/test_clausification.py
90
90
  tests/test_cnf.py
91
+ tests/test_encode_pb_conditional.py
91
92
  tests/test_equals1.py
92
93
  tests/test_formula_unique.py
94
+ tests/test_idpool.py
93
95
  tests/test_process.py
94
96
  tests/test_propagate.py
95
97
  tests/test_unique_model.py
@@ -0,0 +1,54 @@
1
+ from pysat.formula import IDPool
2
+ from pysat.card import CardEnc
3
+ import pytest
4
+
5
+ @pytest.mark.skip(reason="PBLIB not installed in CI")
6
+ def test_pbenc_conditional():
7
+ from pysat.pb import PBEnc, EncType
8
+ L = 3
9
+ LITS = list(range(1, L + 1)) # Variables x1, x2, x3, x4
10
+ WEIGHTS = [2, 1, 1] # Coefficients: 2*x1 + 3*x2 + 5*x3 + 8*x4
11
+ bound = 10 # Constraint: ... <= 10
12
+
13
+ CONDS = [L+1]
14
+
15
+ # We need a vpool even if we don't use it, to handle PySAT internal structure
16
+ vpool = IDPool()
17
+
18
+ # Generate the CNF clauses
19
+ cnf = PBEnc.atleast(
20
+ lits=LITS,
21
+ weights=WEIGHTS,
22
+ bound=bound,
23
+ vpool=vpool,
24
+ conditionals=CONDS
25
+ )
26
+
27
+ assert cnf.clauses == [[-4]] # without PR to pblib this will be [[3, -4], [1, -4], [2, -4], [-4]]
28
+
29
+ bound = 2
30
+
31
+ # Generate the CNF clauses
32
+ cnf = PBEnc.atleast(
33
+ lits=LITS,
34
+ weights=WEIGHTS,
35
+ bound=bound,
36
+ vpool=vpool,
37
+ conditionals=CONDS
38
+ )
39
+
40
+ assert cnf.clauses == [[5], [-5, 6], [3, 6], [-5, 3, 7], [2, 6], [-5, 2, 7], [3, 2, 7], [-5, 3, 2, 8], [1, 9], [-7, 9], [1, -7, 10], [-10, -4]]
41
+
42
+ bound = 0
43
+
44
+ # Generate the CNF clauses
45
+ cnf = PBEnc.atleast(
46
+ lits=LITS,
47
+ weights=WEIGHTS,
48
+ bound=bound,
49
+ vpool=vpool,
50
+ conditionals=CONDS
51
+ )
52
+
53
+ assert cnf.clauses == []
54
+
@@ -0,0 +1,27 @@
1
+ from pysat.formula import IDPool
2
+
3
+ def test_idpool_neg():
4
+ pool = IDPool(with_neg=True)
5
+
6
+ pool.id('hello')
7
+ pool.id(+25)
8
+ pool.id(-42)
9
+ pool.id('world')
10
+
11
+ assert pool.id('hello') == 1
12
+ assert pool.id(25) == -pool.id(-25) == +2
13
+ assert pool.id(42) == -pool.id(-42) == -3
14
+ assert pool.id('world') == 4
15
+
16
+ def test_idpool_occupied():
17
+ pool = IDPool(start_from=5, occupied=[[2, 10], [12, 20], [22, 30]], with_neg=True)
18
+
19
+ pool.id('hello')
20
+ pool.id(+25)
21
+ pool.id(-42)
22
+ pool.id('world')
23
+
24
+ assert pool.id('hello') == 11
25
+ assert pool.id(25) == -pool.id(-25) == +21
26
+ assert pool.id(42) == -pool.id(-42) == -31
27
+ assert pool.id('world') == 32
File without changes
File without changes