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