python-sat 1.8.dev26__tar.gz → 1.8.dev28__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 (100) hide show
  1. {python_sat-1.8.dev26/python_sat.egg-info → python_sat-1.8.dev28}/PKG-INFO +1 -1
  2. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/rc2.py +2 -2
  3. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/__init__.py +1 -1
  4. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/formula.py +109 -32
  5. {python_sat-1.8.dev26 → python_sat-1.8.dev28/python_sat.egg-info}/PKG-INFO +1 -1
  6. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/LICENSE.txt +0 -0
  7. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/MANIFEST.in +0 -0
  8. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/README.rst +0 -0
  9. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/allies/__init__.py +0 -0
  10. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/allies/approxmc.py +0 -0
  11. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/allies/unigen.py +0 -0
  12. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/bitwise.hh +0 -0
  13. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/card.hh +0 -0
  14. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/clset.hh +0 -0
  15. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/common.hh +0 -0
  16. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/itot.hh +0 -0
  17. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/ladder.hh +0 -0
  18. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/mto.hh +0 -0
  19. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/pairwise.hh +0 -0
  20. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/ptypes.hh +0 -0
  21. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/pycard.cc +0 -0
  22. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/seqcounter.hh +0 -0
  23. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/sortcard.hh +0 -0
  24. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/cardenc/utils.hh +0 -0
  25. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/__init__.py +0 -0
  26. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/bbscan.py +0 -0
  27. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/bica.py +0 -0
  28. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/fm.py +0 -0
  29. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/genhard.py +0 -0
  30. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/hitman.py +0 -0
  31. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/lbx.py +0 -0
  32. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/lsu.py +0 -0
  33. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/mcsls.py +0 -0
  34. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/models.py +0 -0
  35. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/musx.py +0 -0
  36. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/optux.py +0 -0
  37. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/primer.py +0 -0
  38. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/examples/usage.py +0 -0
  39. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/_fileio.py +0 -0
  40. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/_utils.py +0 -0
  41. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/card.py +0 -0
  42. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/engines.py +0 -0
  43. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/pb.py +0 -0
  44. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/process.py +0 -0
  45. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/pysat/solvers.py +0 -0
  46. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/python_sat.egg-info/SOURCES.txt +0 -0
  47. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/python_sat.egg-info/dependency_links.txt +0 -0
  48. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/python_sat.egg-info/requires.txt +0 -0
  49. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/python_sat.egg-info/top_level.txt +0 -0
  50. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/requirements.txt +0 -0
  51. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/setup.cfg +0 -0
  52. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/setup.py +0 -0
  53. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/cadical103.tar.gz +0 -0
  54. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/cadical153.tar.gz +0 -0
  55. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/cadical195.tar.gz +0 -0
  56. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/glucose30.tar.gz +0 -0
  57. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/glucose41.tar.gz +0 -0
  58. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/glucose421.tar.gz +0 -0
  59. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/lingeling.tar.gz +0 -0
  60. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/maplechrono.zip +0 -0
  61. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/maplecm.zip +0 -0
  62. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/maplesat.zip +0 -0
  63. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/mergesat3.tar.gz +0 -0
  64. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/minicard.tar.gz +0 -0
  65. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/minisat22.tar.gz +0 -0
  66. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/minisatgh.zip +0 -0
  67. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/cadical103.patch +0 -0
  68. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/cadical153.patch +0 -0
  69. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/cadical195.patch +0 -0
  70. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/glucose30.patch +0 -0
  71. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/glucose41.patch +0 -0
  72. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/glucose421.patch +0 -0
  73. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/gluecard30.patch +0 -0
  74. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/gluecard41.patch +0 -0
  75. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/lingeling.patch +0 -0
  76. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/maplechrono.patch +0 -0
  77. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/maplecm.patch +0 -0
  78. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/maplesat.patch +0 -0
  79. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/mergesat3.patch +0 -0
  80. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/minicard.patch +0 -0
  81. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/minisat22.patch +0 -0
  82. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/patches/minisatgh.patch +0 -0
  83. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/prepare.py +0 -0
  84. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/solvers/pysolvers.cc +0 -0
  85. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_accum_stats.py +0 -0
  86. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_atmost.py +0 -0
  87. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_atmost1.py +0 -0
  88. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_atmostk.py +0 -0
  89. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_boolengine.py +0 -0
  90. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_clausification.py +0 -0
  91. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_cnf.py +0 -0
  92. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_encode_pb_conditional.py +0 -0
  93. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_equals1.py +0 -0
  94. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_formula_unique.py +0 -0
  95. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_idpool.py +0 -0
  96. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_process.py +0 -0
  97. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_propagate.py +0 -0
  98. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_unique_model.py +0 -0
  99. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_unique_mus.py +0 -0
  100. {python_sat-1.8.dev26 → python_sat-1.8.dev28}/tests/test_warmstart.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.8.dev26
