python-sat 1.8.dev25__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.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 (48) hide show
  1. pycard.cpython-314-x86_64-linux-gnu.so +0 -0
  2. pysat/__init__.py +24 -0
  3. pysat/_fileio.py +209 -0
  4. pysat/_utils.py +58 -0
  5. pysat/allies/__init__.py +0 -0
  6. pysat/allies/approxmc.py +385 -0
  7. pysat/allies/unigen.py +435 -0
  8. pysat/card.py +802 -0
  9. pysat/engines.py +1302 -0
  10. pysat/examples/__init__.py +0 -0
  11. pysat/examples/bbscan.py +663 -0
  12. pysat/examples/bica.py +691 -0
  13. pysat/examples/fm.py +527 -0
  14. pysat/examples/genhard.py +516 -0
  15. pysat/examples/hitman.py +653 -0
  16. pysat/examples/lbx.py +638 -0
  17. pysat/examples/lsu.py +496 -0
  18. pysat/examples/mcsls.py +610 -0
  19. pysat/examples/models.py +189 -0
  20. pysat/examples/musx.py +344 -0
  21. pysat/examples/optux.py +710 -0
  22. pysat/examples/primer.py +620 -0
  23. pysat/examples/rc2.py +1858 -0
  24. pysat/examples/usage.py +63 -0
  25. pysat/formula.py +5619 -0
  26. pysat/pb.py +463 -0
  27. pysat/process.py +363 -0
  28. pysat/solvers.py +7591 -0
  29. pysolvers.cpython-314-x86_64-linux-gnu.so +0 -0
  30. python_sat-1.8.dev25.data/scripts/approxmc.py +385 -0
  31. python_sat-1.8.dev25.data/scripts/bbscan.py +663 -0
  32. python_sat-1.8.dev25.data/scripts/bica.py +691 -0
  33. python_sat-1.8.dev25.data/scripts/fm.py +527 -0
  34. python_sat-1.8.dev25.data/scripts/genhard.py +516 -0
  35. python_sat-1.8.dev25.data/scripts/lbx.py +638 -0
  36. python_sat-1.8.dev25.data/scripts/lsu.py +496 -0
  37. python_sat-1.8.dev25.data/scripts/mcsls.py +610 -0
  38. python_sat-1.8.dev25.data/scripts/models.py +189 -0
  39. python_sat-1.8.dev25.data/scripts/musx.py +344 -0
  40. python_sat-1.8.dev25.data/scripts/optux.py +710 -0
  41. python_sat-1.8.dev25.data/scripts/primer.py +620 -0
  42. python_sat-1.8.dev25.data/scripts/rc2.py +1858 -0
  43. python_sat-1.8.dev25.data/scripts/unigen.py +435 -0
  44. python_sat-1.8.dev25.dist-info/METADATA +45 -0
  45. python_sat-1.8.dev25.dist-info/RECORD +48 -0
  46. python_sat-1.8.dev25.dist-info/WHEEL +6 -0
  47. python_sat-1.8.dev25.dist-info/licenses/LICENSE.txt +21 -0
  48. python_sat-1.8.dev25.dist-info/top_level.txt +3 -0
