1 from collections import defaultdict
2 from fractions import Fraction
5 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
7 from libcpp.pair cimport pair
8 from libcpp.set cimport set
9 from libcpp.string cimport string
10 from libcpp.vector cimport vector
12 from cvc5 cimport cout
13 from cvc5 cimport Datatype as c_Datatype
14 from cvc5 cimport DatatypeConstructor as c_DatatypeConstructor
15 from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
16 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
17 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
18 from cvc5 cimport Result as c_Result
19 from cvc5 cimport RoundingMode as c_RoundingMode
20 from cvc5 cimport Op as c_Op
21 from cvc5 cimport Solver as c_Solver
22 from cvc5 cimport Grammar as c_Grammar
23 from cvc5 cimport Sort as c_Sort
24 from cvc5 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
25 from cvc5 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO
26 from cvc5 cimport ROUND_NEAREST_TIES_TO_AWAY
27 from cvc5 cimport Term as c_Term
28 from cvc5 cimport hash as c_hash
30 from cvc5kinds cimport Kind as c_Kind
32 ################################## DECORATORS #################################
33 def expand_list_arg(num_req_args=0):
35 Creates a decorator that looks at index num_req_args of the args,
36 if it's a list, it expands it before calling the function.
39 def wrapper(owner, *args):
40 if len(args) == num_req_args + 1 and \
41 isinstance(args[num_req_args], list):
42 args = list(args[:num_req_args]) + args[num_req_args]
43 return func(owner, *args)
46 ###############################################################################
49 ### Using PEP-8 spacing recommendations
50 ### Limit linewidth to 79 characters
51 ### Break before binary operators
52 ### surround top level functions and classes with two spaces
53 ### separate methods by one space
54 ### use spaces in functions sparingly to separate logical blocks
55 ### can omit spaces between unrelated oneliners
56 ### always use c++ default arguments
57 #### only use default args of None at python level
59 # References and pointers
60 # The Solver object holds a pointer to a c_Solver.
61 # This is because the assignment operator is deleted in the C++ API for solvers.
62 # Cython has a limitation where you can't stack allocate objects
63 # that have constructors with arguments:
64 # https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs.
65 # To get around that you can either have a nullary constructor and assignment
66 # or, use a pointer (which is what we chose).
67 # An additional complication of this is that to free up resources, you must
68 # know when to delete the object.
69 # Python will not follow the same scoping rules as in C++, so it must be
70 # able to reference count. To do this correctly, the solver must be a
71 # reference in the Python class for any class that keeps a pointer to
72 # the solver in C++ (to ensure the solver is not deleted before something
73 # that depends on it).
76 ## Objects for hashing
77 cdef c_hash[c_Op] cophash = c_hash[c_Op]()
78 cdef c_hash[c_Sort] csorthash = c_hash[c_Sort]()
79 cdef c_hash[c_Term] ctermhash = c_hash[c_Term]()
83 """Wrapper class for :cpp:class:`cvc5::api::Datatype`."""
86 def __cinit__(self, Solver solver):
89 def __getitem__(self, index):
90 """Return a constructor by index or by name."""
91 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
92 if isinstance(index, int) and index >= 0:
93 dc.cdc = self.cd[(<int?> index)]
94 elif isinstance(index, str):
95 dc.cdc = self.cd[(<const string &> index.encode())]
97 raise ValueError("Expecting a non-negative integer or string")
100 def getConstructor(self, str name):
101 """Return a constructor by name."""
102 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
103 dc.cdc = self.cd.getConstructor(name.encode())
106 def getConstructorTerm(self, str name):
107 """:return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::api::Datatype::getConstructorTerm>`)."""
108 cdef Term term = Term(self.solver)
109 term.cterm = self.cd.getConstructorTerm(name.encode())
112 def getNumConstructors(self):
113 """:return: number of constructors."""
114 return self.cd.getNumConstructors()
116 def isParametric(self):
117 """:return: whether this datatype is parametric."""
118 return self.cd.isParametric()
120 def isCodatatype(self):
121 """:return: whether this datatype corresponds to a co-datatype."""
122 return self.cd.isCodatatype()
125 """:return: whether this datatype corresponds to a tuple."""
126 return self.cd.isTuple()
129 """:return: whether this datatype corresponds to a record."""
130 return self.cd.isRecord()
133 """:return: whether this datatype is finite."""
134 return self.cd.isFinite()
136 def isWellFounded(self):
137 """:return: whether this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::api::Datatype::isWellFounded>`)."""
138 return self.cd.isWellFounded()
140 def hasNestedRecursion(self):
141 """:return: whether this datatype has nested recursion (see :cpp:func:`Datatype::hasNestedRecursion() <cvc5::api::Datatype::hasNestedRecursion>`)."""
142 return self.cd.hasNestedRecursion()
145 return self.cd.toString().decode()
148 return self.cd.toString().decode()
152 dc = DatatypeConstructor(self.solver)
157 cdef class DatatypeConstructor:
158 cdef c_DatatypeConstructor cdc
160 def __cinit__(self, Solver solver):
161 self.cdc = c_DatatypeConstructor()
164 def __getitem__(self, index):
165 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
166 if isinstance(index, int) and index >= 0:
167 ds.cds = self.cdc[(<int?> index)]
168 elif isinstance(index, str):
169 ds.cds = self.cdc[(<const string &> name.encode())]
171 raise ValueError("Expecting a non-negative integer or string")
175 return self.cdc.getName().decode()
177 def getConstructorTerm(self):
178 cdef Term term = Term(self.solver)
179 term.cterm = self.cdc.getConstructorTerm()
182 def getTesterTerm(self):
183 cdef Term term = Term(self.solver)
184 term.cterm = self.cdc.getTesterTerm()
187 def getNumSelectors(self):
188 return self.cdc.getNumSelectors()
190 def getSelector(self, str name):
191 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
192 ds.cds = self.cdc.getSelector(name.encode())
195 def getSelectorTerm(self, str name):
196 cdef Term term = Term(self.solver)
197 term.cterm = self.cdc.getSelectorTerm(name.encode())
201 return self.cdc.toString().decode()
204 return self.cdc.toString().decode()
208 ds = DatatypeSelector(self.solver)
213 cdef class DatatypeConstructorDecl:
214 cdef c_DatatypeConstructorDecl cddc
217 def __cinit__(self, Solver solver):
220 def addSelector(self, str name, Sort sort):
221 self.cddc.addSelector(name.encode(), sort.csort)
223 def addSelectorSelf(self, str name):
224 self.cddc.addSelectorSelf(name.encode())
227 return self.cddc.toString().decode()
230 return self.cddc.toString().decode()
233 cdef class DatatypeDecl:
234 cdef c_DatatypeDecl cdd
236 def __cinit__(self, Solver solver):
239 def addConstructor(self, DatatypeConstructorDecl ctor):
240 self.cdd.addConstructor(ctor.cddc)
242 def getNumConstructors(self):
243 return self.cdd.getNumConstructors()
245 def isParametric(self):
246 return self.cdd.isParametric()
249 return self.cdd.toString().decode()
252 return self.cdd.toString().decode()
255 cdef class DatatypeSelector:
256 cdef c_DatatypeSelector cds
258 def __cinit__(self, Solver solver):
259 self.cds = c_DatatypeSelector()
263 return self.cds.getName().decode()
265 def getSelectorTerm(self):
266 cdef Term term = Term(self.solver)
267 term.cterm = self.cds.getSelectorTerm()
270 def getRangeSort(self):
271 cdef Sort sort = Sort(self.solver)
272 sort.csort = self.cds.getRangeSort()
276 return self.cds.toString().decode()
279 return self.cds.toString().decode()
285 def __cinit__(self, Solver solver):
289 def __eq__(self, Op other):
290 return self.cop == other.cop
292 def __ne__(self, Op other):
293 return self.cop != other.cop
296 return self.cop.toString().decode()
299 return self.cop.toString().decode()
302 return cophash(self.cop)
305 return kind(<int> self.cop.getKind())
308 return self.cop.isNull()
310 def getIndices(self):
313 indices = self.cop.getIndices[string]()
318 indices = self.cop.getIndices[uint32_t]()
323 indices = self.cop.getIndices[pair[uint32_t, uint32_t]]()
328 raise RuntimeError("Unable to retrieve indices from {}".format(self))
333 cdef c_Grammar cgrammar
335 def __cinit__(self, Solver solver):
337 self.cgrammar = c_Grammar()
339 def addRule(self, Term ntSymbol, Term rule):
340 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
342 def addAnyConstant(self, Term ntSymbol):
343 self.cgrammar.addAnyConstant(ntSymbol.cterm)
345 def addAnyVariable(self, Term ntSymbol):
346 self.cgrammar.addAnyVariable(ntSymbol.cterm)
348 def addRules(self, Term ntSymbol, rules):
349 cdef vector[c_Term] crules
351 crules.push_back((<Term?> r).cterm)
352 self.cgrammar.addRules(ntSymbol.cterm, crules)
357 # gets populated by solver
361 return self.cr.isNull()
364 return self.cr.isSat()
367 return self.cr.isUnsat()
369 def isSatUnknown(self):
370 return self.cr.isSatUnknown()
372 def isEntailed(self):
373 return self.cr.isEntailed()
375 def isNotEntailed(self):
376 return self.cr.isNotEntailed()
378 def isEntailmentUnknown(self):
379 return self.cr.isEntailmentUnknown()
381 def __eq__(self, Result other):
382 return self.cr == other.cr
384 def __ne__(self, Result other):
385 return self.cr != other.cr
387 def getUnknownExplanation(self):
388 return self.cr.getUnknownExplanation().decode()
391 return self.cr.toString().decode()
394 return self.cr.toString().decode()
397 cdef class RoundingMode:
398 cdef c_RoundingMode crm
400 def __cinit__(self, int rm):
401 # crm always assigned externally
402 self.crm = <c_RoundingMode> rm
403 self.name = __rounding_modes[rm]
405 def __eq__(self, RoundingMode other):
406 return (<int> self.crm) == (<int> other.crm)
408 def __ne__(self, RoundingMode other):
409 return not self.__eq__(other)
412 return hash((<int> self.crm, self.name))
422 cdef c_Solver* csolver
425 self.csolver = new c_Solver(NULL)
427 def __dealloc__(self):
430 def supportsFloatingPoint(self):
431 return self.csolver.supportsFloatingPoint()
433 def getBooleanSort(self):
434 cdef Sort sort = Sort(self)
435 sort.csort = self.csolver.getBooleanSort()
438 def getIntegerSort(self):
439 cdef Sort sort = Sort(self)
440 sort.csort = self.csolver.getIntegerSort()
443 def getRealSort(self):
444 cdef Sort sort = Sort(self)
445 sort.csort = self.csolver.getRealSort()
448 def getRegExpSort(self):
449 cdef Sort sort = Sort(self)
450 sort.csort = self.csolver.getRegExpSort()
453 def getRoundingModeSort(self):
454 cdef Sort sort = Sort(self)
455 sort.csort = self.csolver.getRoundingModeSort()
458 def getStringSort(self):
459 cdef Sort sort = Sort(self)
460 sort.csort = self.csolver.getStringSort()
463 def mkArraySort(self, Sort indexSort, Sort elemSort):
464 cdef Sort sort = Sort(self)
465 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
468 def mkBitVectorSort(self, uint32_t size):
469 cdef Sort sort = Sort(self)
470 sort.csort = self.csolver.mkBitVectorSort(size)
473 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
474 cdef Sort sort = Sort(self)
475 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
478 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
479 cdef Sort sort = Sort(self)
480 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
483 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts):
486 cdef vector[c_DatatypeDecl] decls
487 for decl in dtypedecls:
488 decls.push_back((<DatatypeDecl?> decl).cdd)
490 cdef set[c_Sort] usorts
491 for usort in unresolvedSorts:
492 usorts.insert((<Sort?> usort).csort)
494 csorts = self.csolver.mkDatatypeSorts(
495 <const vector[c_DatatypeDecl]&> decls, <const set[c_Sort]&> usorts)
503 def mkFunctionSort(self, sorts, Sort codomain):
505 cdef Sort sort = Sort(self)
506 # populate a vector with dereferenced c_Sorts
507 cdef vector[c_Sort] v
509 if isinstance(sorts, Sort):
510 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
512 elif isinstance(sorts, list):
514 v.push_back((<Sort?>s).csort)
516 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
520 def mkParamSort(self, symbolname):
521 cdef Sort sort = Sort(self)
522 sort.csort = self.csolver.mkParamSort(symbolname.encode())
525 @expand_list_arg(num_req_args=0)
526 def mkPredicateSort(self, *sorts):
528 Supports the following arguments:
529 Sort mkPredicateSort(List[Sort] sorts)
531 where sorts can also be comma-separated arguments of
534 cdef Sort sort = Sort(self)
535 cdef vector[c_Sort] v
537 v.push_back((<Sort?> s).csort)
538 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
541 @expand_list_arg(num_req_args=0)
542 def mkRecordSort(self, *fields):
544 Supports the following arguments:
545 Sort mkRecordSort(List[Tuple[str, Sort]] fields)
547 where fields can also be comma-separated arguments of
548 type Tuple[str, Sort]
550 cdef Sort sort = Sort(self)
551 cdef vector[pair[string, c_Sort]] v
552 cdef pair[string, c_Sort] p
556 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
558 sort.csort = self.csolver.mkRecordSort(
559 <const vector[pair[string, c_Sort]] &> v)
562 def mkSetSort(self, Sort elemSort):
563 cdef Sort sort = Sort(self)
564 sort.csort = self.csolver.mkSetSort(elemSort.csort)
567 def mkBagSort(self, Sort elemSort):
568 cdef Sort sort = Sort(self)
569 sort.csort = self.csolver.mkBagSort(elemSort.csort)
572 def mkSequenceSort(self, Sort elemSort):
573 cdef Sort sort = Sort(self)
574 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
577 def mkUninterpretedSort(self, str name):
578 cdef Sort sort = Sort(self)
579 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
582 def mkSortConstructorSort(self, str symbol, size_t arity):
583 cdef Sort sort = Sort(self)
584 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
587 @expand_list_arg(num_req_args=0)
588 def mkTupleSort(self, *sorts):
590 Supports the following arguments:
591 Sort mkTupleSort(List[Sort] sorts)
593 where sorts can also be comma-separated arguments of
596 cdef Sort sort = Sort(self)
597 cdef vector[c_Sort] v
599 v.push_back((<Sort?> s).csort)
600 sort.csort = self.csolver.mkTupleSort(v)
603 @expand_list_arg(num_req_args=1)
604 def mkTerm(self, kind_or_op, *args):
606 Supports the following arguments:
607 Term mkTerm(Kind kind)
608 Term mkTerm(Kind kind, Op child1, List[Term] children)
609 Term mkTerm(Kind kind, List[Term] children)
611 where List[Term] can also be comma-separated arguments
613 cdef Term term = Term(self)
614 cdef vector[c_Term] v
617 if isinstance(kind_or_op, kind):
618 op = self.mkOp(kind_or_op)
621 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
624 v.push_back((<Term?> a).cterm)
625 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
628 def mkOp(self, kind k, arg0=None, arg1 = None):
630 Supports the following uses:
632 Op mkOp(Kind kind, Kind k)
633 Op mkOp(Kind kind, const string& arg)
634 Op mkOp(Kind kind, uint32_t arg)
635 Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)
637 cdef Op op = Op(self)
640 op.cop = self.csolver.mkOp(k.k)
642 if isinstance(arg0, kind):
643 op.cop = self.csolver.mkOp(k.k, (<kind?> arg0).k)
644 elif isinstance(arg0, str):
645 op.cop = self.csolver.mkOp(k.k,
648 elif isinstance(arg0, int):
649 op.cop = self.csolver.mkOp(k.k, <int?> arg0)
651 raise ValueError("Unsupported signature"
652 " mkOp: {}".format(" X ".join([k, arg0])))
654 if isinstance(arg0, int) and isinstance(arg1, int):
655 op.cop = self.csolver.mkOp(k.k, <int> arg0,
658 raise ValueError("Unsupported signature"
659 " mkOp: {}".format(" X ".join([k, arg0, arg1])))
663 cdef Term term = Term(self)
664 term.cterm = self.csolver.mkTrue()
668 cdef Term term = Term(self)
669 term.cterm = self.csolver.mkFalse()
672 def mkBoolean(self, bint val):
673 cdef Term term = Term(self)
674 term.cterm = self.csolver.mkBoolean(val)
678 cdef Term term = Term(self)
679 term.cterm = self.csolver.mkPi()
682 def mkInteger(self, val):
683 cdef Term term = Term(self)
685 term.cterm = self.csolver.mkInteger("{}".format(integer).encode())
688 def mkReal(self, val, den=None):
689 cdef Term term = Term(self)
691 term.cterm = self.csolver.mkReal(str(val).encode())
693 if not isinstance(val, int) or not isinstance(den, int):
694 raise ValueError("Expecting integers when"
695 " constructing a rational"
696 " but got: {}".format((val, den)))
697 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
700 def mkRegexpEmpty(self):
701 cdef Term term = Term(self)
702 term.cterm = self.csolver.mkRegexpEmpty()
705 def mkRegexpSigma(self):
706 cdef Term term = Term(self)
707 term.cterm = self.csolver.mkRegexpSigma()
710 def mkEmptySet(self, Sort s):
711 cdef Term term = Term(self)
712 term.cterm = self.csolver.mkEmptySet(s.csort)
716 def mkSepNil(self, Sort sort):
717 cdef Term term = Term(self)
718 term.cterm = self.csolver.mkSepNil(sort.csort)
721 def mkString(self, str_or_vec):
722 cdef Term term = Term(self)
723 cdef vector[unsigned] v
724 if isinstance(str_or_vec, str):
726 v.push_back(<unsigned> ord(u))
727 term.cterm = self.csolver.mkString(<const vector[unsigned]&> v)
728 elif isinstance(str_or_vec, list):
730 if not isinstance(u, int):
731 raise ValueError("List should contain ints but got: {}"
733 v.push_back(<unsigned> u)
734 term.cterm = self.csolver.mkString(<const vector[unsigned]&> v)
736 raise ValueError("Expected string or vector of ASCII codes"
737 " but got: {}".format(str_or_vec))
740 def mkEmptySequence(self, Sort sort):
741 cdef Term term = Term(self)
742 term.cterm = self.csolver.mkEmptySequence(sort.csort)
745 def mkUniverseSet(self, Sort sort):
746 cdef Term term = Term(self)
747 term.cterm = self.csolver.mkUniverseSet(sort.csort)
750 def mkBitVector(self, size_or_str, val = None):
751 cdef Term term = Term(self)
752 if isinstance(size_or_str, int):
754 term.cterm = self.csolver.mkBitVector(<uint32_t> size_or_str)
756 term.cterm = self.csolver.mkBitVector(<uint32_t> size_or_str,
757 <const string &> str(val).encode(),
759 elif isinstance(size_or_str, str):
760 # handle default value
762 term.cterm = self.csolver.mkBitVector(
763 <const string &> size_or_str.encode())
765 term.cterm = self.csolver.mkBitVector(
766 <const string &> size_or_str.encode(), <uint32_t> val)
768 raise ValueError("Unexpected inputs {} to"
769 " mkBitVector".format((size_or_str, val)))
772 def mkConstArray(self, Sort sort, Term val):
773 cdef Term term = Term(self)
774 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
777 def mkPosInf(self, int exp, int sig):
778 cdef Term term = Term(self)
779 term.cterm = self.csolver.mkPosInf(exp, sig)
782 def mkNegInf(self, int exp, int sig):
783 cdef Term term = Term(self)
784 term.cterm = self.csolver.mkNegInf(exp, sig)
787 def mkNaN(self, int exp, int sig):
788 cdef Term term = Term(self)
789 term.cterm = self.csolver.mkNaN(exp, sig)
792 def mkPosZero(self, int exp, int sig):
793 cdef Term term = Term(self)
794 term.cterm = self.csolver.mkPosZero(exp, sig)
797 def mkNegZero(self, int exp, int sig):
798 cdef Term term = Term(self)
799 term.cterm = self.csolver.mkNegZero(exp, sig)
802 def mkRoundingMode(self, RoundingMode rm):
803 cdef Term term = Term(self)
804 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
807 def mkUninterpretedConst(self, Sort sort, int index):
808 cdef Term term = Term(self)
809 term.cterm = self.csolver.mkUninterpretedConst(sort.csort, index)
812 def mkAbstractValue(self, index):
813 cdef Term term = Term(self)
815 term.cterm = self.csolver.mkAbstractValue(str(index).encode())
817 raise ValueError("mkAbstractValue expects a str representing a number"
818 " or an int, but got{}".format(index))
821 def mkFloatingPoint(self, int exp, int sig, Term val):
822 cdef Term term = Term(self)
823 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
826 def mkConst(self, Sort sort, symbol=None):
827 cdef Term term = Term(self)
829 term.cterm = self.csolver.mkConst(sort.csort)
831 term.cterm = self.csolver.mkConst(sort.csort,
832 (<str?> symbol).encode())
835 def mkVar(self, Sort sort, symbol=None):
836 cdef Term term = Term(self)
838 term.cterm = self.csolver.mkVar(sort.csort)
840 term.cterm = self.csolver.mkVar(sort.csort,
841 (<str?> symbol).encode())
844 def mkDatatypeConstructorDecl(self, str name):
845 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
846 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
849 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
850 cdef DatatypeDecl dd = DatatypeDecl(self)
851 cdef vector[c_Sort] v
854 if sorts_or_bool is None and isCoDatatype is None:
855 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
856 elif sorts_or_bool is not None and isCoDatatype is None:
857 if isinstance(sorts_or_bool, bool):
858 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
859 <bint> sorts_or_bool)
860 elif isinstance(sorts_or_bool, Sort):
861 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
862 (<Sort> sorts_or_bool).csort)
863 elif isinstance(sorts_or_bool, list):
864 for s in sorts_or_bool:
865 v.push_back((<Sort?> s).csort)
866 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
867 <const vector[c_Sort]&> v)
869 raise ValueError("Unhandled second argument type {}"
870 .format(type(sorts_or_bool)))
871 elif sorts_or_bool is not None and isCoDatatype is not None:
872 if isinstance(sorts_or_bool, Sort):
873 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
874 (<Sort> sorts_or_bool).csort,
876 elif isinstance(sorts_or_bool, list):
877 for s in sorts_or_bool:
878 v.push_back((<Sort?> s).csort)
879 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
880 <const vector[c_Sort]&> v,
883 raise ValueError("Unhandled second argument type {}"
884 .format(type(sorts_or_bool)))
886 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
893 def simplify(self, Term t):
894 cdef Term term = Term(self)
895 term.cterm = self.csolver.simplify(t.cterm)
898 def assertFormula(self, Term term):
899 self.csolver.assertFormula(term.cterm)
902 cdef Result r = Result()
903 r.cr = self.csolver.checkSat()
906 def mkSygusGrammar(self, boundVars, ntSymbols):
907 cdef Grammar grammar = Grammar(self)
908 cdef vector[c_Term] bvc
909 cdef vector[c_Term] ntc
911 bvc.push_back((<Term?> bv).cterm)
913 ntc.push_back((<Term?> nt).cterm)
914 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
917 def mkSygusVar(self, Sort sort, str symbol=""):
918 cdef Term term = Term(self)
919 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
922 def addSygusConstraint(self, Term t):
923 self.csolver.addSygusConstraint(t.cterm)
925 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
926 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
928 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
929 cdef Term term = Term(self)
930 cdef vector[c_Term] v
931 for bv in bound_vars:
932 v.push_back((<Term?> bv).cterm)
934 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
936 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
939 def checkSynth(self):
940 cdef Result r = Result()
941 r.cr = self.csolver.checkSynth()
944 def getSynthSolution(self, Term term):
945 cdef Term t = Term(self)
946 t.cterm = self.csolver.getSynthSolution(term.cterm)
949 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
950 cdef Term term = Term(self)
951 cdef vector[c_Term] v
952 for bv in bound_vars:
953 v.push_back((<Term?> bv).cterm)
955 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
957 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
960 def printSynthSolution(self):
961 self.csolver.printSynthSolution(cout)
963 @expand_list_arg(num_req_args=0)
964 def checkSatAssuming(self, *assumptions):
966 Supports the following arguments:
967 Result checkSatAssuming(List[Term] assumptions)
969 where assumptions can also be comma-separated arguments of
972 cdef Result r = Result()
973 # used if assumptions is a list of terms
974 cdef vector[c_Term] v
975 for a in assumptions:
976 v.push_back((<Term?> a).cterm)
977 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
980 @expand_list_arg(num_req_args=0)
981 def checkEntailed(self, *assumptions):
983 Supports the following arguments:
984 Result checkEntailed(List[Term] assumptions)
986 where assumptions can also be comma-separated arguments of
989 cdef Result r = Result()
990 # used if assumptions is a list of terms
991 cdef vector[c_Term] v
992 for a in assumptions:
993 v.push_back((<Term?> a).cterm)
994 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
997 @expand_list_arg(num_req_args=1)
998 def declareDatatype(self, str symbol, *ctors):
1000 Supports the following arguments:
1001 Sort declareDatatype(str symbol, List[Term] ctors)
1003 where ctors can also be comma-separated arguments of
1004 type DatatypeConstructorDecl
1006 cdef Sort sort = Sort(self)
1007 cdef vector[c_DatatypeConstructorDecl] v
1010 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1011 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1014 def declareFun(self, str symbol, list sorts, Sort sort):
1015 cdef Term term = Term(self)
1016 cdef vector[c_Sort] v
1018 v.push_back((<Sort?> s).csort)
1019 term.cterm = self.csolver.declareFun(symbol.encode(),
1020 <const vector[c_Sort]&> v,
1024 def declareSort(self, str symbol, int arity):
1025 cdef Sort sort = Sort(self)
1026 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1029 def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1032 Term defineFun(str symbol, List[Term] bound_vars,
1033 Sort sort, Term term, bool glbl)
1034 Term defineFun(Term fun, List[Term] bound_vars,
1035 Term term, bool glbl)
1037 cdef Term term = Term(self)
1038 cdef vector[c_Term] v
1039 for bv in bound_vars:
1040 v.push_back((<Term?> bv).cterm)
1043 term.cterm = self.csolver.defineFun((<str?> sym_or_fun).encode(),
1044 <const vector[c_Term] &> v,
1045 (<Sort?> sort_or_term).csort,
1049 term.cterm = self.csolver.defineFun((<Term?> sym_or_fun).cterm,
1050 <const vector[c_Term]&> v,
1051 (<Term?> sort_or_term).cterm,
1056 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1059 Term defineFunRec(str symbol, List[Term] bound_vars,
1060 Sort sort, Term term, bool glbl)
1061 Term defineFunRec(Term fun, List[Term] bound_vars,
1062 Term term, bool glbl)
1064 cdef Term term = Term(self)
1065 cdef vector[c_Term] v
1066 for bv in bound_vars:
1067 v.push_back((<Term?> bv).cterm)
1070 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1071 <const vector[c_Term] &> v,
1072 (<Sort?> sort_or_term).csort,
1076 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1077 <const vector[c_Term]&> v,
1078 (<Term?> sort_or_term).cterm,
1083 def defineFunsRec(self, funs, bound_vars, terms):
1084 cdef vector[c_Term] vf
1085 cdef vector[vector[c_Term]] vbv
1086 cdef vector[c_Term] vt
1089 vf.push_back((<Term?> f).cterm)
1091 cdef vector[c_Term] temp
1092 for v in bound_vars:
1094 temp.push_back((<Term?> t).cterm)
1099 vf.push_back((<Term?> t).cterm)
1101 def getAssertions(self):
1103 for a in self.csolver.getAssertions():
1106 assertions.append(term)
1109 def getInfo(self, str flag):
1110 return self.csolver.getInfo(flag.encode())
1112 def getOption(self, str option):
1113 return self.csolver.getOption(option.encode())
1115 def getUnsatAssumptions(self):
1117 for a in self.csolver.getUnsatAssumptions():
1120 assumptions.append(term)
1123 def getUnsatCore(self):
1125 for a in self.csolver.getUnsatCore():
1131 def getValue(self, Term t):
1132 cdef Term term = Term(self)
1133 term.cterm = self.csolver.getValue(t.cterm)
1136 def getSeparationHeap(self):
1137 cdef Term term = Term(self)
1138 term.cterm = self.csolver.getSeparationHeap()
1141 def declareSeparationHeap(self, Sort locType, Sort dataType):
1142 self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
1144 def getSeparationNilTerm(self):
1145 cdef Term term = Term(self)
1146 term.cterm = self.csolver.getSeparationNilTerm()
1149 def declarePool(self, str symbol, Sort sort, initValue):
1150 cdef Term term = Term(self)
1151 cdef vector[c_Term] niv
1153 niv.push_back((<Term?> v).cterm)
1154 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
1157 def pop(self, nscopes=1):
1158 self.csolver.pop(nscopes)
1160 def push(self, nscopes=1):
1161 self.csolver.push(nscopes)
1163 def resetAssertions(self):
1164 self.csolver.resetAssertions()
1166 def setInfo(self, str keyword, str value):
1167 self.csolver.setInfo(keyword.encode(), value.encode())
1169 def setLogic(self, str logic):
1170 self.csolver.setLogic(logic.encode())
1172 def setOption(self, str option, str value):
1173 self.csolver.setOption(option.encode(), value.encode())
1179 def __cinit__(self, Solver solver):
1180 # csort always set by Solver
1181 self.solver = solver
1183 def __eq__(self, Sort other):
1184 return self.csort == other.csort
1186 def __ne__(self, Sort other):
1187 return self.csort != other.csort
1189 def __lt__(self, Sort other):
1190 return self.csort < other.csort
1192 def __gt__(self, Sort other):
1193 return self.csort > other.csort
1195 def __le__(self, Sort other):
1196 return self.csort <= other.csort
1198 def __ge__(self, Sort other):
1199 return self.csort >= other.csort
1202 return self.csort.toString().decode()
1205 return self.csort.toString().decode()
1208 return csorthash(self.csort)
1210 def isBoolean(self):
1211 return self.csort.isBoolean()
1213 def isInteger(self):
1214 return self.csort.isInteger()
1217 return self.csort.isReal()
1220 return self.csort.isString()
1223 return self.csort.isRegExp()
1225 def isRoundingMode(self):
1226 return self.csort.isRoundingMode()
1228 def isBitVector(self):
1229 return self.csort.isBitVector()
1231 def isFloatingPoint(self):
1232 return self.csort.isFloatingPoint()
1234 def isDatatype(self):
1235 return self.csort.isDatatype()
1237 def isParametricDatatype(self):
1238 return self.csort.isParametricDatatype()
1240 def isConstructor(self):
1241 return self.csort.isConstructor()
1243 def isSelector(self):
1244 return self.csort.isSelector()
1247 return self.csort.isTester()
1249 def isFunction(self):
1250 return self.csort.isFunction()
1252 def isPredicate(self):
1253 return self.csort.isPredicate()
1256 return self.csort.isTuple()
1259 return self.csort.isRecord()
1262 return self.csort.isArray()
1265 return self.csort.isSet()
1268 return self.csort.isBag()
1270 def isSequence(self):
1271 return self.csort.isSequence()
1273 def isUninterpretedSort(self):
1274 return self.csort.isUninterpretedSort()
1276 def isSortConstructor(self):
1277 return self.csort.isSortConstructor()
1279 def isFirstClass(self):
1280 return self.csort.isFirstClass()
1282 def isFunctionLike(self):
1283 return self.csort.isFunctionLike()
1285 def isSubsortOf(self, Sort sort):
1286 return self.csort.isSubsortOf(sort.csort)
1288 def isComparableTo(self, Sort sort):
1289 return self.csort.isComparableTo(sort.csort)
1291 def getDatatype(self):
1292 cdef Datatype d = Datatype(self.solver)
1293 d.cd = self.csort.getDatatype()
1296 def instantiate(self, params):
1297 cdef Sort sort = Sort(self.solver)
1298 cdef vector[c_Sort] v
1300 v.push_back((<Sort?> s).csort)
1301 sort.csort = self.csort.instantiate(v)
1304 def getConstructorArity(self):
1305 return self.csort.getConstructorArity()
1307 def getConstructorDomainSorts(self):
1309 for s in self.csort.getConstructorDomainSorts():
1310 sort = Sort(self.solver)
1312 domain_sorts.append(sort)
1315 def getConstructorCodomainSort(self):
1316 cdef Sort sort = Sort(self.solver)
1317 sort.csort = self.csort.getConstructorCodomainSort()
1320 def getSelectorDomainSort(self):
1321 cdef Sort sort = Sort(self.solver)
1322 sort.csort = self.csort.getSelectorDomainSort()
1325 def getSelectorCodomainSort(self):
1326 cdef Sort sort = Sort(self.solver)
1327 sort.csort = self.csort.getSelectorCodomainSort()
1330 def getTesterDomainSort(self):
1331 cdef Sort sort = Sort(self.solver)
1332 sort.csort = self.csort.getTesterDomainSort()
1335 def getTesterCodomainSort(self):
1336 cdef Sort sort = Sort(self.solver)
1337 sort.csort = self.csort.getTesterCodomainSort()
1340 def getFunctionArity(self):
1341 return self.csort.getFunctionArity()
1343 def getFunctionDomainSorts(self):
1345 for s in self.csort.getFunctionDomainSorts():
1346 sort = Sort(self.solver)
1348 domain_sorts.append(sort)
1351 def getFunctionCodomainSort(self):
1352 cdef Sort sort = Sort(self.solver)
1353 sort.csort = self.csort.getFunctionCodomainSort()
1356 def getArrayIndexSort(self):
1357 cdef Sort sort = Sort(self.solver)
1358 sort.csort = self.csort.getArrayIndexSort()
1361 def getArrayElementSort(self):
1362 cdef Sort sort = Sort(self.solver)
1363 sort.csort = self.csort.getArrayElementSort()
1366 def getSetElementSort(self):
1367 cdef Sort sort = Sort(self.solver)
1368 sort.csort = self.csort.getSetElementSort()
1371 def getBagElementSort(self):
1372 cdef Sort sort = Sort(self.solver)
1373 sort.csort = self.csort.getBagElementSort()
1376 def getSequenceElementSort(self):
1377 cdef Sort sort = Sort(self.solver)
1378 sort.csort = self.csort.getSequenceElementSort()
1381 def getUninterpretedSortName(self):
1382 return self.csort.getUninterpretedSortName().decode()
1384 def isUninterpretedSortParameterized(self):
1385 return self.csort.isUninterpretedSortParameterized()
1387 def getUninterpretedSortParamSorts(self):
1389 for s in self.csort.getUninterpretedSortParamSorts():
1390 sort = Sort(self.solver)
1392 param_sorts.append(sort)
1395 def getSortConstructorName(self):
1396 return self.csort.getSortConstructorName().decode()
1398 def getSortConstructorArity(self):
1399 return self.csort.getSortConstructorArity()
1401 def getBVSize(self):
1402 return self.csort.getBVSize()
1404 def getFPExponentSize(self):
1405 return self.csort.getFPExponentSize()
1407 def getFPSignificandSize(self):
1408 return self.csort.getFPSignificandSize()
1410 def getDatatypeParamSorts(self):
1412 for s in self.csort.getDatatypeParamSorts():
1413 sort = Sort(self.solver)
1415 param_sorts.append(sort)
1418 def getDatatypeArity(self):
1419 return self.csort.getDatatypeArity()
1421 def getTupleLength(self):
1422 return self.csort.getTupleLength()
1424 def getTupleSorts(self):
1426 for s in self.csort.getTupleSorts():
1427 sort = Sort(self.solver)
1429 tuple_sorts.append(sort)
1436 def __cinit__(self, Solver solver):
1437 # cterm always set in the Solver object
1438 self.solver = solver
1440 def __eq__(self, Term other):
1441 return self.cterm == other.cterm
1443 def __ne__(self, Term other):
1444 return self.cterm != other.cterm
1446 def __getitem__(self, int index):
1447 cdef Term term = Term(self.solver)
1449 term.cterm = self.cterm[index]
1451 raise ValueError("Expecting a non-negative integer or string")
1455 return self.cterm.toString().decode()
1458 return self.cterm.toString().decode()
1461 for ci in self.cterm:
1462 term = Term(self.solver)
1467 return ctermhash(self.cterm)
1470 return kind(<int> self.cterm.getKind())
1473 cdef Sort sort = Sort(self.solver)
1474 sort.csort = self.cterm.getSort()
1477 def substitute(self, list es, list replacements):
1478 cdef vector[c_Term] ces
1479 cdef vector[c_Term] creplacements
1480 cdef Term term = Term(self.solver)
1482 if len(es) != len(replacements):
1483 raise RuntimeError("Expecting list inputs to substitute to "
1484 "have the same length but got: "
1485 "{} and {}".format(len(es), len(replacements)))
1487 for e, r in zip(es, replacements):
1488 ces.push_back((<Term?> e).cterm)
1489 creplacements.push_back((<Term?> r).cterm)
1491 term.cterm = self.cterm.substitute(ces, creplacements)
1495 return self.cterm.hasOp()
1498 cdef Op op = Op(self.solver)
1499 op.cop = self.cterm.getOp()
1503 return self.cterm.isNull()
1505 def getConstArrayBase(self):
1506 cdef Term term = Term(self.solver)
1507 term.cterm = self.cterm.getConstArrayBase()
1510 def getConstSequenceElements(self):
1512 for e in self.cterm.getConstSequenceElements():
1513 term = Term(self.solver)
1519 cdef Term term = Term(self.solver)
1520 term.cterm = self.cterm.notTerm()
1523 def andTerm(self, Term t):
1524 cdef Term term = Term(self.solver)
1525 term.cterm = self.cterm.andTerm((<Term> t).cterm)
1528 def orTerm(self, Term t):
1529 cdef Term term = Term(self.solver)
1530 term.cterm = self.cterm.orTerm(t.cterm)
1533 def xorTerm(self, Term t):
1534 cdef Term term = Term(self.solver)
1535 term.cterm = self.cterm.xorTerm(t.cterm)
1538 def eqTerm(self, Term t):
1539 cdef Term term = Term(self.solver)
1540 term.cterm = self.cterm.eqTerm(t.cterm)
1543 def impTerm(self, Term t):
1544 cdef Term term = Term(self.solver)
1545 term.cterm = self.cterm.impTerm(t.cterm)
1548 def iteTerm(self, Term then_t, Term else_t):
1549 cdef Term term = Term(self.solver)
1550 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
1553 def toPythonObj(self):
1555 Converts a constant value Term to a Python object.
1558 Boolean -- returns a Python bool
1559 Int -- returns a Python int
1560 Real -- returns a Python Fraction
1561 BV -- returns a Python int (treats BV as unsigned)
1562 Array -- returns a Python dict mapping indices to values
1563 -- the constant base is returned as the default value
1564 String -- returns a Python Unicode string
1567 string_repr = self.cterm.toString().decode()
1569 sort = self.getSort()
1571 if sort.isBoolean():
1572 if string_repr == "true":
1575 assert string_repr == "false"
1577 elif sort.isInteger():
1578 updated_string_repr = string_repr.strip('()').replace(' ', '')
1580 res = int(updated_string_repr)
1582 raise ValueError("Failed to convert"
1583 " {} to an int".format(string_repr))
1585 updated_string_repr = string_repr
1587 # expecting format (/ a b)
1588 # note: a or b could be negated: (- a)
1589 splits = [s.strip('()/')
1590 for s in updated_string_repr.strip('()/') \
1591 .replace('(- ', '(-').split()]
1592 assert len(splits) == 2
1593 num = int(splits[0])
1594 den = int(splits[1])
1595 res = Fraction(num, den)
1597 raise ValueError("Failed to convert "
1598 "{} to a Fraction".format(string_repr))
1600 elif sort.isBitVector():
1601 # expecting format #b<bits>
1602 assert string_repr[:2] == "#b"
1603 python_bin_repr = "0" + string_repr[1:]
1605 res = int(python_bin_repr, 2)
1607 raise ValueError("Failed to convert bitvector "
1608 "{} to an int".format(string_repr))
1609 elif sort.isArray():
1614 # Array models are represented as a series of store operations
1615 # on a constant array
1618 if t.getKind() == kinds.Store:
1620 keys.append(t[1].toPythonObj())
1621 values.append(t[2].toPythonObj())
1622 to_visit.append(t[0])
1624 assert t.getKind() == kinds.ConstArray
1625 base_value = t.getConstArrayBase().toPythonObj()
1627 assert len(keys) == len(values)
1628 assert base_value is not None
1630 # put everything in a dictionary with the constant
1631 # base as the result for any index not included in the stores
1632 res = defaultdict(lambda : base_value)
1633 for k, v in zip(keys, values):
1635 elif sort.isString():
1636 # Strip leading and trailing double quotes and replace double
1637 # double quotes by single quotes
1638 string_repr = string_repr[1:-1].replace('""', '"')
1640 # Convert escape sequences
1642 escape_prefix = '\\u{'
1646 i = string_repr.find(escape_prefix, i)
1648 res += string_repr[prev_i:]
1651 res += string_repr[prev_i:i]
1652 val = string_repr[i + len(escape_prefix):string_repr.find('}', i)]
1653 res += chr(int(val, 16))
1654 i += len(escape_prefix) + len(val) + 1
1656 raise ValueError("Cannot convert term {}"
1657 " of sort {} to Python object".format(string_repr,
1660 assert res is not None
1664 # Generate rounding modes
1665 cdef __rounding_modes = {
1666 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
1667 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
1668 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
1669 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
1670 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
1673 mod_ref = sys.modules[__name__]
1674 for rm_int, name in __rounding_modes.items():
1675 r = RoundingMode(rm_int)
1677 if name in dir(mod_ref):
1678 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
1680 setattr(mod_ref, name, r)