3
+ Version: 1.8.dev28
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
@@ -345,8 +345,8 @@ class RC2(object):
345
345
  else:
346
346
  # adding to formula's hard clauses
347
347
  # if any preprocessing is required
348
- formula.hard.append(cl + [-sel])
349
- formula.soft[i] = [sel]
348
+ formula.hard.append(cl)
349
+ formula.soft[i] = [selv]
350
350
 
351
351
  if selv not in self.wght:
352
352
  # record selector and its weight
@@ -10,7 +10,7 @@
10
10
 
11
11
  # current version
12
12
  #==============================================================================
13
- VERSION = (1, 8, 'dev', 26)
13
+ VERSION = (1, 8, 'dev', 28)
14
14
 
15
15
 
16
16
  # PEP440 Format
@@ -4036,26 +4036,34 @@ class WCNF(object):
4036
4036
 
4037
4037
  .. code-block:: python
4038
4038
 
4039
- >>> with open('some-file.cnf', 'r') as fp:
4039
+ >>> with open('some-file.wcnf', 'r') as fp:
4040
4040
  ... cnf1 = WCNF()
4041
4041
  ... cnf1.from_fp(fp)
4042
4042
  >>>
4043
- >>> with open('another-file.cnf', 'r') as fp:
4043
+ >>> with open('another-file.wcnf', 'r') as fp:
4044
4044
  ... cnf2 = WCNF(from_fp=fp)
4045
4045
  """
4046
4046
 
4047
4047
  def parse_wght(string):
4048
- wght = float(string)
4049
- return int(wght) if wght.is_integer() else decimal.Decimal(string)
4048
+ if string == 'h':
4049
+ return None
4050
+ else:
4051
+ wght = float(string)
4052
+ return int(wght) if wght.is_integer() else decimal.Decimal(string)
4050
4053
 
4051
4054
  self.nv = 0
4052
4055
  self.hard = []
4053
4056
  self.soft = []
4054
4057
  self.wght = []
4055
- self.topw = 1
4058
+ self.topw = decimal.Decimal('+inf')
4056
4059
  self.comments = []
4057
4060
  comment_lead = set(['p']).union(set(comment_lead))
4058
4061
 
4062
+ # we are now expecting the new WCNF format
4063
+ assert 'h' not in comment_lead, \
4064
+ "Character 'h' cannot be used for comments" \
4065
+ " (reserved to signify hard clauses)"
4066
+
4059
4067
  # soft clauses with negative weights
4060
4068
  negs = []
4061
4069
 
@@ -4066,7 +4074,7 @@ class WCNF(object):
4066
4074
  w, items = line.split(sep=None, maxsplit=1)
4067
4075
  w = parse_wght(w)
4068
4076
 
4069
- if w >= self.topw:
4077
+ if w is None or w >= self.topw:
4070
4078
  self.hard.append(list(map(int, items.split()[:-1])))
4071
4079
  elif w > 0:
4072
4080
  self.soft.append(list(map(int, items.split()[:-1])))
@@ -4078,12 +4086,16 @@ class WCNF(object):
4078
4086
  elif not line.startswith('p wcnf '):
4079
4087
  self.comments.append(line)
4080
4088
  else: # expecting the preamble
4089
+ assert len(self.soft) == len(self.hard) == 0, \
4090
+ 'Preamble goes after some of the clauses have been read'
4091
+
4081
4092
  preamble = line.split(' ')
4082
4093
  if len(preamble) == 5: # preamble should be "p wcnf nvars nclauses topw"
4083
4094
  self.topw = parse_wght(preamble[-1])
4084
4095
  else: # preamble should be "p wcnf nvars nclauses", with topw omitted
4085
4096
  self.topw = decimal.Decimal('+inf')
4086
4097
 
4098
+ # potentially expensive: calculating the largest variable identifier
4087
4099
  self.nv = max(map(lambda cl: max(map(abs, cl)), itertools.chain.from_iterable([[[self.nv]], self.hard, self.soft])))
4088
4100
 
4089
4101
  # if there is any soft clause with negative weight
@@ -4198,7 +4210,8 @@ class WCNF(object):
4198
4210
 
4199
4211
  return wcnf
4200
4212
 
4201
- def to_file(self, fname, comments=None, compress_with='use_ext'):
4213
+ def to_file(self, fname, comments=None, compress_with='use_ext',
4214
+ format='mse22'):
4202
4215
  """
