python-sat 1.9.dev5__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.
Files changed (119) hide show
  1. {python_sat-1.9.dev5/python_sat.egg-info → python_sat-1.9.dev7}/PKG-INFO +1 -1
  2. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/rc2.py +7 -0
  3. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_parse.cc +32 -14
  4. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_scan.hh +26 -0
  5. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_weight.cc +3 -2
  6. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pyformula.hh +1 -1
  7. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/__init__.py +1 -1
  8. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/engines.py +35 -9
  9. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/formula.py +2 -0
  10. {python_sat-1.9.dev5 → python_sat-1.9.dev7/python_sat.egg-info}/PKG-INFO +1 -1
  11. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/python_sat.egg-info/SOURCES.txt +2 -0
  12. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/minisatep.patch +1 -1
  13. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/pysolvers.cc +1103 -919
  14. python_sat-1.9.dev7/tests/test_empty_extclause.py +45 -0
  15. python_sat-1.9.dev7/tests/test_formula_parsing.py +143 -0
  16. python_sat-1.9.dev7/tests/test_oom.py +74 -0
  17. python_sat-1.9.dev5/tests/test_formula_parsing.py +0 -70
  18. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/LICENSE.txt +0 -0
  19. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/MANIFEST.in +0 -0
  20. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/README.rst +0 -0
  21. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/allies/__init__.py +0 -0
  22. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/allies/approxmc.py +0 -0
  23. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/allies/unigen.py +0 -0
  24. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/bitwise.hh +0 -0
  25. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/card.hh +0 -0
  26. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/clset.hh +0 -0
  27. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/common.hh +0 -0
  28. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/itot.hh +0 -0
  29. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/ladder.hh +0 -0
  30. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/mto.hh +0 -0
  31. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/pairwise.hh +0 -0
  32. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/ptypes.hh +0 -0
  33. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/pycard.cc +0 -0
  34. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/seqcounter.hh +0 -0
  35. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/sortcard.hh +0 -0
  36. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/cardenc/utils.hh +0 -0
  37. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/__init__.py +0 -0
  38. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/bbscan.py +0 -0
  39. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/bica.py +0 -0
  40. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/fm.py +0 -0
  41. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/genhard.py +0 -0
  42. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/hitman.py +0 -0
  43. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/lbx.py +0 -0
  44. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/lsu.py +0 -0
  45. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/mcsls.py +0 -0
  46. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/models.py +0 -0
  47. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/musx.py +0 -0
  48. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/optux.py +0 -0
  49. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/primer.py +0 -0
  50. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/examples/usage.py +0 -0
  51. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_plus.cc +0 -0
  52. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_plus.hh +0 -0
  53. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_py.hh +0 -0
  54. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pf_weight.hh +0 -0
  55. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/formula/pyformula.cc +0 -0
  56. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/_fileio.py +0 -0
  57. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/_utils.py +0 -0
  58. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/card.py +0 -0
  59. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/integer.py +0 -0
  60. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/pb.py +0 -0
  61. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/process.py +0 -0
  62. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/pysat/solvers.py +0 -0
  63. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/python_sat.egg-info/dependency_links.txt +0 -0
  64. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/python_sat.egg-info/requires.txt +0 -0
  65. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/python_sat.egg-info/top_level.txt +0 -0
  66. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/requirements.txt +0 -0
  67. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/setup.cfg +0 -0
  68. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/setup.py +0 -0
  69. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/cadical103.tar.gz +0 -0
  70. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/cadical153.tar.gz +0 -0
  71. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/cadical195.tar.gz +0 -0
  72. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/cadical300.tar.gz +0 -0
  73. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/glucose30.tar.gz +0 -0
  74. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/glucose41.tar.gz +0 -0
  75. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/glucose421.tar.gz +0 -0
  76. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/lingeling.tar.gz +0 -0
  77. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/maplechrono.zip +0 -0
  78. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/maplecm.zip +0 -0
  79. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/maplesat.zip +0 -0
  80. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/mergesat3.tar.gz +0 -0
  81. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/minicard.tar.gz +0 -0
  82. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/minisat22.tar.gz +0 -0
  83. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/minisatgh.zip +0 -0
  84. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/cadical103.patch +0 -0
  85. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/cadical153.patch +0 -0
  86. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/cadical195.patch +0 -0
  87. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/cadical300.patch +0 -0
  88. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/glucose30.patch +0 -0
  89. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/glucose41.patch +0 -0
  90. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/glucose421.patch +0 -0
  91. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/gluecard30.patch +0 -0
  92. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/gluecard41.patch +0 -0
  93. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/kissat404.patch +0 -0
  94. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/lingeling.patch +0 -0
  95. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/maplechrono.patch +0 -0
  96. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/maplecm.patch +0 -0
  97. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/maplesat.patch +0 -0
  98. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/mergesat3.patch +0 -0
  99. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/minicard.patch +0 -0
  100. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/minisat22.patch +0 -0
  101. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/patches/minisatgh.patch +0 -0
  102. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/solvers/prepare.py +0 -0
  103. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_accum_stats.py +0 -0
  104. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_atmost.py +0 -0
  105. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_atmost1.py +0 -0
  106. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_atmostk.py +0 -0
  107. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_boolengine.py +0 -0
  108. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_clausification.py +0 -0
  109. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_cnf.py +0 -0
  110. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_encode_pb_conditional.py +0 -0
  111. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_equals1.py +0 -0
  112. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_formula_unique.py +0 -0
  113. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_idpool.py +0 -0
  114. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_integer.py +0 -0
  115. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_process.py +0 -0
  116. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_propagate.py +0 -0
  117. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_unique_model.py +0 -0
  118. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_unique_mus.py +0 -0
  119. {python_sat-1.9.dev5 → python_sat-1.9.dev7}/tests/test_warmstart.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.9.dev5