pysat/process.py ADDED
@@ -0,0 +1,363 @@
1
+ #!/usr/bin/env python
2
+ #-*- coding:utf-8 -*-
3
+ ##
4
+ ## process.py
5
+ ##
6
+ ## Created on: Jan 17, 2023
7
+ ## Author: Christos Karamanos
8
+ ## E-mail: karamanos.christos@gmail.com
9
+ ##
10
+
11
+ """
12
+ ===============
13
+ List of classes
14
+ ===============
15
+
16
+ .. autosummary::
17
+ :nosignatures:
18
+
19
+ Processor
20
+
21
+ ==================
22
+ Module description
23
+ ==================
24
+
25
+ This module provides access to the preprocessor functionality of `CaDiCaL
26
+ 1.5.3 <https://github.com/arminbiere/cadical>`__. It can be used to
27
+ process [1]_ (also see references therein) a given CNF formula and output
28
+ a another formula, which is guaranteed to be *equisatisfiable* with the
29
+ original formula. The processor can be invoked for a user-provided number
30
+ of rounds. Also, the following preprocessing techniques can be used when
31
+ running the processor:
32
+
33
+ - blocked clause elimination
34
+ - covered clause elimination
35
+ - globally-blocked clause elimination
36
+ - equivalent literal substitution
37
+ - bounded variable elimination
38
+ - failed literal probing
39
+ - hyper binary resolution
40
+ - clause subsumption
41
+ - clause vivification
42
+
43
+ .. [1] Armin Biere, Matti Järvisalo, Benjamin Kiesl. *Preprocessing in SAT
44
+ Solving*. In *Handbook of Satisfiability - Second Edition*. pp. 391-435
45
+
46
+ Importantly, the module provides a user with a possibility to freeze some
47
+ of the formula's variables so that they aren't eliminated, which may be
48
+ useful when unsatisfiability preserving processing is required - usable in
49
+ MCS and MUS enumeration as well as MaxSAT solving.
50
+
51
+ Note that the numerous parameters used in CaDiCaL for tweaking the
52
+ preprocessor's behavior are currently unavailable here. (Default values
53
+ are used.)
54
+
55
+ .. code-block:: python
56
+
57
+ >>> from pysat.formula import CNF
58
+ >>> from pysat.process import Processor
59
+ >>> from pysat.solvers import Solver
60
+ >>>
61
+ >>> cnf = CNF(from_clauses=[[1, 2], [3, 2], [-1, 4, -2], [3, -2], [3, 4]])
62
+ >>> processor = Processor(bootstrap_with=cnf)
63
+ >>>
64
+ >>> processed = processor.process()
65
+ >>> print(processed.clauses)
66
+ []
67
+ >>> print(processed.status)
68
+ True
69
+ >>>
70
+ >>> with Solver(bootstrap_with=processed) as solver:
71
+ ... solver.solve()
72
+ True
73
+ ... print('proc model:', solver.get_model())
74
+ proc model: []
75
+ ... print('orig model:', processor.restore(solver.get_model()))
76
+ orig model: [1, -2, 3, -4]
77
+ >>>
78
+ >>> processor.delete()
79
+
80
+ ==============
81
+ Module details
82
+ ==============
83
+ """
84
+
85
+ #
86
+ #==============================================================================
87
+ from pysat.formula import CNF
88
+ from pysat.solvers import Cadical153
89
+
90
+
91
+ #
92
+ #==============================================================================
93
+ class Processor(object):
94
+ """
95
+ This class provides interface to CaDiCaL's preprocessor. The only
96
+ input parameter is ``bootstrap_with``, which is expected to be a
97
+ :class:`.CNF` formula or a list (or iterable) of clauses.
98
+
99
+ :param bootstrap_with: a list of clauses for processor initialization.
100
+ :type bootstrap_with: :class:`.CNF` or iterable(iterable(int))
101
+
102
+ Once created and used, a processor must be deleted with the
103
+ :meth:`delete` method. Alternatively, if created using the ``with``
104
+ statement, deletion is done automatically when the end of the ``with``
105
+ block is reached. It is *important* to keep the processor if a user
106
+ wants to restore a model of the original formula.
107
+
108
+ The main methods of this class are :meth:`process` and
109
+ :meth:`restore`. The former calls CaDiCaL's preprocessor while the
110
+ latter can be used to reconstruct a model of the original formula
111
+ given a model for the processed formula as illustrated below.
112
+
113
+ Note how keeping the :class:`Processor` object is needed for model
114
+ restoration. (If it is deleted, the information needed for model
115
+ reconstruction is lost.)
116
+
117
+ .. code-block:: python
118
+
119
+ >>> from pysat.process import Processor
120
+ >>> from pysat.solvers import Solver
121
+ >>>
122
+ >>> processor = Processor(bootstrap_with=[[-1, 2], [1, -2]])
123
+ >>> processor.append_formula([[-2, 3], [1]])
124
+ >>> processor.add_clause([-3, 4])
125
+ >>>
126
+ >>> processed = processor.process()
127
+ >>> print(processed.clauses)
128
+ []
129
+ >>> print(processed.status)
130
+ True
131
+ >>>
132
+ >>> with Solver(bootstrap_with=processed) as solver:
133
+ ... solver.solve()
134
+ True
135
+ ... print('proc model:', solver.get_model())
136
+ proc model: []
137
+ ... print('orig model:', processor.restore(solver.get_model()))
138
+ orig model: [1, 2, 3, 4]
139
+ >>>
140
+ >>> processor.delete()
141
+ """
142
+
143
+ def __init__(self, bootstrap_with=None):
144
+ """
145
+ Basic constructor.
146
+ """
147
+
148
+ # immediately creating a CaDiCaL object
149
+ self.cadical = Cadical153()
150
+
151
+ # status of processor is True by default meaning
152
+ # that the input formula *is not* unsatisfiable
153
+ self.status = True
154
+
155
+ if bootstrap_with:
156
+ self.append_formula(bootstrap_with)
157
+
158
+ def __del__(self):
159
+ """
160
+ Default destructor.
161
+ """
162
+
163
+ self.delete()
164
+
165
+ def __enter__(self):
166
+ """
167
+ 'with' constructor.
168
+ """
169
+
170
+ return self
171
+
172
+ def __exit__(self, exc_type, exc_value, traceback):
173
+ """
174
+ 'with' destructor.
175
+ """
176
+
177
+ self.delete()
178
+
179
+ def delete(self):
180
+ """
181
+ Actual destructor.
182
+ """
183
+
184
+ if self.cadical:
185
+ self.cadical.delete()
186
+ self.cadical = None
187
+
188
+ def add_clause(self, clause):
189
+ """
190
+ Add a single clause to the processor.
191
+
192
+ :param clause: a clause to add
193
+ :type clause: list(int) or any iterable(int)
194
+
195
+ .. code-block:: python
196
+
197
+ >>> processor = Processor()
198
+ >>> processor.add_clause([-1, 2, 3])
199
+ """
200
+
201
+ if self.cadical:
202
+ self.cadical.add_clause(clause)
203
+
204
+ def append_formula(self, formula):
205
+ """
206
+ Add a given list of clauses into the solver.
207
+
208
+ :param formula: a list of clauses.
209
+ :type formula: iterable(iterable(int)), or :class:`.CNF`
210
+
211
+ .. code-block:: python
212
+
213
+ >>> cnf = CNF()
214
+ ... # assume the formula contains clauses
215
+ >>> processor = Processor()
216
+ >>> processor.append_formula(cnf)
217
+ """
218
+
219
+ if self.cadical:
220
+ self.cadical.append_formula(formula)
221
+
222
+ def process(self, rounds=1, block=False, cover=False, condition=False,
223
+ decompose=True, elim=True, probe=True, probehbr=True,
224
+ subsume=True, vivify=True, freeze=[]):
225
+ """
226
+ Runs CaDiCaL's preprocessor for the internal formula for a given
227
+ number of rounds and using the techniques specified in the
228
+ arguments. Note that the default values of all the arguments used
229
+ are set as in the default configuration of CaDiCaL 1.5.3.
230
+
231
+ As the result, the method returns a :class:`.CNF` object
232
+ containing the processed formula. Additionally to the clauses, the
233
+ formula contains a ``status`` variable, which is set to ``False``
234
+ if the preprocessor found the original formula to be unsatisfiable
235
+ (and ``True`` otherwise). The same status value is set to the
236
+ ``status`` variable of the processor itself.
237
+
238
+ It is important to note that activation of some of the
239
+ preprocessing techniques conditionally depends on the activation
240
+ of other preprocessing techniques. For instance, subsumed, blocked
241
+ and covered clause elimination is invoked only if bounded variable
242
+ elimination is active. Subsumption elimination in turn may trigger
243
+ vivification and transitive reduction if the corresponding flags
244
+ are set.
245
+
246
+ Finally, note that the ``freeze`` argument can be used to keep
247
+ some of the variables of the original formula unchanged during
248
+ preprocessing. If convenient, the list may contain literals too
249
+ (negative integers).
250
+
251
+ :param rounds: number of preprocessing rounds
252
+ :type rounds: int
253
+
254
+ :param block: apply blocked clause elimination
255
+ :type block: bool
256
+
257
+ :param cover: apply covered clause elimination
258
+ :type cover: bool
259
+
260
+ :param condition: detect conditional autarkies and apply globally-blocked clause elimination
261
+ :type condition: bool
262
+
263
+ :param decompose: detect strongly connected components (SCCs) in the binary implication graph (BIG) and apply equivalent literal substitution (ELS)
264
+ :type decompose: bool
265
+
266
+ :param elim: apply bounded variable elimination
267
+ :type elim: bool
268
+
269
+ :param probe: apply failed literal probing
270
+ :type probe: bool
271
+
272
+ :param probehbr: learn hyper binary resolvents while probing
273
+ :type probehbr: bool
274
+
275
+ :param subsume: apply global forward clause subsumption
276
+ :type subsume: bool
277
+
278
+ :param vivify: apply clause vivification
279
+ :type vivify: bool
280
+
281
+ :param freeze: a list of variables / literals to be kept during preprocessing
282
+ :type freeze: list(int) or any iterable(int)
283
+
284
+ :return: processed formula
285
+ :rtype: :class:`.CNF`
286
+
287
+ .. code-block:: python
288
+
289
+ >>> from pysat.process import Processor
290
+ >>>
291
+ >>> processor = Processor(bootstrap_with=[[-1, 2], [-2, 3], [-1, -3]])
292
+ >>> processor.add_clause([1])
293
+ >>>
294
+ >>> processed = processor.process()
295
+ >>> print(processed.clauses)
296
+ [[]]
297
+ >>> print(processed.status)
298
+ False # this means the processor decided the formula to be unsatisfiable
299
+ >>>
300
+ >>> with Solver(bootstrap_with=processed) as solver:
301
+ ... solver.solve()
302
+ False
303
+ >>> processor.delete()
304
+ """
305
+
306
+ if self.cadical:
307
+ self.status, result = self.cadical.process(rounds, block, cover,
308
+ condition, decompose,
309
+ elim, probe, probehbr,
310
+ subsume, vivify,
311
+ freeze)
312
+
313
+ # making the status Boolean
314
+ self.status = False if self.status == 20 else True
315
+
316
+ # saving it in the output formula
317
+ result = CNF(from_clauses=result)
318
+ result.status = self.status
319
+
320
+ return result
321
+
322
+ def get_status(self):
323
+ """
324
+ Preprocessor's status as the result of the previous call to
325
+ :meth:`process()`. A ``False`` status indicates that the formula
326
+ is found to be unsatisfiable by the preprocessor. Otherwise, the
327
+ status equals ``True``.
328
+
329
+ :rtype: bool
330
+ """
331
+
332
+ return self.status
333
+
334
+ def restore(self, model):
335
+ """
336
+ Reconstruct a model for the original formula given a model for the
337
+ processed formula. Done by using CaDiCaL's extend() and
338
+ reconstruction stack functionality.
339
+
340
+ :param model: a model for the preprocessed formula
341
+ :type model: iterable(int)
342
+
343
+ :return: extended model satisfying the original formula
344
+ :rtype: list(int)
345
+
346
+ .. code-block:: python
347
+
348
+ >>> from pysat.process import Processor
349
+ >>>
350
+ >>> with Processor(bootstrap_with=[[-1, 2], [-2, 3]]) as proc:
351
+ ... proc.add_clause([1])
352
+ ... processed = proc.process()
353
+ ... with Solver(bootstrap_with=processed) as solver:
354
+ ... solver.solve()
355
+ ... print('model:', proc.restore(solver.get_model()))
356
+ ...
357
+ model: [1, 2, 3]
358
+ """
359
+
360
+ assert self.status, 'Cannot restore a model for an unsatisfiable formula!'
361
+
362
+ if self.cadical:
363
+ return self.cadical.restore(model)