4203
4216
  The method is for saving a WCNF formula into a file in the DIMACS
4204
4217
  CNF format. A file name is expected as an argument. Additionally,
@@ -4206,13 +4219,20 @@ class WCNF(object):
4206
4219
  parameter. Also, a file can be compressed using either gzip, bzip2,
4207
4220
  lzma (xz), or zstd.
4208
4221
 
4222
+ The ``format`` parameter can be set either to value ``'mse22'``
4223
+ (set by default) or ``'legacy'``. Both variants are described on
4224
+ the `MSE 2022 webpage
4225
+ <https://maxsat-evaluations.github.io/2022/rules.html#input>`__.
4226
+
4209
4227
  :param fname: a file name where to store the formula.
4210
4228
  :param comments: additional comments to put in the file.
4211
4229
  :param compress_with: file compression algorithm
4230
+ :param format: WCNF format to use
4212
4231
 
4213
4232
  :type fname: str
4214
4233
  :type comments: list(str)
4215
4234
  :type compress_with: str
4235
+ :type format: str
4216
4236
 
4217
4237
  Note that the ``compressed_with`` parameter can be ``None`` (i.e.
4218
4238
  the file is uncompressed), ``'gzip'``, ``'bzip2'``, ``'lzma'``,
@@ -4234,20 +4254,27 @@ class WCNF(object):
4234
4254
  """
4235
4255
 
4236
4256
  with FileObject(fname, mode='w', compression=compress_with) as fobj:
4237
- self.to_fp(fobj.fp, comments)
4257
+ self.to_fp(fobj.fp, comments, format=format)
4238
4258
 
4239
- def to_fp(self, file_pointer, comments=None):
4259
+ def to_fp(self, file_pointer, comments=None, format='mse22'):
4240
4260
  """
4241
4261
  The method can be used to save a WCNF formula into a file pointer.
4242
4262
  The file pointer is expected as an argument. Additionally,
4243
4263
  supplementary comment lines can be specified in the ``comments``
4244
4264
  parameter.
4245
4265
 
4266
+ The ``format`` parameter can be set either to value ``'mse22'``
4267
+ (set by default) or ``'legacy'``. Both variants are described on
4268
+ the `MSE 2022 webpage
4269
+ <https://maxsat-evaluations.github.io/2022/rules.html#input>`__.
4270
+
4246
4271
  :param file_pointer: a file pointer where to store the formula.
4247
4272
  :param comments: additional comments to put in the file.
4273
+ :param format: WCNF format to use
4248
4274
 
4249
4275
  :type file_pointer: file pointer
4250
4276
  :type comments: list(str)
4277
+ :type format: str
4251
4278
 
4252
4279
  Example:
4253
4280
 
@@ -4270,21 +4297,32 @@ class WCNF(object):
4270
4297
  for c in comments:
4271
4298
  print(c, file=file_pointer)
4272
4299
 
