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.
- {python_sat-1.8.dev24/python_sat.egg-info → python_sat-1.8.dev25}/PKG-INFO +1 -1
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/__init__.py +1 -1
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/formula.py +28 -3
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/pb.py +33 -12
- {python_sat-1.8.dev24 → python_sat-1.8.dev25/python_sat.egg-info}/PKG-INFO +1 -1
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/SOURCES.txt +2 -0
- python_sat-1.8.dev25/tests/test_encode_pb_conditional.py +54 -0
- python_sat-1.8.dev25/tests/test_idpool.py +27 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/LICENSE.txt +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/MANIFEST.in +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/README.rst +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/__init__.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/approxmc.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/allies/unigen.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/bitwise.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/card.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/clset.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/common.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/itot.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/ladder.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/mto.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/pairwise.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/ptypes.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/pycard.cc +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/seqcounter.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/sortcard.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/cardenc/utils.hh +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/__init__.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/bbscan.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/bica.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/fm.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/genhard.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/hitman.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/lbx.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/lsu.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/mcsls.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/models.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/musx.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/optux.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/primer.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/rc2.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/examples/usage.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/_fileio.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/_utils.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/card.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/engines.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/process.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/pysat/solvers.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/dependency_links.txt +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/requires.txt +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/python_sat.egg-info/top_level.txt +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/requirements.txt +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/setup.cfg +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/setup.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical103.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical153.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/cadical195.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose30.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose41.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/glucose421.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/lingeling.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplechrono.zip +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplecm.zip +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/maplesat.zip +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/mergesat3.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minicard.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minisat22.tar.gz +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/minisatgh.zip +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical103.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical153.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/cadical195.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose30.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose41.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/glucose421.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/gluecard30.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/gluecard41.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/lingeling.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplechrono.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplecm.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/maplesat.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/mergesat3.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minicard.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minisat22.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/patches/minisatgh.patch +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/prepare.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/solvers/pysolvers.cc +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_accum_stats.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmost.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmost1.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_atmostk.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_boolengine.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_clausification.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_cnf.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_equals1.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_formula_unique.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_process.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_propagate.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_unique_model.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_unique_mus.py +0 -0
- {python_sat-1.8.dev24 → python_sat-1.8.dev25}/tests/test_warmstart.py +0 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
462
|
+
vpool=vpool, encoding=encoding, comparator='=',
|
|
463
|
+
conditionals=conditionals)
|
|
@@ -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
|
|
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
|