python-sat 1.9.dev6__tar.gz → 1.9.dev7__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.
Potentially problematic release.
This version of python-sat might be problematic. Click here for more details.
- {python_sat-1.9.dev6/python_sat.egg-info → python_sat-1.9.dev7}/PKG-INFO +1 -1
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_parse.cc +32 -14
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_scan.hh +26 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_weight.cc +3 -2
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pyformula.hh +1 -1
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/__init__.py +1 -1
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/formula.py +2 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7/python_sat.egg-info}/PKG-INFO +1 -1
- python_sat-1.9.dev7/tests/test_formula_parsing.py +143 -0
- python_sat-1.9.dev6/tests/test_formula_parsing.py +0 -70
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/LICENSE.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/MANIFEST.in +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/README.rst +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/allies/__init__.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/allies/approxmc.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/allies/unigen.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/bitwise.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/card.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/clset.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/common.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/itot.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/ladder.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/mto.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/pairwise.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/ptypes.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/pycard.cc +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/seqcounter.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/sortcard.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/cardenc/utils.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/__init__.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/bbscan.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/bica.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/fm.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/genhard.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/hitman.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/lbx.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/lsu.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/mcsls.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/models.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/musx.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/optux.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/primer.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/rc2.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/examples/usage.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_plus.cc +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_plus.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_py.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pf_weight.hh +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/formula/pyformula.cc +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/_fileio.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/_utils.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/card.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/engines.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/integer.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/pb.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/process.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/pysat/solvers.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/python_sat.egg-info/SOURCES.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/python_sat.egg-info/dependency_links.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/python_sat.egg-info/requires.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/python_sat.egg-info/top_level.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/requirements.txt +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/setup.cfg +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/setup.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/cadical103.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/cadical153.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/cadical195.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/cadical300.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/glucose30.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/glucose41.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/glucose421.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/lingeling.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/maplechrono.zip +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/maplecm.zip +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/maplesat.zip +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/mergesat3.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/minicard.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/minisat22.tar.gz +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/minisatgh.zip +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/cadical103.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/cadical153.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/cadical195.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/cadical300.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/glucose30.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/glucose41.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/glucose421.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/gluecard30.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/gluecard41.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/kissat404.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/lingeling.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/maplechrono.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/maplecm.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/maplesat.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/mergesat3.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/minicard.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/minisat22.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/minisatep.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/patches/minisatgh.patch +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/prepare.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/solvers/pysolvers.cc +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_accum_stats.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_atmost.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_atmost1.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_atmostk.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_boolengine.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_clausification.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_cnf.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_empty_extclause.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_encode_pb_conditional.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_equals1.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_formula_unique.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_idpool.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_integer.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_oom.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_process.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_propagate.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_unique_model.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_unique_mus.py +0 -0
- {python_sat-1.9.dev6 → python_sat-1.9.dev7}/tests/test_warmstart.py +0 -0
|
@@ -47,10 +47,14 @@ PyObject *parse_cnf_impl(PyObject *txt_obj, PyObject *comment_lead)
|
|
|
47
47
|
continue;
|
|
48
48
|
|
|
49
49
|
if (comment_mask[(unsigned char)beg[0]]) {
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if (line_has_kind(beg, lend, "cnf"))
|
|
51
|
+
continue;
|
|
52
|
+
if (line_has_p(beg, lend)) {
|
|
53
|
+
PyErr_SetString(PyExc_ValueError, "invalid CNF preamble");
|
|
54
|
+
goto fail;
|
|
53
55
|
}
|
|
56
|
+
if (!append_comment(comments, beg, lend))
|
|
57
|
+
goto fail;
|
|
54
58
|
continue;
|
|
55
59
|
}
|
|
56
60
|
|
|
@@ -143,13 +147,17 @@ PyObject *parse_wcnf_impl(PyObject *txt_obj, PyObject *comment_lead)
|
|
|
143
147
|
continue;
|
|
144
148
|
|
|
145
149
|
if (comment_mask[(unsigned char)beg[0]]) {
|
|
146
|
-
if (
|
|
147
|
-
if (!
|
|
150
|
+
if (line_has_kind(beg, lend, "wcnf")) {
|
|
151
|
+
if (!parse_weight_preamble(beg, lend,
|
|
152
|
+
"invalid WCNF preamble", &topw))
|
|
148
153
|
goto fail;
|
|
149
154
|
}
|
|
155
|
+
else if (line_has_p(beg, lend)) {
|
|
156
|
+
PyErr_SetString(PyExc_ValueError, "invalid WCNF preamble");
|
|
157
|
+
goto fail;
|
|
158
|
+
}
|
|
150
159
|
else {
|
|
151
|
-
if (!
|
|
152
|
-
"invalid WCNF preamble", &topw))
|
|
160
|
+
if (!append_comment(comments, beg, lend))
|
|
153
161
|
goto fail;
|
|
154
162
|
}
|
|
155
163
|
continue;
|
|
@@ -249,10 +257,15 @@ PyObject *parse_cnfplus_impl(PyObject *txt_obj, PyObject *comment_lead)
|
|
|
249
257
|
continue;
|
|
250
258
|
|
|
251
259
|
if (comment_mask[(unsigned char)beg[0]]) {
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
|
|
260
|
+
if (line_has_kind(beg, lend, "cnf", "cnf+"))
|
|
261
|
+
continue;
|
|
262
|
+
if (line_has_p(beg, lend)) {
|
|
263
|
+
PyErr_SetString(PyExc_ValueError, "invalid CNF/CNF+ preamble");
|
|
264
|
+
goto fail;
|
|
255
265
|
}
|
|
266
|
+
|
|
267
|
+
if (!append_comment(comments, beg, lend))
|
|
268
|
+
goto fail;
|
|
256
269
|
continue;
|
|
257
270
|
}
|
|
258
271
|
|
|
@@ -366,13 +379,18 @@ PyObject *parse_wcnfplus_impl(PyObject *txt_obj, PyObject *comment_lead)
|
|
|
366
379
|
continue;
|
|
367
380
|
|
|
368
381
|
if (comment_mask[(unsigned char)beg[0]]) {
|
|
369
|
-
if (
|
|
370
|
-
if (!
|
|
382
|
+
if (line_has_kind(beg, lend, "wcnf", "wcnf+")) {
|
|
383
|
+
if (!parse_weight_preamble(beg, lend,
|
|
384
|
+
"invalid WCNF/WCNF+ preamble", &topw))
|
|
371
385
|
goto fail;
|
|
372
386
|
}
|
|
387
|
+
else if (line_has_p(beg, lend)) {
|
|
388
|
+
PyErr_SetString(PyExc_ValueError,
|
|
389
|
+
"invalid WCNF/WCNF+ preamble");
|
|
390
|
+
goto fail;
|
|
391
|
+
}
|
|
373
392
|
else {
|
|
374
|
-
if (!
|
|
375
|
-
"invalid WCNF+ preamble", &topw))
|
|
393
|
+
if (!append_comment(comments, beg, lend))
|
|
376
394
|
goto fail;
|
|
377
395
|
}
|
|
378
396
|
continue;
|
|
@@ -83,6 +83,32 @@ static inline bool read_span(const char * &p, const char *end,
|
|
|
83
83
|
return true;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// check whether a line starts with the exact DIMACS preamble marker
|
|
87
|
+
//=============================================================================
|
|
88
|
+
static inline bool line_has_p(const char *beg, const char *end)
|
|
89
|
+
{
|
|
90
|
+
const char *p = beg;
|
|
91
|
+
const char *tbeg, *tend;
|
|
92
|
+
|
|
93
|
+
return read_span(p, end, tbeg, tend) && span_eq(tbeg, tend, "p");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// check whether a line has an exact DIMACS preamble kind token
|
|
97
|
+
//=============================================================================
|
|
98
|
+
static inline bool line_has_kind(const char *beg, const char *end,
|
|
99
|
+
const char *kind1, const char *kind2 = NULL)
|
|
100
|
+
{
|
|
101
|
+
const char *p = beg;
|
|
102
|
+
const char *tbeg, *tend;
|
|
103
|
+
|
|
104
|
+
if (!read_span(p, end, tbeg, tend) || !span_eq(tbeg, tend, "p") ||
|
|
105
|
+
!read_span(p, end, tbeg, tend))
|
|
106
|
+
return false;
|
|
107
|
+
|
|
108
|
+
return span_eq(tbeg, tend, kind1) ||
|
|
109
|
+
(kind2 != NULL && span_eq(tbeg, tend, kind2));
|
|
110
|
+
}
|
|
111
|
+
|
|
86
112
|
// check whether a span has the syntax of a signed integer
|
|
87
113
|
//=============================================================================
|
|
88
114
|
static inline bool span_is_integer_like(const char *beg, const char *end)
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
// parse only the weighted preamble fields relevant to the native parser
|
|
14
14
|
//=============================================================================
|
|
15
15
|
bool parse_weight_preamble(const char *beg, const char *end,
|
|
16
|
-
const char *
|
|
16
|
+
const char *errmsg, PyObject **topw)
|
|
17
17
|
{
|
|
18
18
|
const char *p = beg;
|
|
19
19
|
const char *tbeg, *tend;
|
|
20
20
|
|
|
21
21
|
if (!read_span(p, end, tbeg, tend) || !span_eq(tbeg, tend, "p") ||
|
|
22
|
-
!read_span(p, end, tbeg, tend) ||
|
|
22
|
+
!read_span(p, end, tbeg, tend) ||
|
|
23
|
+
!(span_eq(tbeg, tend, "wcnf") || span_eq(tbeg, tend, "wcnf+")) ||
|
|
23
24
|
!read_span(p, end, tbeg, tend) ||
|
|
24
25
|
!read_span(p, end, tbeg, tend)) {
|
|
25
26
|
PyErr_SetString(PyExc_ValueError, errmsg);
|
|
@@ -76,7 +76,7 @@ typedef struct {
|
|
|
76
76
|
vector<long long> wght;
|
|
77
77
|
} plus_body;
|
|
78
78
|
|
|
79
|
-
bool parse_weight_preamble(const char *beg, const char *end,
|
|
79
|
+
bool parse_weight_preamble(const char *beg, const char *end,
|
|
80
80
|
const char *errmsg, PyObject **topw);
|
|
81
81
|
|
|
82
82
|
bool parse_clause_body(const char *p, const char *end,
|
|
@@ -4129,6 +4129,7 @@ class WCNF(object):
|
|
|
4129
4129
|
# normalize it, i.e. transform into a set of clauses
|
|
4130
4130
|
# with a positive weight
|
|
4131
4131
|
if negs:
|
|
4132
|
+
self.nv = max(self.nv, max(map(lambda cl: max(map(abs, cl[0])), negs)))
|
|
4132
4133
|
self.normalize_negatives(negs)
|
|
4133
4134
|
|
|
4134
4135
|
# if topw was unspecified and assigned to +infinity,
|
|
@@ -5380,6 +5381,7 @@ class WCNFPlus(WCNF, object):
|
|
|
5380
5381
|
# normalize it, i.e. transform into a set of clauses
|
|
5381
5382
|
# with a positive weight
|
|
5382
5383
|
if negs:
|
|
5384
|
+
self.nv = max(self.nv, max(map(lambda cl: max(map(abs, cl[0])), negs)))
|
|
5383
5385
|
self.normalize_negatives(negs)
|
|
5384
5386
|
|
|
5385
5387
|
# if topw was unspecified and assigned to +infinity,
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from io import StringIO
|
|
2
|
+
from decimal import Decimal
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
import pysat.formula as formula_mod
|
|
6
|
+
from pysat.formula import CNF, WCNF, CNFPlus, WCNFPlus
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_cnf_parser_comments_and_clauses():
|
|
10
|
+
s = 'c hello\np cnf 3 2\n-1 2 0\n3 0\n'
|
|
11
|
+
cnf = CNF(from_string=s)
|
|
12
|
+
|
|
13
|
+
assert cnf.comments == ['c hello']
|
|
14
|
+
assert cnf.clauses == [[-1, 2], [3]]
|
|
15
|
+
assert cnf.nv == 3
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_cnf_parser_from_fp():
|
|
19
|
+
fp = StringIO('c note\np cnf 2 1\n1 -2 0\n')
|
|
20
|
+
cnf = CNF(from_fp=fp)
|
|
21
|
+
|
|
22
|
+
assert cnf.comments == ['c note']
|
|
23
|
+
assert cnf.clauses == [[1, -2]]
|
|
24
|
+
assert cnf.nv == 2
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_wcnf_parser_decimal_and_negative_weights():
|
|
28
|
+
s = 'c weighted\np wcnf 3 3 10\n10 -1 2 0\n3.5 1 0\n-2 -3 0\n'
|
|
29
|
+
wcnf = WCNF(from_string=s)
|
|
30
|
+
|
|
31
|
+
assert wcnf.comments == ['c weighted']
|
|
32
|
+
assert wcnf.hard == [[-1, 2]]
|
|
33
|
+
assert wcnf.soft == [[1], [3]]
|
|
34
|
+
assert wcnf.wght == [Decimal('3.5'), 2]
|
|
35
|
+
assert wcnf.topw == 10
|
|
36
|
+
assert wcnf.nv == 3
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_cnfplus_parser_pb_and_cardinality():
|
|
40
|
+
s = 'c plus\np cnf+ 5 3\n1 -2 3 0\n1 2 3 <= 1\nw 2*1 3*-4 1*5 >= 3\n'
|
|
41
|
+
cnf = CNFPlus(from_string=s)
|
|
42
|
+
|
|
43
|
+
assert cnf.comments == ['c plus']
|
|
44
|
+
assert cnf.clauses == [[1, -2, 3]]
|
|
45
|
+
assert cnf.atmosts == [
|
|
46
|
+
[[1, 2, 3], 1],
|
|
47
|
+
[[-1, 4, -5], 3, [2, 3, 1]],
|
|
48
|
+
]
|
|
49
|
+
assert cnf.nv == 5
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_wcnfplus_parser_hard_soft_and_pb():
|
|
53
|
+
s = (
|
|
54
|
+
'c wplus\n'
|
|
55
|
+
'p wcnf+ 5 4 10\n'
|
|
56
|
+
'10 1 -2 0\n'
|
|
57
|
+
'2.5 3 0\n'
|
|
58
|
+
'h 1 2 3 <= 1\n'
|
|
59
|
+
'h w 2*1 3*-4 1*5 >= 3\n'
|
|
60
|
+
)
|
|
61
|
+
wcnf = WCNFPlus(from_string=s)
|
|
62
|
+
|
|
63
|
+
assert wcnf.comments == ['c wplus']
|
|
64
|
+
assert wcnf.hard == [[1, -2]]
|
|
65
|
+
assert wcnf.soft == [[3]]
|
|
66
|
+
assert wcnf.wght == [Decimal('2.5')]
|
|
67
|
+
assert wcnf.atms == [
|
|
68
|
+
[[1, 2, 3], 1],
|
|
69
|
+
[[-1, 4, -5], 3, [2, 3, 1]],
|
|
70
|
+
]
|
|
71
|
+
assert wcnf.topw == 10
|
|
72
|
+
assert wcnf.nv == 5
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_cnfplus_parser_accepts_plain_cnf_preamble():
|
|
76
|
+
s = 'c plain\np cnf 3 2\n1 0\n-2 3 0\n'
|
|
77
|
+
cnf = CNFPlus(from_string=s)
|
|
78
|
+
|
|
79
|
+
assert cnf.comments == ['c plain']
|
|
80
|
+
assert cnf.clauses == [[1], [-2, 3]]
|
|
81
|
+
assert cnf.atmosts == []
|
|
82
|
+
assert cnf.nv == 3
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_wcnfplus_parser_accepts_plain_wcnf_preamble():
|
|
86
|
+
s = 'c plain\np wcnf 3 3 5\n5 1 0\n1 -2 0\n2 3 0\n'
|
|
87
|
+
wcnf = WCNFPlus(from_string=s)
|
|
88
|
+
|
|
89
|
+
assert wcnf.comments == ['c plain']
|
|
90
|
+
assert wcnf.hard == [[1]]
|
|
91
|
+
assert wcnf.soft == [[-2], [3]]
|
|
92
|
+
assert wcnf.wght == [1, 2]
|
|
93
|
+
assert wcnf.atms == []
|
|
94
|
+
assert wcnf.topw == 5
|
|
95
|
+
assert wcnf.nv == 3
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_invalid_preamble_lines_raise_errors():
|
|
99
|
+
with pytest.raises(ValueError, match='invalid CNF/CNF\\+ preamble'):
|
|
100
|
+
CNFPlus(from_string='c x\np bullshit\np cnf 2 1\n1 0\n')
|
|
101
|
+
|
|
102
|
+
with pytest.raises(ValueError, match='invalid CNF/CNF\\+ preamble'):
|
|
103
|
+
CNFPlus(from_string='p cnfxyz\np cnf 2 1\n1 0\n')
|
|
104
|
+
|
|
105
|
+
with pytest.raises(ValueError, match='invalid WCNF/WCNF\\+ preamble'):
|
|
106
|
+
WCNFPlus(from_string='c y\np nonsense\np wcnf 2 1 5\n5 1 0\n')
|
|
107
|
+
|
|
108
|
+
with pytest.raises(ValueError, match='invalid WCNF/WCNF\\+ preamble'):
|
|
109
|
+
WCNFPlus(from_string='p wcnfxyz\np wcnf 2 1 5\n5 1 0\n')
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_python_wcnfplus_negative_normalization_keeps_nv():
|
|
113
|
+
old = formula_mod.pyformula_present
|
|
114
|
+
formula_mod.pyformula_present = False
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
s = 'p wcnf 4 3 10\n10 1 0\n3.5 -2 0\n-2 3 0\n'
|
|
118
|
+
wcnf = WCNFPlus(from_string=s)
|
|
119
|
+
finally:
|
|
120
|
+
formula_mod.pyformula_present = old
|
|
121
|
+
|
|
122
|
+
assert wcnf.hard == [[1]]
|
|
123
|
+
assert wcnf.soft == [[-2], [-3]]
|
|
124
|
+
assert wcnf.wght == [Decimal('3.5'), 2]
|
|
125
|
+
assert wcnf.topw == 10
|
|
126
|
+
assert wcnf.nv == 3
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_python_wcnf_negative_normalization_counts_aux_var():
|
|
130
|
+
old = formula_mod.pyformula_present
|
|
131
|
+
formula_mod.pyformula_present = False
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
s = 'p wcnf 5 2 10\n10 1 0\n-2 4 5 0\n'
|
|
135
|
+
wcnf = WCNF(from_string=s)
|
|
136
|
+
finally:
|
|
137
|
+
formula_mod.pyformula_present = old
|
|
138
|
+
|
|
139
|
+
assert wcnf.soft == [[-6]]
|
|
140
|
+
assert wcnf.wght == [2]
|
|
141
|
+
assert sorted(wcnf.hard) == sorted([[1], [6, -4], [6, -5], [-6, 4, 5]])
|
|
142
|
+
assert wcnf.topw == 10
|
|
143
|
+
assert wcnf.nv == 6
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
from io import StringIO
|
|
2
|
-
from decimal import Decimal
|
|
3
|
-
|
|
4
|
-
from pysat.formula import CNF, WCNF, CNFPlus, WCNFPlus
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_cnf_parser_comments_and_clauses():
|
|
8
|
-
s = 'c hello\np cnf 3 2\n-1 2 0\n3 0\n'
|
|
9
|
-
cnf = CNF(from_string=s)
|
|
10
|
-
|
|
11
|
-
assert cnf.comments == ['c hello']
|
|
12
|
-
assert cnf.clauses == [[-1, 2], [3]]
|
|
13
|
-
assert cnf.nv == 3
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_cnf_parser_from_fp():
|
|
17
|
-
fp = StringIO('c note\np cnf 2 1\n1 -2 0\n')
|
|
18
|
-
cnf = CNF(from_fp=fp)
|
|
19
|
-
|
|
20
|
-
assert cnf.comments == ['c note']
|
|
21
|
-
assert cnf.clauses == [[1, -2]]
|
|
22
|
-
assert cnf.nv == 2
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def test_wcnf_parser_decimal_and_negative_weights():
|
|
26
|
-
s = 'c weighted\np wcnf 3 3 10\n10 -1 2 0\n3.5 1 0\n-2 -3 0\n'
|
|
27
|
-
wcnf = WCNF(from_string=s)
|
|
28
|
-
|
|
29
|
-
assert wcnf.comments == ['c weighted']
|
|
30
|
-
assert wcnf.hard == [[-1, 2]]
|
|
31
|
-
assert wcnf.soft == [[1], [3]]
|
|
32
|
-
assert wcnf.wght == [Decimal('3.5'), 2]
|
|
33
|
-
assert wcnf.topw == 10
|
|
34
|
-
assert wcnf.nv == 3
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def test_cnfplus_parser_pb_and_cardinality():
|
|
38
|
-
s = 'c plus\np cnf+ 5 3\n1 -2 3 0\n1 2 3 <= 1\nw 2*1 3*-4 1*5 >= 3\n'
|
|
39
|
-
cnf = CNFPlus(from_string=s)
|
|
40
|
-
|
|
41
|
-
assert cnf.comments == ['c plus']
|
|
42
|
-
assert cnf.clauses == [[1, -2, 3]]
|
|
43
|
-
assert cnf.atmosts == [
|
|
44
|
-
[[1, 2, 3], 1],
|
|
45
|
-
[[-1, 4, -5], 3, [2, 3, 1]],
|
|
46
|
-
]
|
|
47
|
-
assert cnf.nv == 5
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_wcnfplus_parser_hard_soft_and_pb():
|
|
51
|
-
s = (
|
|
52
|
-
'c wplus\n'
|
|
53
|
-
'p wcnf+ 5 4 10\n'
|
|
54
|
-
'10 1 -2 0\n'
|
|
55
|
-
'2.5 3 0\n'
|
|
56
|
-
'h 1 2 3 <= 1\n'
|
|
57
|
-
'h w 2*1 3*-4 1*5 >= 3\n'
|
|
58
|
-
)
|
|
59
|
-
wcnf = WCNFPlus(from_string=s)
|
|
60
|
-
|
|
61
|
-
assert wcnf.comments == ['c wplus']
|
|
62
|
-
assert wcnf.hard == [[1, -2]]
|
|
63
|
-
assert wcnf.soft == [[3]]
|
|
64
|
-
assert wcnf.wght == [Decimal('2.5')]
|
|
65
|
-
assert wcnf.atms == [
|
|
66
|
-
[[1, 2, 3], 1],
|
|
67
|
-
[[-1, 4, -5], 3, [2, 3, 1]],
|
|
68
|
-
]
|
|
69
|
-
assert wcnf.topw == 10
|
|
70
|
-
assert wcnf.nv == 5
|
|
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
|
|
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
|