4273
- print('p wcnf', self.nv, len(self.hard) + len(self.soft), self.topw, file=file_pointer)
4300
+ if format == 'legacy':
4301
+ print('p wcnf', self.nv, len(self.hard) + len(self.soft), self.topw, file=file_pointer)
4274
4302
 
4275
4303
  # soft clauses are dumped first because
4276
4304
  # some tools (e.g. LBX) cannot count them properly
4277
4305
  for i, cl in enumerate(self.soft):
4278
4306
  print(self.wght[i], ' '.join(str(l) for l in cl), '0', file=file_pointer)
4279
4307
 
4308
+ # hard clause either have a top weight or are marked as 'h'
4309
+ topw = self.topw if format == 'legacy' else 'h'
4280
4310
  for cl in self.hard:
4281
- print(self.topw, ' '.join(str(l) for l in cl), '0', file=file_pointer)
4311
+ print(topw, ' '.join(str(l) for l in cl), '0', file=file_pointer)
4282
4312
 
4283
- def to_dimacs(self):
4313
+ def to_dimacs(self, format='mse22'):
4284
4314
  """
4285
4315
  Return the current state of the object in extended DIMACS format.
4286
4316
 
4287
- For example, if 'some-file.cnf' contains:
4317
+ The ``format`` parameter can be set either to value ``'mse22'``
4318
+ (set by default) or ``'legacy'``. Both variants are described on
4319
+ the `MSE 2022 webpage
4320
+ <https://maxsat-evaluations.github.io/2022/rules.html#input>`__.
4321
+
4322
+ :param format: WCNF format to use
4323
+ :type format: str
4324
+
4325
+ For example, if 'some-file.wcnf' contains:
4288
4326
 
4289
4327
  ::
4290
4328
 
@@ -4299,20 +4337,31 @@ class WCNF(object):
4299
4337
  .. code-block:: python
4300
4338
 
4301
4339
  >>> from pysat.formula import WCNF
4302
- >>> cnf = WCNF(from_file='some-file.cnf')
4303
- >>> print(cnf.to_dimacs())
4340
+ >>> cnf = WCNF(from_file='some-file.wcnf')
4341
+ >>> print(cnf.to_dimacs(format='legacy'))
4304
4342
  c Example
4305
4343
  p wcnf 2 3 10
4306
4344
  10 1 2 0
4307
4345
  1 -1 0
4308
4346
  2 -2 0
4347
+ >>>
4348
+ >>> print(cnf.to_dimacs())
4349
+ c Example
4350
+ h 1 2 0
4351
+ 1 -1 0
4352
+ 2 -2 0
4309
4353
  """
4310
4354
 
4311
- header_lines = [f'p wcnf {self.nv} {len(self.hard) + len(self.soft)} {self.topw}']
4312
4355
  comment_lines = [f'{comment}' for comment in self.comments]
4313
- hard_lines = [f'{self.topw} ' + ' '.join(map(str, clause)) + ' 0' for clause in self.hard]
4314
4356
  soft_lines = [f'{weight} ' + ' '.join(map(str, clause)) + ' 0' for clause, weight in zip(self.soft, self.wght)]
4315
4357
 
4358
+ if format == 'legacy':
4359
+ header_lines = [f'p wcnf {self.nv} {len(self.hard) + len(self.soft)} {self.topw}']
4360
+ hard_lines = [f'{self.topw} ' + ' '.join(map(str, clause)) + ' 0' for clause in self.hard]
4361
+ else:
4362
+ header_lines = []
4363
+ hard_lines = ['h ' + ' '.join(map(str, clause)) + ' 0' for clause in self.hard]
4364
+
4316
4365
  lines = '\n'.join(comment_lines + header_lines + hard_lines + soft_lines)
4317
4366
  return lines
4318
4367
 