3
+ Version: 1.9.dev7
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
@@ -409,6 +409,9 @@ class RC2(object):
409
409
  :type clause: iterable(int)
410
410
  :type weight: int
411
411
 
412
+ :return: selector literal for a soft clause and ``None`` for a hard one
413
+ :rtype: int or None
414
+
412
415
  .. code-block:: python
413
416
 
414
417
  >>> from pysat.examples.rc2 import RC2
@@ -449,6 +452,8 @@ class RC2(object):
449
452
  '{0} does not support native cardinality constraints. Make sure you use the right type of formula.'.format(self.solver)
450
453
 
451
454
  self.oracle.add_atmost(cl, clause[1], weights=clause[2] if len(clause) == 3 else [])
455
+
456
+ return None
452
457
  else:
453
458
  # soft clauses should be augmented with a selector
454
459
  selv = cl[0] # for a unit clause, no selector is needed
@@ -472,6 +477,8 @@ class RC2(object):
472
477
  self.sall.append(selv)
473
478
  self.sels_set.add(selv)
474
479
 
480
+ return selv
481
+
475
482
  def delete(self):
476
483
  """
477
484
  Explicit destructor of the internal SAT oracle and all the
@@ -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 (!line_starts(beg, lend, "p cnf ")) {
51
- if (!append_comment(comments, beg, lend))
52
- goto fail;
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 (!line_starts(beg, lend, "p wcnf ")) {
147
- if (!append_comment(comments, beg, lend))
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 (!parse_weight_preamble(beg, lend, "wcnf",
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 (!line_starts(beg, lend, "p cnf+")) {
253
- if (!append_comment(comments, beg, lend))
254
- goto fail;
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 (!line_starts(beg, lend, "p wcnf+")) {
370
- if (!append_comment(comments, beg, lend))
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 (!parse_weight_preamble(beg, lend, "wcnf+",
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 *kind, const char *errmsg, PyObject **topw)
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) || !span_eq(tbeg, tend, kind) ||
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, const char *kind,
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,
@@ -10,7 +10,7 @@
10
10
 
11
11
  # current version
12
12
  #==============================================================================
13
- VERSION = (1, 9, 'dev', 5)
13
+ VERSION = (1, 9, 'dev', 7)
14
14
 
15
15
 
16
16
  # PEP440 Format
@@ -564,8 +564,11 @@ class Propagator(object):
564
564
  def provide_reason(self, lit: int) -> List[int]:
565
565
  pass # explain why a given literal was propagated
566
566
 
567
+ def has_clause(self) -> bool:
568
+ return False # optional: report whether an external clause exists
569
+
567
570
  def add_clause(self) -> List[int]:
568
- return [] # add an(y) external clause to the solver
571
+ return [] # if has_clause() is used, may also be the empty clause
569
572
  """
