PySMT 0.9.7.dev431__py2.py3-none-any.whl → 0.9.7.dev433__py2.py3-none-any.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.
pysmt/__init__.py CHANGED
@@ -19,7 +19,7 @@
19
19
  from typing import Tuple, Union
20
20
 
21
21
 
22
- VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 431)
22
+ VERSION: Union[Tuple[int, int, int], Tuple[int, int, int, str, int]] = (0, 9, 7, "dev", 433)
23
23
 
24
24
  # Try to provide human-readable version of latest commit for dev versions
25
25
  # E.g. v0.5.1-4-g49a49f2-wip
pysmt/fnode.py CHANGED
@@ -29,7 +29,7 @@ from pysmt.operators import (FORALL, EXISTS, AND, OR, NOT, IMPLIES, IFF,
29
29
  PLUS, MINUS, TIMES, DIV,
30
30
  LE, LT, EQUALS,
31
31
  ITE,
32
- TOREAL,
32
+ TOREAL, TOINT,
33
33
  BV_CONSTANT, BV_NOT, BV_AND, BV_OR, BV_XOR,
34
34
  BV_CONCAT, BV_EXTRACT,
35
35
  BV_ULT, BV_ULE, BV_NEG, BV_ADD, BV_SUB,
@@ -256,6 +256,10 @@ class FNode(object):
256
256
  """Test whether the node is the ToReal operator."""
257
257
  return self.node_type() == TOREAL
258
258
 
259
+ def is_toint(self) -> bool:
260
+ """Test whether the node is the ToInt operator."""
261
+ return self.node_type() == TOINT
262
+
259
263
  def is_forall(self) -> bool:
260
264
  """Test whether the node is the ForAll operator."""
261
265
  return self.node_type() == FORALL
pysmt/formula.py CHANGED
@@ -493,6 +493,44 @@ class FormulaManager(object):
493
493
  raise PysmtTypeError("Argument is of type %s, but INT was "
494
494
  "expected!\n" % t)
495
495
 
496
+ def ToInt(self, formula: FNode) -> FNode:
497
+ """ Cast a formula to integer type.
498
+
499
+ This is the SMT-LIB to_int function, i.e. the floor: it rounds
500
+ towards minus infinity, hence ToInt(-3/2) is -2 and not -1.
501
+ """
502
+ t = self.env.stc.get_type(formula)
503
+ if t == types.INT:
504
+ # Ignore casting of an Int
505
+ return formula
506
+ elif t == types.REAL:
507
+ if formula.is_real_constant():
508
+ value = cast(fractions.Fraction, formula.constant_value())
509
+ # Floor division on the numerator/denominator, so that this
510
+ # also works for the gmpy2 mpq backend (see pysmt.constants)
511
+ return self.Int(value.numerator // value.denominator)
512
+ return self.create_node(node_type=op.TOINT,
513
+ args=(formula,))
514
+ else:
515
+ raise PysmtTypeError("Argument is of type %s, but REAL was "
516
+ "expected!\n" % t)
517
+
518
+ def IsInt(self, formula: FNode) -> FNode:
519
+ """ Returns whether the given real formula has an integer value.
520
+
521
+ This is the SMT-LIB is_int predicate, expanded into its SMT-LIB
522
+ definition: (is_int t) is (= t (to_real (to_int t))).
523
+ """
524
+ t = self.env.stc.get_type(formula)
525
+ if t == types.INT:
526
+ # An Int is always an integer
527
+ return self.TRUE()
528
+ elif t == types.REAL:
529
+ return self.Equals(formula, self.ToReal(self.ToInt(formula)))
530
+ else:
531
+ raise PysmtTypeError("Argument is of type %s, but REAL was "
532
+ "expected!\n" % t)
533
+
496
534
  def AtMostOne(self, *args: Union[FNode, Iterable[FNode]]) -> FNode:
497
535
  """ At most one of the bool expressions can be true at anytime.
498
536
 
pysmt/operators.py CHANGED
@@ -25,7 +25,7 @@ from itertools import chain
25
25
  from typing import List
26
26
 
27
27
 
28
- ALL_TYPES = list(range(0,66))
28
+ ALL_TYPES = list(range(0,67))
29
29
 
30
30
  (
31
31
  FORALL, EXISTS, AND, OR, NOT, IMPLIES, IFF, # Boolean Logic (0-6)
@@ -79,6 +79,7 @@ DIV, # Arithmetic Division (62)
79
79
  POW, # Arithmetic Power (63)
80
80
  ALGEBRAIC_CONSTANT, # Algebraic Number (64)
81
81
  BV_TONATURAL, # BV to Natural Conversion (65)
82
+ TOINT, # LIRA to_int() function, i.e. floor (66)
82
83
  ) = ALL_TYPES
83
84
 
84
85
  QUANTIFIERS = frozenset([FORALL, EXISTS])
@@ -110,7 +111,8 @@ BV_OPERATORS = frozenset([BV_NOT, BV_AND, BV_OR, BV_XOR,
110
111
  STR_OPERATORS = frozenset([STR_LENGTH, STR_CONCAT, STR_INDEXOF, STR_REPLACE,
111
112
  STR_SUBSTR, STR_CHARAT, STR_TO_INT, INT_TO_STR,])
112
113
 
113
- IRA_OPERATORS = frozenset([PLUS, MINUS, TIMES, TOREAL, DIV, POW, BV_TONATURAL])
114
+ IRA_OPERATORS = frozenset([PLUS, MINUS, TIMES, TOREAL, TOINT, DIV, POW,
115
+ BV_TONATURAL])
114
116
 
115
117
  ARRAY_OPERATORS = frozenset([ARRAY_SELECT, ARRAY_STORE, ARRAY_VALUE])
116
118
 
@@ -178,6 +180,7 @@ __OP_STR__ = {
178
180
  EQUALS : "EQUALS",
179
181
  ITE : "ITE",
180
182
  TOREAL : "TOREAL",
183
+ TOINT : "TOINT",
181
184
  BV_CONSTANT : "BV_CONSTANT",
182
185
  BV_NOT : "BV_NOT",
183
186
  BV_AND : "BV_AND",
pysmt/oracles.py CHANGED
@@ -246,6 +246,12 @@ class TheoryOracle(walkers.DagWalker):
246
246
  """Extends the Theory with LIRA."""
247
247
  theory_out = args[0].set_lira() # This makes a copy of args[0]
248
248
  return theory_out
249
+
250
+ def walk_toint(self, formula: FNode, args: List[Theory], **kwargs) -> Theory:
251
+ #pylint: disable=unused-argument
252
+ """Extends the Theory with LIRA."""
253
+ theory_out = args[0].set_lira() # This makes a copy of args[0]
254
+ return theory_out
249
255
  rtype = formula.symbol_name()
250
256
 
251
257
  @walkers.handles([op.STR_LENGTH, op.STR_INDEXOF, op.STR_TO_INT])
pysmt/parsing.py CHANGED
@@ -199,6 +199,8 @@ class HRLexer(Lexer):
199
199
  "ZEXT": InfixOpAdapter(self.BVHack(self.mgr.BVZExt), 90),# BVZext
200
200
  "SEXT": InfixOpAdapter(self.BVHack(self.mgr.BVSExt), 90),# BVSext
201
201
  "ToReal": UnaryOpAdapter(self.mgr.ToReal, 100),#
202
+ "ToInt": UnaryOpAdapter(self.mgr.ToInt, 100),#
203
+ "IsInt": UnaryOpAdapter(self.mgr.IsInt, 100),#
202
204
  "Int": IntTypeTok(),# Int Type
203
205
  "Real": RealTypeTok(),# Real Type
204
206
  "Bool": BoolTypeTok(),# Bool Type
pysmt/printers.py CHANGED
@@ -177,6 +177,11 @@ class HRPrinter(TreeWalker):
177
177
  yield formula.arg(0)
178
178
  self.write(")")
179
179
 
180
+ def walk_toint(self, formula: FNode) -> Iterator[FNode]:
181
+ self.write("ToInt(")
182
+ yield formula.arg(0)
183
+ self.write(")")
184
+
180
185
  def walk_str_constant(self, formula: FNode):
181
186
  formula_value = formula.constant_value()
182
187
  assert isinstance(formula_value, str), \
pysmt/shortcuts.py CHANGED
@@ -361,6 +361,19 @@ def ToReal(formula: FNode) -> FNode:
361
361
  return get_env().formula_manager.ToReal(formula)
362
362
 
363
363
 
364
+ def ToInt(formula: FNode) -> FNode:
365
+ """Explicit cast of a term into an Int term.
366
+
367
+ This is the SMT-LIB to_int function, i.e. the floor.
368
+ """
369
+ return get_env().formula_manager.ToInt(formula)
370
+
371
+
372
+ def IsInt(formula: FNode) -> FNode:
373
+ """Returns whether the given real term has an integer value."""
374
+ return get_env().formula_manager.IsInt(formula)
375
+
376
+
364
377
  def AtMostOne(*args: Union[FNode, Iterable[FNode]]) -> FNode:
365
378
  """At most one can be true at anytime.
366
379
 
pysmt/simplifier.py CHANGED
@@ -463,6 +463,16 @@ class Simplifier(pysmt.walkers.DagWalker):
463
463
  return self.manager.Real(cast(int, args[0].constant_value()))
464
464
  return self.manager.ToReal(args[0])
465
465
 
466
+ def walk_toint(self, formula: FNode, args: List[FNode], **kwargs) -> FNode:
467
+ assert len(args) == 1
468
+ if args[0].is_toreal():
469
+ # to_int(to_real(x)) is x, since x is an integer.
470
+ # Note that the converse does not hold: to_real(to_int(y)) is
471
+ # y only when y happens to have an integer value.
472
+ return args[0].arg(0)
473
+ # Folding of real constants is done by the FormulaManager
474
+ return self.manager.ToInt(args[0])
475
+
466
476
  def walk_bv_and(self, formula: FNode, args: List[FNode], **kwargs) -> FNode:
467
477
  simplified = None
468
478
  width = formula.bv_width()
@@ -392,6 +392,8 @@ class SmtLibParser(object):
392
392
  'ite': self._operator_adapter(self.Ite),
393
393
  'distinct': self._operator_adapter(self.AllDifferent),
394
394
  'to_real': self._operator_adapter(mgr.ToReal),
395
+ 'to_int': self._operator_adapter(mgr.ToInt),
396
+ 'is_int': self._operator_adapter(mgr.IsInt),
395
397
  'concat': self._operator_adapter(mgr.BVConcat),
396
398
  'bvnot': self._operator_adapter(mgr.BVNot),
397
399
  'bvand': self._operator_adapter(mgr.BVAnd),
pysmt/smtlib/printers.py CHANGED
@@ -94,6 +94,7 @@ class SmtPrinter(TreeWalker):
94
94
  def walk_lt(self, formula): return self.walk_nary(formula, "<")
95
95
  def walk_ite(self, formula): return self.walk_nary(formula, "ite")
96
96
  def walk_toreal(self, formula): return self.walk_nary(formula, "to_real")
97
+ def walk_toint(self, formula): return self.walk_nary(formula, "to_int")
97
98
  def walk_div(self, formula): return self.walk_nary(formula, "/")
98
99
  def walk_pow(self, formula): return self.walk_nary(formula, "pow")
99
100
  def walk_bv_and(self, formula): return self.walk_nary(formula, "bvand")
@@ -422,6 +423,9 @@ class SmtDagPrinter(DagWalker):
422
423
  def walk_toreal(self, formula: FNode, args: List[str]) -> str:
423
424
  return self.walk_nary(formula, args, "to_real")
424
425
 
426
+ def walk_toint(self, formula: FNode, args: List[str]) -> str:
427
+ return self.walk_nary(formula, args, "to_int")
428
+
425
429
  def walk_div(self, formula: FNode, args: List[str]) -> str:
426
430
  return self.walk_nary(formula, args, "/")
427
431
 
pysmt/solvers/cvcfive.py CHANGED
@@ -394,6 +394,9 @@ class CVC5Converter(Converter, DagWalker):
394
394
  def walk_toreal(self, formula, args, **kwargs):
395
395
  return self.cvc5_solver.mkTerm(Kind.TO_REAL, args[0])
396
396
 
397
+ def walk_toint(self, formula, args, **kwargs):
398
+ return self.cvc5_solver.mkTerm(Kind.TO_INTEGER, args[0])
399
+
397
400
  def walk_function(self, formula, args, **kwargs):
398
401
  name = formula.function_name()
399
402
  if name not in self.declared_vars:
pysmt/solvers/cvcfour.py CHANGED
@@ -351,6 +351,9 @@ class CVC4Converter(Converter, DagWalker):
351
351
  def walk_toreal(self, formula, args, **kwargs):
352
352
  return self.mkExpr(CVC4.TO_REAL, args[0])
353
353
 
354
+ def walk_toint(self, formula, args, **kwargs):
355
+ return self.mkExpr(CVC4.TO_INTEGER, args[0])
356
+
354
357
  def walk_function(self, formula, args, **kwargs):
355
358
  name = formula.function_name()
356
359
  if name not in self.declared_vars:
pysmt/solvers/msat.py CHANGED
@@ -427,6 +427,7 @@ class MSatConverter(Converter, DagWalker):
427
427
  self._msat_lib.MSAT_TAG_BV_LSHR: self._back_adapter(self.mgr.BVLShr),
428
428
  self._msat_lib.MSAT_TAG_BV_ASHR: self._back_adapter(self.mgr.BVAShr),
429
429
  self._msat_lib.MSAT_TAG_BV_COMP: self._back_adapter(self.mgr.BVComp),
430
+ self._msat_lib.MSAT_TAG_FLOOR: self._back_adapter(self.mgr.ToInt),
430
431
  self._msat_lib.MSAT_TAG_INT_FROM_UBV: self._back_adapter(self.mgr.BVToNatural),
431
432
  self._msat_lib.MSAT_TAG_ARRAY_READ: self._back_adapter(self.mgr.Select),
432
433
  self._msat_lib.MSAT_TAG_ARRAY_WRITE: self._back_adapter(self.mgr.Store),
@@ -461,6 +462,8 @@ class MSatConverter(Converter, DagWalker):
461
462
  self._msat_lib.MSAT_TAG_LEQ: self._sig_most_generic_bool_binary,
462
463
  self._msat_lib.MSAT_TAG_PLUS: self._sig_most_generic_bool_binary,
463
464
  self._msat_lib.MSAT_TAG_TIMES: self._sig_most_generic_bool_binary,
465
+ self._msat_lib.MSAT_TAG_FLOOR: lambda term, args:\
466
+ types.FunctionType(types.INT, [types.REAL]),
464
467
  self._msat_lib.MSAT_TAG_BV_MUL: self._sig_binary,
465
468
  self._msat_lib.MSAT_TAG_BV_ADD: self._sig_binary,
466
469
  self._msat_lib.MSAT_TAG_BV_UDIV:self._sig_binary,
@@ -1004,6 +1007,9 @@ class MSatConverter(Converter, DagWalker):
1004
1007
  # In mathsat toreal is implicit
1005
1008
  return args[0]
1006
1009
 
1010
+ def walk_toint(self, formula: FNode, args: List[Any], **kwargs) -> Any:
1011
+ return self._msat_lib.msat_make_floor(self.msat_env(), args[0])
1012
+
1007
1013
  def walk_bv_tonatural(self, formula: FNode, args: List[Any], **kwargs) -> Any:
1008
1014
  return self._msat_lib.msat_make_int_from_ubv(self.msat_env(), args[0])
1009
1015
 
pysmt/solvers/yices.py CHANGED
@@ -470,6 +470,11 @@ class YicesConverter(Converter, DagWalker):
470
470
  def walk_toreal(self, formula: FNode, args, **kwargs):
471
471
  return args[0]
472
472
 
473
+ def walk_toint(self, formula: FNode, args, **kwargs):
474
+ res = yices_api.yices_floor(args[0])
475
+ self._check_term_result(res)
476
+ return res
477
+
473
478
  def walk_function(self, formula: FNode, args, **kwargs):
474
479
  name = formula.function_name()
475
480
  if name not in self.symbol_to_decl:
pysmt/solvers/z3.py CHANGED
@@ -340,6 +340,8 @@ class Z3Converter(Converter, DagWalker):
340
340
  z3.Z3_OP_IMPLIES: lambda args, expr: self.mgr.Implies(args[0], args[1]),
341
341
  z3.Z3_OP_ITE: lambda args, expr: self.mgr.Ite(args[0], args[1], args[2]),
342
342
  z3.Z3_OP_TO_REAL: lambda args, expr: self.mgr.ToReal(args[0]),
343
+ z3.Z3_OP_TO_INT: lambda args, expr: self.mgr.ToInt(args[0]),
344
+ z3.Z3_OP_IS_INT: lambda args, expr: self.mgr.IsInt(args[0]),
343
345
  z3.Z3_OP_BAND : lambda args, expr: self.mgr.BVAnd(args),
344
346
  z3.Z3_OP_BOR : lambda args, expr: self.mgr.BVOr(args),
345
347
  z3.Z3_OP_BXOR : lambda args, expr: self.mgr.BVXor(args[0], args[1]),
@@ -737,6 +739,11 @@ class Z3Converter(Converter, DagWalker):
737
739
  z3.Z3_inc_ref(self.ctx.ref(), z3term)
738
740
  return z3term
739
741
 
742
+ def walk_toint(self, formula, args, **kwargs):
743
+ z3term = z3.Z3_mk_real2int(self.ctx.ref(), args[0])
744
+ z3.Z3_inc_ref(self.ctx.ref(), z3term)
745
+ return z3term
746
+
740
747
  def _z3_func_decl(self, func_name):
741
748
  """Create a Z3 Function Declaration for the given function."""
742
749
  try:
pysmt/test/examples.py CHANGED
@@ -23,7 +23,7 @@ from pysmt.shortcuts import (Symbol, Function,
23
23
  Int, Real, FALSE, TRUE,
24
24
  And, Iff, Or, Not, Implies, Ite,
25
25
  LT, LE, GT, GE,
26
- Times, Pow, Equals, Plus, Minus, Div, ToReal,
26
+ Times, Pow, Equals, Plus, Minus, Div, ToReal, ToInt,
27
27
  ForAll, Exists,
28
28
  BV, SBV, BVOne, BVZero,
29
29
  BVNot, BVAnd, BVOr, BVXor,
@@ -698,6 +698,32 @@ def get_full_example_formulae(environment: Optional[Environment]=None) -> List[E
698
698
  is_sat=False,
699
699
  logic=pysmt.logics.QF_UFLIRA
700
700
  ),
701
+
702
+ # ToInt is the floor, hence it rounds towards minus infinity
703
+ Example(hr="((r = -3/2) -> (ToInt(r) = -2))",
704
+ expr=Implies(Equals(r, Real(Fraction(-3, 2))),
705
+ Equals(ToInt(r), Int(-2))),
706
+ is_valid=True,
707
+ is_sat=True,
708
+ logic=pysmt.logics.QF_LIRA
709
+ ),
710
+
711
+ # ToInt must not truncate towards zero
712
+ Example(hr="((r = -3/2) & (ToInt(r) = -1))",
713
+ expr=And(Equals(r, Real(Fraction(-3, 2))),
714
+ Equals(ToInt(r), Int(-1))),
715
+ is_valid=False,
716
+ is_sat=False,
717
+ logic=pysmt.logics.QF_LIRA
718
+ ),
719
+
720
+ Example(hr="((ToInt(r) = p) & (0.0 < r))",
721
+ expr=And(Equals(ToInt(r), p),
722
+ GT(r, Real(0))),
723
+ is_valid=False,
724
+ is_sat=True,
725
+ logic=pysmt.logics.QF_LIRA
726
+ ),
701
727
  #
702
728
  # STR
703
729
  #
@@ -118,6 +118,7 @@ class TestSMTParseExamples(TestCase):
118
118
  logics.QF_BOOL: logics.QF_UF,
119
119
  logics.BOOL: logics.LRA,
120
120
  logics.QF_NIRA: logics.AUFNIRA,
121
+ logics.QF_LIRA: logics.QF_UFLIRA,
121
122
  }
122
123
  fs = get_example_formulae()
123
124
 
pysmt/test/test_lira.py CHANGED
@@ -16,9 +16,11 @@
16
16
  # limitations under the License.
17
17
  #
18
18
  from pysmt.shortcuts import *
19
+ from pysmt.constants import Fraction
20
+ from pysmt.exceptions import PysmtTypeError
19
21
  from pysmt.typing import INT, REAL, FunctionType
20
22
  from pysmt.test import TestCase, main
21
- from pysmt.logics import QF_UFLIRA, UFLIRA
23
+ from pysmt.logics import QF_LIRA, QF_UFLIRA, UFLIRA
22
24
 
23
25
  class TestLIRA(TestCase):
24
26
 
@@ -47,6 +49,80 @@ class TestLIRA(TestCase):
47
49
  ToReal(ToReal(Plus(b, Int(1)))))
48
50
 
49
51
 
52
+ def test_toint_is_floor(self):
53
+ # to_int rounds towards minus infinity, it does not truncate
54
+ self.assertEqual(ToInt(Real(Fraction(-3, 2))), Int(-2))
55
+ self.assertEqual(ToInt(Real(Fraction(3, 2))), Int(1))
56
+ self.assertEqual(ToInt(Real(Fraction(-1, 3))), Int(-1))
57
+ self.assertEqual(ToInt(Real(0)), Int(0))
58
+ self.assertEqual(ToInt(Real(-2)), Int(-2))
59
+
60
+
61
+ def test_toint(self):
62
+ a = Symbol("a", REAL)
63
+ b = Symbol("b", INT)
64
+
65
+ # Casting an Int is a no-op
66
+ self.assertEqual(b, ToInt(b))
67
+ self.assertEqual(Plus(b, Int(1)), ToInt(Plus(b, Int(1))))
68
+
69
+ self.assertTrue(ToInt(a).is_toint())
70
+ self.assertEqual(get_type(ToInt(a)), INT)
71
+
72
+ for bad in (TRUE(), Symbol("x"), BV(1, 8)):
73
+ with self.assertRaises(PysmtTypeError):
74
+ ToInt(bad)
75
+
76
+
77
+ def test_toint_simplify(self):
78
+ a = Symbol("a", REAL)
79
+ b = Symbol("b", INT)
80
+
81
+ # to_int(to_real(b)) is b, since b is an integer
82
+ self.assertEqual(b, ToInt(ToReal(b)).simplify())
83
+ self.assertEqual(Plus(b, Int(1)),
84
+ ToInt(ToReal(Plus(b, Int(1)))).simplify())
85
+
86
+ # The converse does NOT hold: to_real(to_int(a)) is a only when a
87
+ # happens to have an integer value.
88
+ self.assertNotEqual(a, ToReal(ToInt(a)).simplify())
89
+
90
+
91
+ def test_isint(self):
92
+ a = Symbol("a", REAL)
93
+ b = Symbol("b", INT)
94
+
95
+ # is_int is expanded into its SMT-LIB definition
96
+ self.assertEqual(IsInt(a), Equals(a, ToReal(ToInt(a))))
97
+ # An Int is trivially an integer
98
+ self.assertEqual(IsInt(b), TRUE())
99
+
100
+ with self.assertRaises(PysmtTypeError):
101
+ IsInt(TRUE())
102
+
103
+
104
+ def test_toint_solving(self):
105
+ a = Symbol("a", REAL)
106
+
107
+ for sname in get_env().factory.all_solvers(logic=QF_LIRA):
108
+ # 7/2 floors to 3
109
+ self.assertSat(And(Equals(a, Real(Fraction(7, 2))),
110
+ Equals(ToInt(a), Int(3))),
111
+ solver_name=sname)
112
+ # -3/2 floors to -2, and in particular not to -1
113
+ self.assertSat(And(Equals(a, Real(Fraction(-3, 2))),
114
+ Equals(ToInt(a), Int(-2))),
115
+ solver_name=sname)
116
+ self.assertUnsat(And(Equals(a, Real(Fraction(-3, 2))),
117
+ Equals(ToInt(a), Int(-1))),
118
+ solver_name=sname)
119
+ # 1/2 is not an integer
120
+ self.assertUnsat(And(IsInt(a), Equals(a, Real(Fraction(1, 2)))),
121
+ solver_name=sname)
122
+ self.assertSat(And(IsInt(a), Equals(a, Real(Fraction(4, 2)))),
123
+ solver_name=sname)
124
+
125
+
50
126
  def test_uflira(self):
51
127
  a = Symbol("a", REAL)
52
128
  b = Symbol("b", INT)
@@ -20,7 +20,7 @@ from io import StringIO
20
20
  from pysmt.shortcuts import Or, And, Not, Plus, Iff, Implies
21
21
  from pysmt.shortcuts import Exists, ForAll, Ite, ExactlyOne
22
22
  from pysmt.shortcuts import Bool, Real, Int, Symbol, Function
23
- from pysmt.shortcuts import Times, Minus, Equals, LE, LT, ToReal, FreshSymbol
23
+ from pysmt.shortcuts import Times, Minus, Equals, LE, LT, ToReal, ToInt, FreshSymbol
24
24
  from pysmt.typing import REAL, INT, FunctionType
25
25
  from pysmt.smtlib.printers import SmtPrinter, SmtDagPrinter
26
26
  from pysmt.smtlib.annotations import Annotations
@@ -139,6 +139,14 @@ class TestPrinting(TestCase):
139
139
  self.assertEqual(rp.to_smtlib(daggify=False), "(to_real p)")
140
140
  self.assertEqual(rp.to_smtlib(daggify=True), "(let ((.def_0 (to_real p))) .def_0)")
141
141
 
142
+ def test_toint(self):
143
+ r = Symbol("r", REAL)
144
+ ir = ToInt(r)
145
+
146
+ self.assertEqual(ir.to_smtlib(daggify=False), "(to_int r)")
147
+ self.assertEqual(ir.to_smtlib(daggify=True), "(let ((.def_0 (to_int r))) .def_0)")
148
+ self.assertEqual(ir.serialize(), "ToInt(r)")
149
+
142
150
  def test_threshold_printing(self):
143
151
  x = Symbol("x")
144
152
  f = And(x,x)
pysmt/type_checker.py CHANGED
@@ -79,6 +79,11 @@ class SimpleTypeChecker(walkers.DagWalker):
79
79
  #pylint: disable=unused-argument
80
80
  return self.walk_type_to_type(formula, args, INT, REAL)
81
81
 
82
+ @walkers.handles(op.TOINT)
83
+ def walk_real_to_int(self, formula: FNode, args: List[PySMTType], **kwargs) -> Optional[PySMTType]:
84
+ #pylint: disable=unused-argument
85
+ return self.walk_type_to_type(formula, args, REAL, INT)
86
+
82
87
  def walk_real_to_real(self, formula: FNode, args: List[PySMTType], **kwargs) -> Optional[PySMTType]:
83
88
  #pylint: disable=unused-argument
84
89
  return self.walk_type_to_type(formula, args, REAL, REAL)
@@ -114,6 +114,9 @@ class IdentityDagWalker(DagWalker):
114
114
  def walk_toreal(self, formula: FNode, args: List[FNode], **kwargs) -> FNode:
115
115
  return self.mgr.ToReal(args[0])
116
116
 
117
+ def walk_toint(self, formula: FNode, args: List[FNode], **kwargs) -> FNode:
118
+ return self.mgr.ToInt(args[0])
119
+
117
120
  def walk_bv_constant(self, formula: FNode, **kwargs) -> FNode:
118
121
  return self.mgr.BV(cast(int, formula.constant_value()), formula.bv_width())
119
122
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PySMT
3
- Version: 0.9.7.dev431
3
+ Version: 0.9.7.dev433
4
4
  Summary: A solver-agnostic library for SMT Formulae manipulation and solving
5
5
  Home-page: http://www.pysmt.org
6
6
  Author: PySMT Team
@@ -1,4 +1,4 @@
1
- pysmt/__init__.py,sha256=i5sG2soSbeXz4N7EIPPiKx_K1yNeoxD603-viPBU7Hk,1701
1
+ pysmt/__init__.py,sha256=3fqAzPQlXGHf1Ffs6yhccGmhry4ISQoFXyzAIHRNA6w,1701
2
2
  pysmt/__main__.py,sha256=rR-MV1QtLYqtVoJyY3m5B5Iz-lua0-5o6YSB0W4lKy8,1085
3
3
  pysmt/configuration.py,sha256=Iq_46QZ9z_jpBMk76euJWTqGEwHad2qyiEDPix5sXsA,4538
4
4
  pysmt/constants.py,sha256=pulb6NvROY_X8BePeyyX8T9MJLB79HZ_1FUYSlZ7Jfg,5769
@@ -6,18 +6,18 @@ pysmt/decorators.py,sha256=dZWnu0lwfVBq6WGoohH5EWVpi6xr-uAEtFBjDUJgnoo,4106
6
6
  pysmt/environment.py,sha256=UUcccuTIGRYdIxvso4aUvfwJiveoDdOwRgTcVHkuupc,7056
7
7
  pysmt/exceptions.py,sha256=l7JmvC9VML32HeZwIhgxf5L-NQjbbpX4aHCdO9d56nM,5637
8
8
  pysmt/factory.py,sha256=wxqu-SkHFk_iPOkQwDj8L-bhIfCLN37x5GdfhlCha_o,31879
9
- pysmt/fnode.py,sha256=SJ35GNwjYOwxMrexttCmVj5ZddFQ52GFATTSyArUuX0,36313
10
- pysmt/formula.py,sha256=c-2gZmumCzpSzNPpbVGs6_H-lZtgMjQwDmyi04FmleM,49119
9
+ pysmt/fnode.py,sha256=5K0z8Qy3jIbB4N-lyBESXyzDpBDPD92jryNNd50NdLk,36453
10
+ pysmt/formula.py,sha256=gUqv0V91Tww9GVeOD2Z_gsZlthUe8NADd0ZbYmK2CEk,50770
11
11
  pysmt/logics.py,sha256=HQaq2Odqw8oFNCAo1av0zaFOcPujTopO8frWSBsmNtg,29348
12
- pysmt/operators.py,sha256=h4paq_sIatt49--6Ch2cQPfMPFs0mb4ZztM5N1r31kM,8188
13
- pysmt/oracles.py,sha256=Q8m2ju9hZUrKYd36JPxabAPc6jjgIrVUu9NgFq1JIsU,21433
14
- pysmt/parsing.py,sha256=ndADbJ1hCz2JcAGN7MMvVPpHKtR4WhPinB_2EEEtS7o,20960
15
- pysmt/printers.py,sha256=nx8N4uQ6Hp591JyE98hdjKlO6x0lqL9dr2AGf07a644,14955
12
+ pysmt/operators.py,sha256=XGPPoX5bdDsroAkr5rUAiBdi7BXkPaOyst7jEWqLTa0,8329
13
+ pysmt/oracles.py,sha256=fg1ORZGCTsVXMCZDKRKFHtW7uV79qF_XRxxSFv2R4Vs,21698
14
+ pysmt/parsing.py,sha256=dj1lBgry0KEKSz16RNY_h_nQ2KaSX_trfLJu-rDnYeA,21078
15
+ pysmt/printers.py,sha256=fB2aPwsV7qQxgtqgVndUA_1wWBp5vMPzqBxngmBJmk4,15099
16
16
  pysmt/rewritings.py,sha256=-oGrrwGt2Rl8_CkT2wy8dTRTHAk4Dxsn43aPpv-NCN0,42207
17
- pysmt/shortcuts.py,sha256=EzwH0wXDXDWeQs46GKMQf3W-x1AGkwisaQJt6xodqso,44599
18
- pysmt/simplifier.py,sha256=s5jUxql86MjZ77_deoFbOVvnDe-5Tj_xpyK3VQtpj6c,44900
17
+ pysmt/shortcuts.py,sha256=Xiq5JnkjefgwuJAEbmMAjnkyqu35MoALnSp2NYtIeDg,44962
18
+ pysmt/simplifier.py,sha256=RcIj0xofu8TstlGH26h1xzX9zw4cJ--O9t9hSFxfbeQ,45384
19
19
  pysmt/substituter.py,sha256=sTW-Phkq6Ae8xft_eLrXR06wJZ6C3EgpkZoqj_HLLMc,14446
20
- pysmt/type_checker.py,sha256=0XfiYad4swJeKRXy1W4eGbidrU371s4qqHcy8AfXZ7g,15793
20
+ pysmt/type_checker.py,sha256=kJvj7qOTG68QgsQpUMnnxTbJl2S0GLbgRj_dG_E5jxM,16034
21
21
  pysmt/typing.py,sha256=aI8ZKEin4J2XLAHsY5fW1Pt4hZvlBlArxM4nrrmBas4,19550
22
22
  pysmt/utils.py,sha256=_dSgl45k-u9cMXSyR672GBJcKMKdtl6xSTjqXKTSfcs,2906
23
23
  pysmt/cmd/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -45,31 +45,31 @@ pysmt/optimization/z3.py,sha256=qhSQ0wR487555yYW9vSvLaIMutKN05cczPPITK_O_u4,7270
45
45
  pysmt/smtlib/__init__.py,sha256=JXBHtcb4Lv-Sb8whc9JuGbRH2EBLWwtLUh3PL9HhNE8,650
46
46
  pysmt/smtlib/annotations.py,sha256=UTl_nnBikMGKzdpW5N17yIpvx-_8HZmo8hxXIKsm7Wo,4596
47
47
  pysmt/smtlib/commands.py,sha256=hwWnXrzZxJmKtkIitHRtuin01WDUErT0VERR9h45t2A,2277
48
- pysmt/smtlib/printers.py,sha256=ZZMx1d0aS5kGDqJj1c7PYCEXqgXnk_CugcVAVinrtzk,25940
48
+ pysmt/smtlib/printers.py,sha256=072iwQcAWzaREXh5nYinUjH1xOuYuU2HfDmSYHItw6M,26138
49
49
  pysmt/smtlib/script.py,sha256=RWJT9KA_LH23YNqhtosc10LaH8Z_6Hj1YNDuf_qqLIc,24099
50
50
  pysmt/smtlib/solver.py,sha256=NUtBsghqgTAPEH2am4_Aq6BYz2ugGPRWGzpdzMQpAr4,8062
51
51
  pysmt/smtlib/utils.py,sha256=C-P8RPgR8RDRQnrB8xfLGc5aFso11u0sEtFw04NMbKQ,2126
52
52
  pysmt/smtlib/parser/__init__.py,sha256=Pfdm6pv9hwOv8D9NbAaHEokDZXkRg3CwYLN5Ny7UNyY,5055
53
- pysmt/smtlib/parser/parser.py,sha256=yXNm3VJDgtSFDA41-iKkgeZVhlUXqKskj9Xsgbja7iE,67454
53
+ pysmt/smtlib/parser/parser.py,sha256=a4BWhJqGIuz3csH1A_a_sPPc-191WoxmzLRzar9D-WQ,67568
54
54
  pysmt/solvers/__init__.py,sha256=JXBHtcb4Lv-Sb8whc9JuGbRH2EBLWwtLUh3PL9HhNE8,650
55
55
  pysmt/solvers/bdd.py,sha256=NG0BHE5-nqfn6vdUZjJIxiBH1ZwdkTgJKSeQGORaCFc,15961
56
56
  pysmt/solvers/btor.py,sha256=V9pAVMhvjmejyrMiQNrpxQFQ8VzmebhRcvuSSwTcAvQ,26033
57
- pysmt/solvers/cvcfive.py,sha256=fxt2lMUjMC2g4vRQkZQY3xLnKPa5X7SIbGs7fHWJGdY,25205
58
- pysmt/solvers/cvcfour.py,sha256=iMMpFRxr7EoNjZnO64q7R1rIodQqw71Cv1JiIdj6kzE,24471
57
+ pysmt/solvers/cvcfive.py,sha256=Kvf-M8xOwuaQz4aZ8et_OP4tVrjW7wOY2uRbkTkwTUU,25322
58
+ pysmt/solvers/cvcfour.py,sha256=410vzWLtXNRJKCNfKpo39vYyVZflrUNA0X_SswI-UmI,24576
59
59
  pysmt/solvers/dynmsat.py,sha256=bJokwHoxKWmQGqw9nQerRDb33d5c66Sa91jUYiZXwY0,2124
60
60
  pysmt/solvers/eager.py,sha256=ZvtXsD-4QAhjd8gRNb_CrosjSLEJn07YEwVEMKTnHAg,3634
61
61
  pysmt/solvers/interpolation.py,sha256=6AO1wMkEKSkptuC4aXlNEO8Be1K2oW3W_er2XGc_aEA,2066
62
- pysmt/solvers/msat.py,sha256=FNsufZycnGjbjIdMRnupSSQKo3J4KtlhSRKmSIHWzRU,60115
62
+ pysmt/solvers/msat.py,sha256=-sDEc87PBXubBw3Csnm18C9e354ZjRdmKvumTyHD6Vo,60467
63
63
  pysmt/solvers/options.py,sha256=DRNUMb5Tlhai4keQkF7Kg34tf3AGbBUd45mqzjsS69c,4036
64
64
  pysmt/solvers/pico.py,sha256=1fN9hy22ym0FYbLYhSoADx1StQBxwd60Kx_RqcUtXdA,10653
65
65
  pysmt/solvers/portfolio.py,sha256=v2OvmQdh84YlXKZQgc_cx3UQ7MPL8l5heOV6WHEyXnU,9809
66
66
  pysmt/solvers/qelim.py,sha256=x3XIhdDdqxlCj4ZNa5WxORiepWjAAM3IWNLn4rfl5zM,5342
67
67
  pysmt/solvers/smtlib.py,sha256=uUG4ux175AJYLoejgvWoTY5qGwcXmUMTD574EMks5gE,9714
68
68
  pysmt/solvers/solver.py,sha256=zZRlGzrerPlZtIAiKGU9q3b4zTphSPdWl-xeCsnAgxA,19315
69
- pysmt/solvers/yices.py,sha256=jGWCic29--1VYWW_JXIp5RmlJY9xj2Pdv61n3ElKZII,25750
70
- pysmt/solvers/z3.py,sha256=_lk-Ifo31D9nS7NNjdyQk2--Wm9gVlKmHoYbQfJRJlA,44259
69
+ pysmt/solvers/yices.py,sha256=uG08Q9iqctXk-2rDP6H5OO88FE_ml83K0k5j8irpbcg,25910
70
+ pysmt/solvers/z3.py,sha256=W-MAj83Kaqz8OCA2QX8-IXnj2ud0SXy17Wxf98o7L3c,44585
71
71
  pysmt/test/__init__.py,sha256=LEFbVYw4X45sgEI4_ax55g-6G5Y7kj6CLaJr1TQr4ks,5750
72
- pysmt/test/examples.py,sha256=uMc4MzgFAPpu3eZF3ZdmHdyumt9SFWUy2GWTSzN8EN4,39703
72
+ pysmt/test/examples.py,sha256=6yWa-hHEMJuo5GEbjWmzg509-LQxVAyr26lxGhcK_jU,40756
73
73
  pysmt/test/omt_examples.py,sha256=LdL43fLaHiR72Cng_2st4UaYf2ueoZgStcvhccy-RdI,10338
74
74
  pysmt/test/optimization_utils.py,sha256=zbj2bN-3uMaNexF7DSjuQAR0889IcMsCiE__tGtR6zM,15665
75
75
  pysmt/test/test_array.py,sha256=OypmqKf_ciigxK1X_W2b9sm0EWOA3wqH376QXt7oGCM,6237
@@ -90,7 +90,7 @@ pysmt/test/test_hr_parsing.py,sha256=bi-iTu7y1C7diMcWsQ7EI40MipDbzTKbMGPnLWX85A8
90
90
  pysmt/test/test_imports.py,sha256=f41EUBrlDItgQ_6SPhWW8-tuwMrdMFXHJzaxrHHB43Q,1583
91
91
  pysmt/test/test_int.py,sha256=dk72Q6viqRUs9XiPB40n6RrwiqsV6GbbKuSlYaQMU9k,1980
92
92
  pysmt/test/test_interpolation.py,sha256=WTodZtnxH5slIvUWbHbjjnI2o0naXgZwZawTGhh3E0o,3941
93
- pysmt/test/test_lira.py,sha256=1B4y1y2U-5CttF6h22tniJkAedUDIwjp1Ad0_Ha_s-8,2175
93
+ pysmt/test/test_lira.py,sha256=o8z7Bcb9zH2ptC7oYTueAJB05a-SINh2a__UNUUP610,5006
94
94
  pysmt/test/test_logics.py,sha256=bWwE_7rq9SVcXglE-ugteGeCHXAYFiBdi-QgIL9-9KE,6893
95
95
  pysmt/test/test_models.py,sha256=npqGoF-3DgAw0DTx6se32ZEZRFBJDcnkppzgyjLDbps,2748
96
96
  pysmt/test/test_native_qe.py,sha256=RGZgwbpAkPBTjIqcCbOkZ_nQXIDZ4Fznrr7Ldx6oA38,3439
@@ -100,7 +100,7 @@ pysmt/test/test_optimization.py,sha256=xU0gJbD2SSn5_lA7wF7IKcR54KF6NU0g-2_dDEqXm
100
100
  pysmt/test/test_optimizing.py,sha256=P-XnTPEPoEp5LvvZfZoiZziI4z3d_FfL7lFcEuI07bE,1512
101
101
  pysmt/test/test_oracles.py,sha256=cHBPTUoi9cPmIvR-DG4bbzohOaBdUJzpKLoQXImxS_c,5615
102
102
  pysmt/test/test_portfolio.py,sha256=k0Jdrdr-EX-BVCxqYNUS3YjC77aCpzzdhezjB8U3OCM,7125
103
- pysmt/test/test_printing.py,sha256=glsnaMRungLc31JIJTmHlT69JnTPsC5pnYn1rZriV2s,8765
103
+ pysmt/test/test_printing.py,sha256=MwxLcmpwN0DYLlqGNrOZM4U1RPdTM1k75_IMKWQFLts,9064
104
104
  pysmt/test/test_qe.py,sha256=k8zYX-lcij0ua9yuRXl7wErUklEgLSEh68QDpV8J9xs,7157
105
105
  pysmt/test/test_regressions.py,sha256=Wuah55f5rROEkhTho_zl-uwaMDzc4LPeP3lfQ6nzS8k,21977
106
106
  pysmt/test/test_rewritings.py,sha256=1eeseDwZyQD2VrOFBABXHTYJFJOXszP4olbCNeLcwfA,15607
@@ -124,7 +124,7 @@ pysmt/test/smtlib/test_generic_wrapper.py,sha256=UOVNZ8dWqUJNfNkFsXp0fz4CNMFvybl
124
124
  pysmt/test/smtlib/test_griggio.py,sha256=W8C5SWABwUeAQdnslQoU_6pxFokaz2cT5sAfJLo1cKw,2959
125
125
  pysmt/test/smtlib/test_model_validation.py,sha256=xHHBkbANSNnxuc8HFUVcEANde0zsZZdTWPtIWVazw7c,3076
126
126
  pysmt/test/smtlib/test_omt_lib_solver.py,sha256=xZZWDSB0eDBsmzu7R8AqRN0fSCvFRW6x4Cq9MmTAfos,8177
127
- pysmt/test/smtlib/test_parser_examples.py,sha256=5e0pNN5rjgi5cLAJl4ZZuUiifCUgVaD__JfBlVJgMR4,10100
127
+ pysmt/test/smtlib/test_parser_examples.py,sha256=Rghq3y-ecce-FYlKURIZAIHeMAd3H-k7JTcWH-kpNvg,10146
128
128
  pysmt/test/smtlib/test_parser_extensibility.py,sha256=MgEVUU-icDEryKh54sW9VC59e8CuC6Q_5Sw65FtxBgo,3933
129
129
  pysmt/test/smtlib/test_parser_lra.py,sha256=N6HD1BqSb88FpOeaHsKME5IOok3Eu3YdpM55XgDFs3s,997
130
130
  pysmt/test/smtlib/test_parser_omt.py,sha256=XhS6Fmy5c1xRya45QlyJuzuV7jdnFfrkig-zZkQrJO0,9564
@@ -141,12 +141,12 @@ pysmt/test/smtlib/test_smtlibscript.py,sha256=oyiilRk7PARXA4NDHfYoqpGP5BUrsBGt7x
141
141
  pysmt/walkers/__init__.py,sha256=xJWAK99BWnVSo_vcpBDaH06SxpF64HWd36A4BE_t05g,1658
142
142
  pysmt/walkers/dag.py,sha256=4CWSgoXm6nONhM-1znKRU4SBCb791OTS-M9QlQFhbs8,5751
143
143
  pysmt/walkers/generic.py,sha256=dmp47kJGtO6rhC2t07Mf_FsYN-lcy64LX-dZggNnWm4,5179
144
- pysmt/walkers/identitydag.py,sha256=DBPaDuIgvZZz1ohKyoWcDeQVa3RgMQDnqn4Jo7gwtNs,10782
144
+ pysmt/walkers/identitydag.py,sha256=EAxSneEW91Z8GphlkbMPsPdlac7_FDcVj-_6_aunU2s,10902
145
145
  pysmt/walkers/tree.py,sha256=8oyDSXZtUsCdExcrwG3hKuEgARHgdW6fvz0LZJwjp-k,2983
146
- pysmt-0.9.7.dev431.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
147
- pysmt-0.9.7.dev431.dist-info/licenses/NOTICE,sha256=Ns-Jsa6nbqZUiTEEAM6HqioSZIxQ2RCJzxoBlWQaUfc,601
148
- pysmt-0.9.7.dev431.dist-info/METADATA,sha256=QcXLPhcitd6QBScf86ZsMC2LPFvJ5M5qgagPBxj-bkk,1774
149
- pysmt-0.9.7.dev431.dist-info/WHEEL,sha256=TdQ5LtNwLuxTCjgxN51AgdU5w-KkB9ttmLbzjTH02pg,109
150
- pysmt-0.9.7.dev431.dist-info/entry_points.txt,sha256=gDc1XM0xTJJMDGC_nXd0kfbX-Omjke9Dn9F3awMLYIU,57
151
- pysmt-0.9.7.dev431.dist-info/top_level.txt,sha256=NwHQbpTaZMEvjIUdC0bvvj-WUyULe-nt-opK3YQNRMk,6
152
- pysmt-0.9.7.dev431.dist-info/RECORD,,
146
+ pysmt-0.9.7.dev433.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
147
+ pysmt-0.9.7.dev433.dist-info/licenses/NOTICE,sha256=Ns-Jsa6nbqZUiTEEAM6HqioSZIxQ2RCJzxoBlWQaUfc,601
148
+ pysmt-0.9.7.dev433.dist-info/METADATA,sha256=0Tm9O6Fmy0LH94YlyULyAyMc--yExxXER6l-AZ_94ow,1774
149
+ pysmt-0.9.7.dev433.dist-info/WHEEL,sha256=4YBfCYNH4wlLpv3pzq1hbEuIlXA4WJabKLFurZ7eTL0,109
150
+ pysmt-0.9.7.dev433.dist-info/entry_points.txt,sha256=gDc1XM0xTJJMDGC_nXd0kfbX-Omjke9Dn9F3awMLYIU,57
151
+ pysmt-0.9.7.dev433.dist-info/top_level.txt,sha256=NwHQbpTaZMEvjIUdC0bvvj-WUyULe-nt-opK3YQNRMk,6
152
+ pysmt-0.9.7.dev433.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (82.0.1)
2
+ Generator: setuptools (84.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any