@@ -5173,18 +5222,26 @@ class WCNFPlus(WCNF, object):
5173
5222
  """
5174
5223
 
5175
5224
  def parse_wght(string):
5176
- wght = float(string)
5177
- return int(wght) if wght.is_integer() else decimal.Decimal(string)
5225
+ if string == 'h':
5226
+ return None
5227
+ else:
5228
+ wght = float(string)
5229
+ return int(wght) if wght.is_integer() else decimal.Decimal(string)
5178
5230
 
5179
5231
  self.nv = 0
5180
5232
  self.hard = []
5181
5233
  self.atms = []
5182
5234
  self.soft = []
5183
5235
  self.wght = []
5184
- self.topw = 1
5236
+ self.topw = decimal.Decimal('+inf')
5185
5237
  self.comments = []
5186
5238
  comment_lead = set(['p']).union(set(comment_lead))
5187
5239
 
5240
+ # we are now expecting the new WCNF format
5241
+ assert 'h' not in comment_lead, \
5242
+ "Character 'h' cannot be used for comments" \
5243
+ " (reserved to signify hard clauses)"
5244
+
5188
5245
  # soft clauses with negative weights
5189
5246
  negs = []
5190
5247
 
@@ -5196,7 +5253,7 @@ class WCNFPlus(WCNF, object):
5196
5253
  w, items = line.split(sep=None, maxsplit=1)
5197
5254
  w = parse_wght(w)
5198
5255
 
5199
- if w >= self.topw:
5256
+ if w is None or w >= self.topw:
5200
5257
  self.hard.append(list(map(int, items.split()[:-1])))
5201
5258
  elif w > 0:
5202
5259
  self.soft.append(list(map(int, items.split()[:-1])))
@@ -5227,6 +5284,9 @@ class WCNFPlus(WCNF, object):
5227
5284
  elif not line.startswith('p wcnf'): # wcnf is allowed here
5228
5285
  self.comments.append(line)
5229
5286
  else: # expecting the preamble
5287
+ assert len(self.soft) == len(self.hard) == len(self.atms) == 0, \
5288
+ 'Preamble goes after some of the clauses have been read'
5289
+
5230
5290
  preamble = line.split(' ')
5231
5291
  if len(preamble) == 5: # preamble should be "p wcnf nvars nclauses topw"
5232
5292
  self.topw = parse_wght(preamble[-1])
@@ -5246,18 +5306,25 @@ class WCNFPlus(WCNF, object):
5246
5306
  if type(self.topw) == decimal.Decimal and self.topw.is_infinite():
5247
5307
  self.topw = 1 + sum(self.wght)
5248
5308
 
5249
- def to_fp(self, file_pointer, comments=None):
5309
+ def to_fp(self, file_pointer, comments=None, format='mse22'):
5250
5310
  """
5251
5311
  The method can be used to save a WCNF+ formula into a file pointer.
5252
5312
  The file pointer is expected as an argument. Additionally,
5253
5313
  supplementary comment lines can be specified in the ``comments``
5254
5314
  parameter.
5255
5315
 
5316
+ The ``format`` parameter can be set either to value ``'mse22'``
5317
+ (set by default) or ``'legacy'``. Both variants are described on
5318
+ the `MSE 2022 webpage
5319
+ <https://maxsat-evaluations.github.io/2022/rules.html#input>`__.
5320
+
5256
5321
  :param file_pointer: a file pointer where to store the formula.
5257
5322
  :param comments: additional comments to put in the file.
5323
+ :param format: WCNF format to use
5258
5324
 
5259
5325
  :type file_pointer: file pointer
5260
5326
  :type comments: list(str)
5327
+ :type format: str
5261
5328
 
5262
5329
  Example:
5263
5330
 
@@ -5280,25 +5347,28 @@ class WCNFPlus(WCNF, object):
5280
5347
  for c in comments:
5281
5348
  print(c, file=file_pointer)
5282
5349
 
5283
- ftype = 'wcnf+' if self.atms else 'wcnf'
5284
- print('p', ftype, self.nv, len(self.hard) + len(self.soft) + len(self.atms),
5285
- self.topw, file=file_pointer)
5350
+ if format == 'legacy':
5351
+ ftype = 'wcnf+' if self.atms else 'wcnf'
5352
+ print('p', ftype, self.nv, len(self.hard) + len(self.soft) + len(self.atms),
5353
+ self.topw, file=file_pointer)
5286
5354
 
5287
5355
  # soft clauses are dumped first because
5288
5356
  # some tools (e.g. LBX) cannot count them properly