570
573
 
571
574
  def __init__(self):
@@ -687,10 +690,9 @@ class Propagator(object):
687
690
 
688
691
  def add_clause(self) -> List[int]:
689
692
  """
690
- The method is called by the solver to add an external clause if
691
- there is any. The clause can be arbitrary but if it is
692
- root-satisfied or tautological, the solver will ignore it without
693
- learning it.
693
+ The method is called by the solver to obtain an external clause.
694
+ The clause can be arbitrary but if it is root-satisfied or
695
+ tautological, the solver will ignore it without learning it.
694
696
 
695
697
  Root-falsified literals are eagerly removed from the clause.
696
698
  Falsified clauses trigger conflict analysis, propagating clauses
@@ -700,6 +702,19 @@ class Propagator(object):
700
702
  An empty clause (or root falsified clause, see above) makes the
701
703
  formula unsatisfiable and stops the search immediately.
702
704
 
705
+ .. note::
706
+
707
+ The exact meaning of returning ``[]`` depends on whether the
708
+ propagator defines method ``has_clause()``.
709
+
710
+ - If ``has_clause()`` is defined, the solver first queries it.
711
+ Whenever it returns ``True``, the follow-up call of
712
+ :meth:`add_clause` is expected to return the clause itself,
713
+ and ``[]`` denotes the actual empty clause.
714
+ - Otherwise, if ``has_clause()`` is undefined, returning
715
+ ``[]`` from :meth:`add_clause` is interpreted as saying that
716
+ there is no clause to add.
717
+
703
718
  :rtype: iterable(int)
704
719
  """
705
720
 
@@ -1283,14 +1298,25 @@ class BooleanEngine(Propagator):
1283
1298
 
1284
1299
  return [lit] + self.origin[lit].justify(lit)
1285
1300
 
1301
+ def has_clause(self):
1302
+ """
1303
+ Check whether the engine currently has an external clause to add.
1304
+ When queried separately by the solver, this lets
1305
+ :meth:`add_clause` return ``[]`` as an actual empty clause.
1306
+ """
1307
+
1308
+ return self.falsified is not None
1309
+
1286
1310
  def add_clause(self):
1287
1311
  """
1288
- Extract a new clause to add to the solver if one exists; return an
1289
- empty clause ``[]`` otherwise.
1312
+ Extract the external clause previously announced by
1313
+ :meth:`has_clause`.
1290
1314
  """
1291
1315
 
1292
- if self.falsified is None:
1293
- return []
1316
+ # # old behaviour checking if we have a clause to add;
1317
+ # # commenting this out because we have has_clause() now
1318
+ # if self.falsified is None:
1319
+ # return []
1294
1320
 
1295
1321
  to_add = self.falsified.explain_failure()
1296
1322
 
@@ -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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.9.dev5
3
+ Version: 1.9.dev7
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
@@ -102,12 +102,14 @@ tests/test_atmostk.py
102
102
  tests/test_boolengine.py
103
103
  tests/test_clausification.py
104
104
  tests/test_cnf.py
105
+ tests/test_empty_extclause.py
105
106
  tests/test_encode_pb_conditional.py
106
107
  tests/test_equals1.py
107
108
  tests/test_formula_parsing.py
108
109
  tests/test_formula_unique.py
109
110
  tests/test_idpool.py
110
111
  tests/test_integer.py
112
+ tests/test_oom.py
111
113
  tests/test_process.py
112
114
  tests/test_propagate.py
113
115
  tests/test_unique_model.py
@@ -623,7 +623,7 @@ diff -Naur solvers/minisatep/core/Solver.cc solvers/mep/core/Solver.cc
623
623
  - for (int i = 0; i < nVars(); i++) {
624
624
  - if (value(i) != Minisat::l_Undef) {
625
625
  - res.push_back(Minisat::LitToint(Minisat::mkLit(i, value(i) == Minisat::l_False)));
626
- + std::vector<int> res; res.reserve(nVars() - 1);
626
+ + std::vector<int> res; res.reserve(nVars() > 0 ? nVars() - 1 : 0);
627
627
  + for (int i = 1; i < nVars(); i++) {
628
628
  + if (value(i) != mep_l_Undef) {
629
629
  + res.push_back(i * (value(i) == mep_l_False ? -1 : 1));