python-sat 1.8.dev27__cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.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-314t-aarch64-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 +1999 -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-314t-aarch64-linux-gnu.so +0 -0
  30. python_sat-1.8.dev27.data/scripts/approxmc.py +385 -0
  31. python_sat-1.8.dev27.data/scripts/bbscan.py +663 -0
  32. python_sat-1.8.dev27.data/scripts/bica.py +691 -0
  33. python_sat-1.8.dev27.data/scripts/fm.py +527 -0
  34. python_sat-1.8.dev27.data/scripts/genhard.py +516 -0
  35. python_sat-1.8.dev27.data/scripts/lbx.py +638 -0
  36. python_sat-1.8.dev27.data/scripts/lsu.py +496 -0
  37. python_sat-1.8.dev27.data/scripts/mcsls.py +610 -0
  38. python_sat-1.8.dev27.data/scripts/models.py +189 -0
  39. python_sat-1.8.dev27.data/scripts/musx.py +344 -0
  40. python_sat-1.8.dev27.data/scripts/optux.py +710 -0
  41. python_sat-1.8.dev27.data/scripts/primer.py +620 -0
  42. python_sat-1.8.dev27.data/scripts/rc2.py +1999 -0
  43. python_sat-1.8.dev27.data/scripts/unigen.py +435 -0
  44. python_sat-1.8.dev27.dist-info/METADATA +45 -0
  45. python_sat-1.8.dev27.dist-info/RECORD +48 -0
  46. python_sat-1.8.dev27.dist-info/WHEEL +6 -0
  47. python_sat-1.8.dev27.dist-info/licenses/LICENSE.txt +21 -0
  48. python_sat-1.8.dev27.dist-info/top_level.txt +3 -0