5289
5357
  for i, cl in enumerate(self.soft):
5290
5358
  print(self.wght[i], ' '.join(str(l) for l in cl), '0', file=file_pointer)
5291
5359
 
5360
+ # hard clause either have a top weight or are marked as 'h'
5361
+ topw = self.topw if format == 'legacy' else 'h'
5292
5362
  for cl in self.hard:
5293
- print(self.topw, ' '.join(str(l) for l in cl), '0', file=file_pointer)
5363
+ print(topw, ' '.join(str(l) for l in cl), '0', file=file_pointer)
5294
5364
 
5295
5365
  # atmost constraints are hard
5296
5366
  for am in self.atms:
5297
5367
  if len(am) == 2: # cardinality constraint
5298
- print(self.topw, ' '.join(str(l) for l in am[0]), '<=', am[1], file=file_pointer)
5368
+ print(topw, ' '.join(str(l) for l in am[0]), '<=', am[1], file=file_pointer)
5299
5369
  else: # len(am) == 3 => PB constraint
5300
5370
  assert len(am[0]) == len(am[2]), 'Number of literals should be equal to the number of weights'
5301
- print(self.topw, 'w', ' '.join('{0}*{1}'.format(str(w), str(l)) for w, l in zip(am[2], am[0])), '<=', am[1], file=file_pointer)
5371
+ print(topw, 'w', ' '.join('{0}*{1}'.format(str(w), str(l)) for w, l in zip(am[2], am[0])), '<=', am[1], file=file_pointer)
5302
5372
 
5303
5373
  def to_dimacs(self):
5304
5374
  """
@@ -5329,18 +5399,25 @@ class WCNFPlus(WCNF, object):
5329
5399
  10 -4 -5 -6 7 <= 2
5330
5400
  """
5331
5401
 
5332
- header_lines = [f'p wcnf+ {self.nv} {len(self.hard) + len(self.soft) + len(self.atms)} {self.topw}']
5333
5402
  comment_lines = [f'{comment}' for comment in self.comments]
5334
- hard_lines = [f'{self.topw} ' + ' '.join(map(str,clause)) + ' 0' for clause in self.hard]
5335
5403
  soft_lines = [f'{weight} ' + ' '.join(map(str,clause)) + ' 0' for clause, weight in zip(self.soft, self.wght)]
5336
5404
 
5405
+ if format == 'legacy':
5406
+ header_lines = [f'p wcnf+ {self.nv} {len(self.hard) + len(self.soft) + len(self.atms)} {self.topw}']
5407
+ topw = self.topw
5408
+ else:
5409
+ header_lines = []
5410
+ topw = 'h'
5411
+
5412
+ hard_lines = [f'{topw} ' + ' '.join(map(str,clause)) + ' 0' for clause in self.hard]
5413
+
5337
5414
  atmost_lines = []
5338
5415
  for am in self.atms:
5339
5416
  if len(am) == 2: # cardinality constraint
5340
- atmost_lines.append(f'{self.topw} ' + ' '.join(str(l) for l in am[0]) + ' <= ' + str(am[1]))
5417
+ atmost_lines.append(f'{topw} ' + ' '.join(str(l) for l in am[0]) + ' <= ' + str(am[1]))
5341
5418
  else: # len(am) == 3 => PB constraint
5342
5419
  assert len(am[0]) == len(am[2]), 'Number of literals should be equal to the number of weights'
5343
- atmost_lines.append(f'{self.topw} ' + 'w ' + ' '.join('{0}*{1}'.format(str(w), str(l)) for w, l in zip(am[2], am[0])) + ' <= ' + str(am[1]))
5420
+ atmost_lines.append(f'{topw} ' + 'w ' + ' '.join('{0}*{1}'.format(str(w), str(l)) for w, l in zip(am[2], am[0])) + ' <= ' + str(am[1]))
5344
5421
 
5345
5422
  lines = '\n'.join(comment_lines + header_lines + hard_lines + soft_lines + atmost_lines) + '\n'
5346
5423
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-sat
3
- Version: 1.8.dev26
3
+ Version: 1.8.dev28
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
File without changes
File without changes