@@ -0,0 +1,516 @@
1
+ #!python
2
+ #-*- coding:utf-8 -*-
3
+ ##
4
+ ## genhard.py
5
+ ##
6
+ ## Created on: Mar 6, 2018
7
+ ## Author: Alexey S. Ignatiev
8
+ ## E-mail: aignatiev@ciencias.ulisboa.pt
9
+ ##
10
+
11
+ """
12
+ ===============
13
+ List of classes
14
+ ===============
15
+
16
+ .. autosummary::
17
+ :nosignatures:
18
+
19
+ CB
20
+ GT
21
+ PAR
22
+ PHP
23
+
24
+ ==================
25
+ Module description
26
+ ==================
27
+
28
+ This module is designed to provide a few examples illustrating how PySAT
29
+ can be used for encoding practical problems into CNF formulas. These
30
+ include combinatorial principles that are widely studied from the
31
+ propositional proof complexity perspective. Namely, encodings for the
32
+ following principles are implemented: *pigeonhole principle* (:class:`PHP`)
33
+ [1]_, *ordering (greater-than) principle* (:class:`GT`) [2]_, *mutilated
34
+ chessboard principle* (:class:`CB`) [3]_, and *parity principle*
35
+ (:class:`PAR`) [4]_.
36
+
37
+ .. [1] Stephen A. Cook, Robert A. Reckhow. *The Relative Efficiency of
38
+ Propositional Proof Systems*. J. Symb. Log. 44(1). 1979. pp. 36-50
39
+
40
+ .. [2] Balakrishnan Krishnamurthy. *Short Proofs for Tricky Formulas*. Acta
41
+ Informatica 22(3). 1985. pp. 253-275
42
+
43
+ .. [3] Michael Alekhnovich. *Mutilated Chessboard Problem Is Exponentially
44
+ Hard For Resolution*. Theor. Comput. Sci. 310(1-3). 2004. pp. 513-525
45
+
46
+ .. [4] Miklós Ajtai. *Parity And The Pigeonhole Principle*. Feasible
47
+ Mathematics. 1990. pp. 1–24
48
+
49
+ The module can be used as an executable (the list of available command-line
50
+ options can be shown using ``genhard.py -h``) in the following way
51
+
52
+ ::
53
+
54
+ $ genhard.py -t php -n 3 -v
55
+ c PHP formula for 4 pigeons and 3 holes
56
+ c (pigeon, hole) pair: (1, 1); bool var: 1
57
+ c (pigeon, hole) pair: (1, 2); bool var: 2
58
+ c (pigeon, hole) pair: (1, 3); bool var: 3
59
+ c (pigeon, hole) pair: (2, 1); bool var: 4
60
+ c (pigeon, hole) pair: (2, 2); bool var: 5
61
+ c (pigeon, hole) pair: (2, 3); bool var: 6
62
+ c (pigeon, hole) pair: (3, 1); bool var: 7
63
+ c (pigeon, hole) pair: (3, 2); bool var: 8
64
+ c (pigeon, hole) pair: (3, 3); bool var: 9
65
+ c (pigeon, hole) pair: (4, 1); bool var: 10
66
+ c (pigeon, hole) pair: (4, 2); bool var: 11
67
+ c (pigeon, hole) pair: (4, 3); bool var: 12
68
+ p cnf 12 22
69
+ 1 2 3 0
70
+ 4 5 6 0
71
+ 7 8 9 0
72
+ 10 11 12 0
73
+ -1 -4 0
74
+ -1 -7 0
75
+ -1 -10 0
76
+ -4 -7 0
77
+ -4 -10 0
78
+ -7 -10 0
79
+ -2 -5 0
80
+ -2 -8 0
81
+ -2 -11 0
82
+ -5 -8 0
83
+ -5 -11 0
84
+ -8 -11 0
85
+ -3 -6 0
86
+ -3 -9 0
87
+ -3 -12 0
88
+ -6 -9 0
89
+ -6 -12 0
90
+ -9 -12 0
91
+
92
+ Alternatively, each of the considered problem encoders can be accessed with
93
+ the use of the standard ``import`` interface of Python, e.g.
94
+
95
+ .. code-block:: python
96
+
97
+ >>> from pysat.examples.genhard import PHP
98
+ >>>
99
+ >>> cnf = PHP(3)
100
+ >>> print(cnf.nv, len(cnf.clauses))
101
+ 12 22
102
+
103
+ Given this example, observe that classes :class:`PHP`, :class:`GT`,
104
+ :class:`CB`, and :class:`PAR` inherit from class
105
+ :class:`pysat.formula.CNF` and, thus, their corresponding clauses can
106
+ accessed through variable ``.clauses``.
107
+
108
+ ==============
109
+ Module details
110
+ ==============
111
+ """
112
+
113
+ #
114
+ #==============================================================================
115
+ from __future__ import print_function
116
+ import collections
117
+ import getopt
118
+ import itertools
119
+ import os
120
+ from pysat.card import *
121
+ from pysat.formula import IDPool, CNF
122
+ from six.moves import range
123
+ import sys
124
+
125
+
126
+ #
127
+ #==============================================================================
128
+ class PHP(CNF, object):
129
+ """
130
+ Generator of :math:`k` pigeonhole principle (:math:`k`-PHP) formulas.
131
+ Given integer parameters :math:`m` and :math:`k`, the :math:`k`
132
+ pigeonhole principle states that if :math:`k\\cdot m+1` pigeons are
133
+ distributes by :math:`m` holes, then at least one hole contains more
134
+ than :math:`k` pigeons.
135
+
136
+ Note that if :math:`k` is 1, the principle degenerates to the
137
+ formulation of the original pigeonhole principle stating that
138
+ :math:`m+1` pigeons cannot be distributed by :math:`m` holes.
139
+
140
+ Assume that a Boolean variable :math:`x_{ij}` encodes that pigeon
141
+ :math:`i` resides in hole :math:`j`. Then a PHP formula can be seen as
142
+ a conjunction: :math:`\\bigwedge_{i=1}^{k\\cdot
143
+ m+1}{\\textsf{AtLeast1}(x_{i1},\\ldots,x_{im})}\\wedge
144
+ \\bigwedge_{j=1}^{m}{\\textsf{AtMost}k(x_{1j},\\ldots,x_{k\\cdot
145
+ m+1,j})}`. Here each :math:`\\textsf{AtLeast1}` constraint forces every
146
+ pigeon to be placed into at least one hole while each
147
+ :math:`\\textsf{AtMost}k` constraint allows the corresponding hole to
148
+ have at most :math:`k` pigeons. The overall PHP formulas are
149
+ unsatisfiable.
150
+
151
+ PHP formulas are well-known [6]_ to be hard for resolution.
152
+
153
+ .. [6] Armin Haken. *The Intractability of Resolution*. Theor. Comput.
154
+ Sci. 39. 1985. pp. 297-308
155
+
156
+ :param nof_holes: number of holes (:math:`n`)
157
+ :param kval: multiplier :math:`k`
158
+ :param topv: current top variable identifier
159
+ :param verb: defines whether or not the encoder is verbose
160
+
161
+ :type nof_holes: int
162
+ :type kval: int
163
+ :type topv: int
164
+ :type verb: bool
165
+
166
+ :return: object of class :class:`pysat.formula.CNF`.
167
+ """
168
+
169
+ def __init__(self, nof_holes, kval=1, topv=0, verb=False):
170
+ """
171
+ Constructor.
172
+ """
173
+
174
+ # initializing CNF's internal parameters
175
+ super(PHP, self).__init__()
176
+
177
+ # initializing the pool of variable ids
178
+ vpool = IDPool(start_from=topv + 1)
179
+ var = lambda i, j: vpool.id('v_{0}_{1}'.format(i, j))
180
+
181
+ # placing all pigeons into holes
182
+ for i in range(1, kval * nof_holes + 2):
183
+ self.append([var(i, j) for j in range(1, nof_holes + 1)])
184
+
185
+ # there cannot be more than k pigeons in a hole
186
+ pigeons = range(1, kval * nof_holes + 2)
187
+ for j in range(1, nof_holes + 1):
188
+ for comb in itertools.combinations(pigeons, kval + 1):
189
+ self.append([-var(i, j) for i in comb])
190
+
191
+ if verb:
192
+ head = 'c {0}PHP formula for'.format('' if kval == 1 else str(kval) + '-')
193
+ head += ' {0} pigeons and {1} holes'.format(kval * nof_holes + 1, nof_holes)
194
+ self.comments.append(head)
195
+
196
+ for i in range(1, kval * nof_holes + 2):
197
+ for j in range(1, nof_holes + 1):
198
+ self.comments.append('c (pigeon, hole) pair: ({0}, {1}); bool var: {2}'.format(i, j, var(i, j)))
199
+
200
+
201
+ #
202
+ #==============================================================================
203
+ class GT(CNF, object):
204
+ """
205
+ Generator of ordering (or *greater than*, GT) principle formulas. Given
206
+ an integer parameter :math:`n`, the principle states that any partial
207
+ order on the set :math:`\\{1,2,\\ldots,n\\}` must have a maximal element.
208
+
209
+ Assume variable :math:`x_{ij}`, for :math:`i,j\\in[n],i\\neq j`,
210
+ denotes the fact that :math:`i \\succ j`. Clauses
211
+ :math:`(\\neg{x_{ij}} \\vee \\neg{x_{ji}})` and :math:`(\\neg{x_{ij}}
212
+ \\vee \\neg{x_{jk}} \\vee x_{ik})` ensure that the relation
213
+ :math:`\\succ` is anti-symmetric and transitive. As a result,
214
+ :math:`\\succ` is a partial order on :math:`[n]`. The additional
215
+ requirement that each element :math:`i` has a successor in
216
+ :math:`[n]\\setminus\\{i\\}` represented a clause :math:`(\\vee_{j
217
+ \\neq i}{x_{ji}})` makes the formula unsatisfiable.
218
+
219
+ GT formulas were originally conjectured [2]_ to be hard for resolution.
220
+ However, [5]_ proved the existence of a polynomial size resolution
221
+ refutation for GT formulas.
222
+
223
+ .. [5] Gunnar Stålmarck. *Short Resolution Proofs for a Sequence of
224
+ Tricky Formulas*. Acta Informatica. 33(3). 1996. pp. 277-280
225
+
226
+ :param size: number of elements (:math:`n`)
227
+ :param topv: current top variable identifier
228
+ :param verb: defines whether or not the encoder is verbose
229
+
230
+ :type size: int
231
+ :type topv: int
232
+ :type verb: bool
233
+
234
+ :return: object of class :class:`pysat.formula.CNF`.
235
+ """
236
+
237
+ def __init__(self, size, topv=0, verb=False):
238
+ """
239
+ Constructor.
240
+ """
241
+
242
+ # initializing CNF's internal parameters
243
+ super(GT, self).__init__()
244
+
245
+ # initializing the pool of variable ids
246
+ vpool = IDPool(start_from=topv + 1)
247
+ var = lambda i, j: vpool.id('v_{0}_{1}'.format(i, j))
248
+
249
+ # anti-symmetric relation clauses
250
+ for i in range(1, size):
251
+ for j in range(i + 1, size + 1):
252
+ self.append([-var(i, j), -var(j, i)])
253
+
254
+ # transitive relation clauses
255
+ for i in range(1, size + 1):
256
+ for j in range(1, size + 1):
257
+ if j != i:
258
+ for k in range(1, size + 1):
259
+ if k != i and k != j:
260
+ self.append([-var(i, j), -var(j, k), var(i, k)])
261
+
262
+ # successor clauses
263
+ for j in range(1, size + 1):
264
+ self.append([var(k, j) for k in range(1, size + 1) if k != j])
265
+
266
+ if verb:
267
+ self.comments.append('c GT formula for {0} elements'.format(size))
268
+ for i in range(1, size + 1):
269
+ for j in range(1, size + 1):
270
+ if i != j:
271
+ self.comments.append('c orig pair: {0}; bool var: {1}'.format((i, j), var(i, j)))
272
+
273
+
274
+ #
275
+ #==============================================================================
276
+ class CB(CNF, object):
277
+ """
278
+ Mutilated chessboard principle (CB). Given an integer :math:`n`, the
279
+ principle states that it is impossible to cover a chessboard of size
280
+ :math:`2n\\cdot 2n` by domino tiles if two diagonally opposite corners
281
+ of the chessboard are removed.
282
+
283
+ Note that the chessboard has :math:`4n^2-2` cells. Introduce a Boolean
284
+ variable :math:`x_{ij}` for :math:`i,j\\in[4n^2-2]` s.t. cells
285
+ :math:`i` and :math:`j` are adjacent (no variables are introduced for
286
+ pairs of non-adjacent cells). CB formulas comprise clauses (1)
287
+ :math:`(\\neg{x_{ji} \\vee \\neg{x_{ki}}})` for every :math:`i,j \\neq
288
+ k` meaning that no more than one adjacent cell can be paired with the
289
+ current one; and (2) :math:`(\\vee_{j \\in \\text{Adj}(i)}
290
+ {x_{ij}})\\,\\, \\forall i` enforcing that every cell :math:`i` should
291
+ be paired with at least one adjacent cell.
292
+
293
+ Clearly, since the two diagonal corners are removed, the formula is
294
+ unsatisfiable. Also note the following. Assuming that the number of
295
+ black cells is larger than the number of the white ones, CB formulas
296
+ are unsatisfiable even if only a half of the formula is present, e.g.
297
+ when :math:`\\textsf{AtMost1}` constraints are formulated only for the
298
+ white cells while the :math:`\\textsf{AtLeast1}` constraints are
299
+ formulated only for the black cells. Depending on the value of
300
+ parameter ``exhaustive`` the encoder applies the *complete* or
301
+ *partial* formulation of the problem.
302
+
303
+ Mutilated chessboard principle is known to be hard for resolution [3]_.
304
+
305
+ :param size: problem size (:math:`n`)
306
+ :param exhaustive: encode the problem exhaustively
307
+ :param topv: current top variable identifier
308
+ :param verb: defines whether or not the encoder is verbose
309
+
310
+ :type size: int
311
+ :type exhaustive: bool
312
+ :type topv: int
313
+ :type verb: bool
314
+
315
+ :return: object of class :class:`pysat.formula.CNF`.
316
+ """
317
+
318
+ def __init__(self, size, exhaustive=False, topv=0, verb=False):
319
+ """
320
+ Constructor.
321
+ """
322
+
323
+ # initializing CNF's internal parameters
324
+ super(CB, self).__init__()
325
+
326
+ # cell number
327
+ cell = lambda i, j: (i - 1) * 2 * size + j
328
+
329
+ # initializing the pool of variable ids
330
+ vpool = IDPool(start_from=topv + 1)
331
+ var = lambda c1, c2: vpool.id('edge: ({0}, {1})'.format(min(c1, c2), max(c1, c2)))
332
+
333
+ for i in range(1, 2 * size + 1):
334
+ for j in range(1, 2 * size + 1):
335
+ adj = []
336
+
337
+ # current cell
338
+ c = cell(i, j)
339
+
340
+ # removing first and last cells (they are white)
341
+ if c in (1, 4 * size * size):
342
+ continue
343
+
344
+ # each cell has 2 <= k <= 4 adjacents
345
+ if i > 1 and cell(i - 1, j) != 1:
346
+ adj.append(var(c, cell(i - 1, j)))
347
+
348
+ if j > 1 and cell(i, j - 1) != 1:
349
+ adj.append(var(c, cell(i, j - 1)))
350
+
351
+ if i < 2 * size and cell(i + 1, j) != 4 * size * size:
352
+ adj.append(var(c, cell(i + 1, j)))
353
+
354
+ if j < 2 * size and cell(i, j + 1) != 4 * size * size:
355
+ adj.append(var(c, cell(i, j + 1)))
356
+
357
+ if not adj: # when n == 1, no clauses will be added
358
+ continue
359
+
360
+ # adding equals1 constraint for black and white cells
361
+ if exhaustive:
362
+ cnf = CardEnc.equals(lits=adj, bound=1, encoding=EncType.pairwise)
363
+ self.extend(cnf.clauses)
364
+ else:
365
+ # atmost1 constraint for white cells
366
+ if i % 2 and c % 2 or i % 2 == 0 and c % 2 == 0:
367
+ am1 = CardEnc.atmost(lits=adj, bound=1, encoding=EncType.pairwise)
368
+ self.extend(am1.clauses)
369
+ else: # atleast1 constrant for black cells
370
+ self.append(adj)
371
+
372
+ if verb:
373
+ head = 'c CB formula for the chessboard of size {0}x{0}'.format(2 * size)
374
+ head += '\nc The encoding is {0}exhaustive'.format('' if exhaustive else 'not ')
375
+ self.comments.append(head)
376
+
377
+ for v in range(1, vpool.top + 1):
378
+ self.comments.append('c {0}; bool var: {1}'.format(vpool.obj(v), v))
379
+
380
+
381
+ #
382
+ #==============================================================================
383
+ class PAR(CNF, object):
384
+ """
385
+ Generator of the parity principle (PAR) formulas. Given an integer
386
+ parameter :math:`n`, the principle states that no graph on :math:`2n+1`
387
+ nodes consists of a complete perfect matching.
388
+
389
+ The encoding of the parity principle uses :math:`\\binom{2n+1}{2}`
390
+ variables :math:`x_{ij},i \\neq j`. If variable :math:`x_{ij}` is
391
+ *true*, then there is an edge between nodes :math:`i` and :math:`j`.
392
+ The formula consists of the following clauses: :math:`(\\vee_{j \\neq
393
+ i}{x_{ij}})` for every :math:`i\\in[2n+1]`, and :math:`(\\neg{x_{ij}}
394
+ \\vee \\neg{x_{kj}})` for all distinct :math:`i,j,k \\in [2n+1]`.
395
+
396
+ The parity principle is known to be hard for resolution [4]_.
397
+
398
+ :param size: problem size (:math:`n`)
399
+ :param topv: current top variable identifier
400
+ :param verb: defines whether or not the encoder is verbose
401
+
402
+ :type size: int
403
+ :type topv: int
404
+ :type verb: bool
405
+
406
+ :return: object of class :class:`pysat.formula.CNF`.
407
+ """
408
+
409
+ def __init__(self, size, topv=0, verb=False):
410
+ """
411
+ Constructor.
412
+ """
413
+
414
+ # initializing CNF's internal parameters
415
+ super(PAR, self).__init__()
416
+
417
+ # initializing the pool of variable ids
418
+ vpool = IDPool(start_from=topv + 1)
419
+ var = lambda i, j: vpool.id('v_{0}_{1}'.format(min(i, j), max(i, j)))
420
+
421
+ for i in range(1, 2 * size + 2):
422
+ self.append([var(i, j) for j in range(1, 2 * size + 2) if j != i])
423
+
424
+ for j in range(1, 2 * size + 2):
425
+ for i, k in itertools.combinations(range(1, 2 * size + 2), 2):
426
+ if i == j or k == j:
427
+ continue
428
+
429
+ self.append([-var(i, j), -var(k, j)])
430
+
431
+ if verb:
432
+ self.comments.append('c Parity formula for m == {0} ({1} vertices)'.format(size, 2 * size + 1))
433
+ for i in range(1, 2 * size + 2):
434
+ for j in range(i + 1, 2 * size + 2):
435
+ self.comments.append('c edge: {0}; bool var: {1}'.format((i, j), var(i, j)))
436
+
437
+
438
+ #
439
+ #==============================================================================
440
+ def parse_options():
441
+ """
442
+ Parses command-line options:
443
+ """
444
+
445
+ try:
446
+ opts, args = getopt.getopt(sys.argv[1:],
447
+ 'k:n:ht:v',
448
+ ['kval=',
449
+ 'size=',
450
+ 'help',
451
+ 'type=',
452
+ 'verb'])
453
+ except getopt.GetoptError as err:
454
+ sys.stderr.write(str(err).capitalize())
455
+ usage()
456
+ sys.exit(1)
457
+
458
+ kval = 1
459
+ size = 8
460
+ ftype = 'php'
461
+ verb = False
462
+
463
+ for opt, arg in opts:
464
+ if opt in ('-h', '--help'):
465
+ usage()
466
+ sys.exit(0)
467
+ elif opt in ('-k', '--kval'):
468
+ kval = int(arg)
469
+ elif opt in ('-n', '--size'):
470
+ size = int(arg)
471
+ elif opt in ('-t', '--type'):
472
+ ftype = str(arg)
473
+ elif opt in ('-v', '--verb'):
474
+ verb = True
475
+ else:
476
+ assert False, 'Unhandled option: {0} {1}'.format(opt, arg)
477
+
478
+ return ftype, kval, size, verb
479
+
480
+
481
+ #
482
+ #==============================================================================
483
+ def usage():
484
+ """
485
+ Prints usage message.
486
+ """
487
+
488
+ print('Usage:', os.path.basename(sys.argv[0]), '[options]')
489
+ print('Options:')
490
+ print(' -k, --kval=<int> Value k for generating k-PHP')
491
+ print(' Available values: [1 .. INT_MAX] (default = 1)')
492
+ print(' -n, --size=<int> Integer parameter of formula (its size)')
493
+ print(' Available values: [0 .. INT_MAX] (default = 8)')
494
+ print(' -h, --help')
495
+ print(' -t, --type=<string> Formula type')
496
+ print(' Available values: cb, gt, par, php (default = php)')
497
+ print(' -v, --verb Be verbose (show comments)')
498
+
499
+ #
500
+ #==============================================================================
501
+ if __name__ == '__main__':
502
+ # parse command-line options
503
+ ftype, kval, size, verb = parse_options()
504
+
505
+ # generate formula
506
+ if ftype == 'php':
507
+ cnf = PHP(size, kval=kval, verb=verb)
508
+ elif ftype == 'gt': # gt
509
+ cnf = GT(size, verb=verb)
510
+ elif ftype == 'cb': # cb
511
+ cnf = CB(size, exhaustive=kval, verb=verb)
512
+ else: # parity
513
+ cnf = PAR(size, verb=verb)
514
+
515
+ # print formula in DIMACS to stdout
516
+ cnf.to_fp(sys.stdout)