1 from collections import defaultdict, Set
2 from fractions import Fraction
3 from functools import wraps
6 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
7 from libc.stddef cimport wchar_t
9 from libcpp.pair cimport pair
10 from libcpp.set cimport set as c_set
11 from libcpp.string cimport string
12 from libcpp.vector cimport vector
14 from cvc5 cimport cout
15 from cvc5 cimport Datatype as c_Datatype
16 from cvc5 cimport DatatypeConstructor as c_DatatypeConstructor
17 from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
18 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
19 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
20 from cvc5 cimport Result as c_Result
21 from cvc5 cimport RoundingMode as c_RoundingMode
22 from cvc5 cimport UnknownExplanation as c_UnknownExplanation
23 from cvc5 cimport Op as c_Op
24 from cvc5 cimport Solver as c_Solver
25 from cvc5 cimport Grammar as c_Grammar
26 from cvc5 cimport Sort as c_Sort
27 from cvc5 cimport ROUND_NEAREST_TIES_TO_EVEN, ROUND_TOWARD_POSITIVE
28 from cvc5 cimport ROUND_TOWARD_NEGATIVE, ROUND_TOWARD_ZERO
29 from cvc5 cimport ROUND_NEAREST_TIES_TO_AWAY
30 from cvc5 cimport REQUIRES_FULL_CHECK, INCOMPLETE, TIMEOUT
31 from cvc5 cimport RESOURCEOUT, MEMOUT, INTERRUPTED
32 from cvc5 cimport NO_STATUS, UNSUPPORTED, UNKNOWN_REASON
33 from cvc5 cimport OTHER
34 from cvc5 cimport Term as c_Term
35 from cvc5 cimport hash as c_hash
36 from cvc5 cimport wstring as c_wstring
37 from cvc5 cimport tuple as c_tuple
38 from cvc5 cimport get0, get1, get2
39 from cvc5kinds cimport Kind as c_Kind
41 cdef extern from "Python.h":
42 wchar_t* PyUnicode_AsWideCharString(object, Py_ssize_t *)
43 object PyUnicode_FromWideChar(const wchar_t*, Py_ssize_t)
44 void PyMem_Free(void*)
46 ################################## DECORATORS #################################
47 def expand_list_arg(num_req_args=0):
49 Creates a decorator that looks at index num_req_args of the args,
50 if it's a list, it expands it before calling the function.
54 def wrapper(owner, *args):
55 if len(args) == num_req_args + 1 and \
56 isinstance(args[num_req_args], list):
57 args = list(args[:num_req_args]) + args[num_req_args]
58 return func(owner, *args)
61 ###############################################################################
64 ### Using PEP-8 spacing recommendations
65 ### Limit linewidth to 79 characters
66 ### Break before binary operators
67 ### surround top level functions and classes with two spaces
68 ### separate methods by one space
69 ### use spaces in functions sparingly to separate logical blocks
70 ### can omit spaces between unrelated oneliners
71 ### always use c++ default arguments
72 #### only use default args of None at python level
74 # References and pointers
75 # The Solver object holds a pointer to a c_Solver.
76 # This is because the assignment operator is deleted in the C++ API for solvers.
77 # Cython has a limitation where you can't stack allocate objects
78 # that have constructors with arguments:
79 # https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs.
80 # To get around that you can either have a nullary constructor and assignment
81 # or, use a pointer (which is what we chose).
82 # An additional complication of this is that to free up resources, you must
83 # know when to delete the object.
84 # Python will not follow the same scoping rules as in C++, so it must be
85 # able to reference count. To do this correctly, the solver must be a
86 # reference in the Python class for any class that keeps a pointer to
87 # the solver in C++ (to ensure the solver is not deleted before something
88 # that depends on it).
91 ## Objects for hashing
92 cdef c_hash[c_Op] cophash = c_hash[c_Op]()
93 cdef c_hash[c_Sort] csorthash = c_hash[c_Sort]()
94 cdef c_hash[c_Term] ctermhash = c_hash[c_Term]()
98 """Wrapper class for :cpp:class:`cvc5::api::Datatype`."""
101 def __cinit__(self, Solver solver):
104 def __getitem__(self, index):
105 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
106 if isinstance(index, int) and index >= 0:
107 dc.cdc = self.cd[(<int?> index)]
108 elif isinstance(index, str):
109 dc.cdc = self.cd[(<const string &> index.encode())]
111 raise ValueError("Expecting a non-negative integer or string")
114 def getConstructor(self, str name):
116 :param name: the name of the constructor.
117 :return: a constructor by name.
119 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
120 dc.cdc = self.cd.getConstructor(name.encode())
123 def getConstructorTerm(self, str name):
125 :param name: the name of the constructor.
126 :return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::api::Datatype::getConstructorTerm>`).
128 cdef Term term = Term(self.solver)
129 term.cterm = self.cd.getConstructorTerm(name.encode())
132 def getSelector(self, str name):
134 :param name: the name of the selector..
135 :return: a selector by name.
137 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
138 ds.cds = self.cd.getSelector(name.encode())
143 :return: the name of the datatype.
145 return self.cd.getName().decode()
147 def getNumConstructors(self):
149 :return: number of constructors in this datatype.
151 return self.cd.getNumConstructors()
153 def isParametric(self):
154 """:return: whether this datatype is parametric."""
155 return self.cd.isParametric()
157 def isCodatatype(self):
158 """:return: whether this datatype corresponds to a co-datatype."""
159 return self.cd.isCodatatype()
162 """:return: whether this datatype corresponds to a tuple."""
163 return self.cd.isTuple()
166 """:return: whether this datatype corresponds to a record."""
167 return self.cd.isRecord()
170 """:return: whether this datatype is finite."""
171 return self.cd.isFinite()
173 def isWellFounded(self):
174 """:return: whether this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::api::Datatype::isWellFounded>`)."""
175 return self.cd.isWellFounded()
177 def hasNestedRecursion(self):
178 """:return: whether this datatype has nested recursion (see :cpp:func:`Datatype::hasNestedRecursion() <cvc5::api::Datatype::hasNestedRecursion>`)."""
179 return self.cd.hasNestedRecursion()
182 return self.cd.isNull()
185 return self.cd.toString().decode()
188 return self.cd.toString().decode()
192 dc = DatatypeConstructor(self.solver)
197 cdef class DatatypeConstructor:
198 """Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructor`."""
199 cdef c_DatatypeConstructor cdc
201 def __cinit__(self, Solver solver):
202 self.cdc = c_DatatypeConstructor()
205 def __getitem__(self, index):
206 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
207 if isinstance(index, int) and index >= 0:
208 ds.cds = self.cdc[(<int?> index)]
209 elif isinstance(index, str):
210 ds.cds = self.cdc[(<const string &> index.encode())]
212 raise ValueError("Expecting a non-negative integer or string")
217 :return: the name of the constructor.
219 return self.cdc.getName().decode()
221 def getConstructorTerm(self):
223 :return: the constructor operator as a term.
225 cdef Term term = Term(self.solver)
226 term.cterm = self.cdc.getConstructorTerm()
229 def getSpecializedConstructorTerm(self, Sort retSort):
231 Specialized method for parametric datatypes (see :cpp:func:`DatatypeConstructor::getSpecializedConstructorTerm() <cvc5::api::DatatypeConstructor::getSpecializedConstructorTerm>`).
233 :param retSort: the desired return sort of the constructor
234 :return: the constructor operator as a term.
236 cdef Term term = Term(self.solver)
237 term.cterm = self.cdc.getSpecializedConstructorTerm(retSort.csort)
240 def getTesterTerm(self):
242 :return: the tester operator that is related to this constructor, as a term.
244 cdef Term term = Term(self.solver)
245 term.cterm = self.cdc.getTesterTerm()
248 def getNumSelectors(self):
250 :return: the number of selecters (so far) of this Datatype constructor.
252 return self.cdc.getNumSelectors()
254 def getSelector(self, str name):
256 :param name: the name of the datatype selector.
257 :return: the first datatype selector with the given name
259 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
260 ds.cds = self.cdc.getSelector(name.encode())
263 def getSelectorTerm(self, str name):
265 :param name: the name of the datatype selector.
266 :return: a term representing the firstdatatype selector with the given name.
268 cdef Term term = Term(self.solver)
269 term.cterm = self.cdc.getSelectorTerm(name.encode())
273 return self.cdc.isNull()
276 return self.cdc.toString().decode()
279 return self.cdc.toString().decode()
283 ds = DatatypeSelector(self.solver)
288 cdef class DatatypeConstructorDecl:
289 """Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructorDecl`."""
290 cdef c_DatatypeConstructorDecl cddc
293 def __cinit__(self, Solver solver):
296 def addSelector(self, str name, Sort sort):
298 Add datatype selector declaration.
300 :param name: the name of the datatype selector declaration to add.
301 :param sort: the range sort of the datatype selector declaration to add.
303 self.cddc.addSelector(name.encode(), sort.csort)
305 def addSelectorSelf(self, str name):
307 Add datatype selector declaration whose range sort is the datatype itself.
309 :param name: the name of the datatype selector declaration to add.
311 self.cddc.addSelectorSelf(name.encode())
314 return self.cddc.isNull()
317 return self.cddc.toString().decode()
320 return self.cddc.toString().decode()
323 cdef class DatatypeDecl:
324 """Wrapper class for :cpp:class:`cvc5::api::DatatypeDecl`."""
325 cdef c_DatatypeDecl cdd
327 def __cinit__(self, Solver solver):
330 def addConstructor(self, DatatypeConstructorDecl ctor):
332 Add a datatype constructor declaration.
334 :param ctor: the datatype constructor declaration to add.
336 self.cdd.addConstructor(ctor.cddc)
338 def getNumConstructors(self):
340 :return: number of constructors (so far) for this datatype declaration.
342 return self.cdd.getNumConstructors()
344 def isParametric(self):
346 :return: is this datatype declaration parametric?
348 return self.cdd.isParametric()
352 :return: the name of this datatype declaration.
354 return self.cdd.getName().decode()
357 return self.cdd.isNull()
360 return self.cdd.toString().decode()
363 return self.cdd.toString().decode()
366 cdef class DatatypeSelector:
367 """Wrapper class for :cpp:class:`cvc5::api::DatatypeSelector`."""
368 cdef c_DatatypeSelector cds
370 def __cinit__(self, Solver solver):
371 self.cds = c_DatatypeSelector()
376 :return: the name of this datatype selector.
378 return self.cds.getName().decode()
380 def getSelectorTerm(self):
382 :return: the selector opeartor of this datatype selector as a term.
384 cdef Term term = Term(self.solver)
385 term.cterm = self.cds.getSelectorTerm()
388 def getUpdaterTerm(self):
390 :return: the updater opeartor of this datatype selector as a term.
392 cdef Term term = Term(self.solver)
393 term.cterm = self.cds.getUpdaterTerm()
396 def getRangeSort(self):
398 :return: the range sort of this selector.
400 cdef Sort sort = Sort(self.solver)
401 sort.csort = self.cds.getRangeSort()
405 return self.cds.isNull()
408 return self.cds.toString().decode()
411 return self.cds.toString().decode()
417 def __cinit__(self, Solver solver):
421 def __eq__(self, Op other):
422 return self.cop == other.cop
424 def __ne__(self, Op other):
425 return self.cop != other.cop
428 return self.cop.toString().decode()
431 return self.cop.toString().decode()
434 return cophash(self.cop)
437 return kind(<int> self.cop.getKind())
440 return self.cop.isIndexed()
443 return self.cop.isNull()
445 def getNumIndices(self):
446 return self.cop.getNumIndices()
448 def getIndices(self):
451 indices = self.cop.getIndices[string]().decode()
456 indices = self.cop.getIndices[uint32_t]()
461 indices = self.cop.getIndices[pair[uint32_t, uint32_t]]()
466 raise RuntimeError("Unable to retrieve indices from {}".format(self))
471 cdef c_Grammar cgrammar
473 def __cinit__(self, Solver solver):
475 self.cgrammar = c_Grammar()
477 def addRule(self, Term ntSymbol, Term rule):
478 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
480 def addAnyConstant(self, Term ntSymbol):
481 self.cgrammar.addAnyConstant(ntSymbol.cterm)
483 def addAnyVariable(self, Term ntSymbol):
484 self.cgrammar.addAnyVariable(ntSymbol.cterm)
486 def addRules(self, Term ntSymbol, rules):
487 cdef vector[c_Term] crules
489 crules.push_back((<Term?> r).cterm)
490 self.cgrammar.addRules(ntSymbol.cterm, crules)
495 # gets populated by solver
499 return self.cr.isNull()
502 return self.cr.isSat()
505 return self.cr.isUnsat()
507 def isSatUnknown(self):
508 return self.cr.isSatUnknown()
510 def isEntailed(self):
511 return self.cr.isEntailed()
513 def isNotEntailed(self):
514 return self.cr.isNotEntailed()
516 def isEntailmentUnknown(self):
517 return self.cr.isEntailmentUnknown()
519 def __eq__(self, Result other):
520 return self.cr == other.cr
522 def __ne__(self, Result other):
523 return self.cr != other.cr
525 def getUnknownExplanation(self):
526 return UnknownExplanation(<int> self.cr.getUnknownExplanation())
529 return self.cr.toString().decode()
532 return self.cr.toString().decode()
535 cdef class RoundingMode:
536 cdef c_RoundingMode crm
538 def __cinit__(self, int rm):
539 # crm always assigned externally
540 self.crm = <c_RoundingMode> rm
541 self.name = __rounding_modes[rm]
543 def __eq__(self, RoundingMode other):
544 return (<int> self.crm) == (<int> other.crm)
546 def __ne__(self, RoundingMode other):
547 return not self.__eq__(other)
550 return hash((<int> self.crm, self.name))
559 cdef class UnknownExplanation:
560 cdef c_UnknownExplanation cue
562 def __cinit__(self, int ue):
563 # crm always assigned externally
564 self.cue = <c_UnknownExplanation> ue
565 self.name = __unknown_explanations[ue]
567 def __eq__(self, UnknownExplanation other):
568 return (<int> self.cue) == (<int> other.cue)
570 def __ne__(self, UnknownExplanation other):
571 return not self.__eq__(other)
574 return hash((<int> self.crm, self.name))
584 """Wrapper class for :cpp:class:`cvc5::api::Solver`."""
585 cdef c_Solver* csolver
588 self.csolver = new c_Solver()
590 def __dealloc__(self):
593 def getBooleanSort(self):
594 """:return: sort Boolean
596 cdef Sort sort = Sort(self)
597 sort.csort = self.csolver.getBooleanSort()
600 def getIntegerSort(self):
601 """:return: sort Integer
603 cdef Sort sort = Sort(self)
604 sort.csort = self.csolver.getIntegerSort()
607 def getNullSort(self):
608 """:return: sort null
610 cdef Sort sort = Sort(self)
611 sort.csort = self.csolver.getNullSort()
614 def getRealSort(self):
615 """:return: sort Real
617 cdef Sort sort = Sort(self)
618 sort.csort = self.csolver.getRealSort()
621 def getRegExpSort(self):
622 """:return: sort of RegExp
624 cdef Sort sort = Sort(self)
625 sort.csort = self.csolver.getRegExpSort()
628 def getRoundingModeSort(self):
629 """:return: sort RoundingMode
631 cdef Sort sort = Sort(self)
632 sort.csort = self.csolver.getRoundingModeSort()
635 def getStringSort(self):
636 """:return: sort String
638 cdef Sort sort = Sort(self)
639 sort.csort = self.csolver.getStringSort()
642 def mkArraySort(self, Sort indexSort, Sort elemSort):
643 """Create an array sort.
645 :param indexSort: the array index sort
646 :param elemSort: the array element sort
647 :return: the array sort
649 cdef Sort sort = Sort(self)
650 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
653 def mkBitVectorSort(self, uint32_t size):
654 """Create a bit-vector sort.
656 :param size: the bit-width of the bit-vector sort
657 :return: the bit-vector sort
659 cdef Sort sort = Sort(self)
660 sort.csort = self.csolver.mkBitVectorSort(size)
663 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
664 """Create a floating-point sort.
666 :param exp: the bit-width of the exponent of the floating-point sort.
667 :param sig: the bit-width of the significand of the floating-point sort.
669 cdef Sort sort = Sort(self)
670 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
673 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
674 """Create a datatype sort.
676 :param dtypedecl: the datatype declaration from which the sort is created
677 :return: the datatype sort
679 cdef Sort sort = Sort(self)
680 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
683 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
684 """Create a vector of datatype sorts using unresolved sorts. The names of
685 the datatype declarations in dtypedecls must be distinct.
687 This method is called when the DatatypeDecl objects dtypedecls have been
688 built using "unresolved" sorts.
690 We associate each sort in unresolvedSorts with exacly one datatype from
691 dtypedecls. In particular, it must have the same name as exactly one
692 datatype declaration in dtypedecls.
694 When constructing datatypes, unresolved sorts are replaced by the datatype
695 sort constructed for the datatype declaration it is associated with.
697 :param dtypedecls: the datatype declarations from which the sort is created
698 :param unresolvedSorts: the list of unresolved sorts
699 :return: the datatype sorts
701 if unresolvedSorts == None:
702 unresolvedSorts = set([])
704 assert isinstance(unresolvedSorts, Set)
707 cdef vector[c_DatatypeDecl] decls
708 for decl in dtypedecls:
709 decls.push_back((<DatatypeDecl?> decl).cdd)
711 cdef c_set[c_Sort] usorts
712 for usort in unresolvedSorts:
713 usorts.insert((<Sort?> usort).csort)
715 csorts = self.csolver.mkDatatypeSorts(
716 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
724 def mkFunctionSort(self, sorts, Sort codomain):
725 """ Create function sort.
727 :param sorts: the sort of the function arguments
728 :param codomain: the sort of the function return value
729 :return: the function sort
732 cdef Sort sort = Sort(self)
733 # populate a vector with dereferenced c_Sorts
734 cdef vector[c_Sort] v
736 if isinstance(sorts, Sort):
737 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
739 elif isinstance(sorts, list):
741 v.push_back((<Sort?>s).csort)
743 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
747 def mkParamSort(self, symbolname):
748 """ Create a sort parameter.
750 :param symbol: the name of the sort
751 :return: the sort parameter
753 cdef Sort sort = Sort(self)
754 sort.csort = self.csolver.mkParamSort(symbolname.encode())
757 @expand_list_arg(num_req_args=0)
758 def mkPredicateSort(self, *sorts):
759 """Create a predicate sort.
761 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
762 :return: the predicate sort
764 cdef Sort sort = Sort(self)
765 cdef vector[c_Sort] v
767 v.push_back((<Sort?> s).csort)
768 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
771 @expand_list_arg(num_req_args=0)
772 def mkRecordSort(self, *fields):
773 """Create a record sort
775 :param fields: the list of fields of the record, as a list or as distinct arguments
776 :return: the record sort
778 cdef Sort sort = Sort(self)
779 cdef vector[pair[string, c_Sort]] v
780 cdef pair[string, c_Sort] p
784 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
786 sort.csort = self.csolver.mkRecordSort(
787 <const vector[pair[string, c_Sort]] &> v)
790 def mkSetSort(self, Sort elemSort):
791 """Create a set sort.
793 :param elemSort: the sort of the set elements
794 :return: the set sort
796 cdef Sort sort = Sort(self)
797 sort.csort = self.csolver.mkSetSort(elemSort.csort)
800 def mkBagSort(self, Sort elemSort):
801 """Create a bag sort.
803 :param elemSort: the sort of the bag elements
804 :return: the bag sort
806 cdef Sort sort = Sort(self)
807 sort.csort = self.csolver.mkBagSort(elemSort.csort)
810 def mkSequenceSort(self, Sort elemSort):
811 """Create a sequence sort.
813 :param elemSort: the sort of the sequence elements
814 :return: the sequence sort
816 cdef Sort sort = Sort(self)
817 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
820 def mkUninterpretedSort(self, str name):
821 """Create an uninterpreted sort.
823 :param symbol: the name of the sort
824 :return: the uninterpreted sort
826 cdef Sort sort = Sort(self)
827 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
830 def mkSortConstructorSort(self, str symbol, size_t arity):
831 """Create a sort constructor sort.
833 :param symbol: the symbol of the sort
834 :param arity: the arity of the sort
835 :return: the sort constructor sort
837 cdef Sort sort = Sort(self)
838 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
841 @expand_list_arg(num_req_args=0)
842 def mkTupleSort(self, *sorts):
843 """Create a tuple sort.
845 :param sorts: of the elements of the tuple, as a list or as distinct arguments
846 :return: the tuple sort
848 cdef Sort sort = Sort(self)
849 cdef vector[c_Sort] v
851 v.push_back((<Sort?> s).csort)
852 sort.csort = self.csolver.mkTupleSort(v)
855 @expand_list_arg(num_req_args=1)
856 def mkTerm(self, kind_or_op, *args):
858 Supports the following arguments:
860 - ``Term mkTerm(Kind kind)``
861 - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
862 - ``Term mkTerm(Kind kind, List[Term] children)``
864 where ``List[Term]`` can also be comma-separated arguments
866 cdef Term term = Term(self)
867 cdef vector[c_Term] v
870 if isinstance(kind_or_op, kind):
871 op = self.mkOp(kind_or_op)
874 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
877 v.push_back((<Term?> a).cterm)
878 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
881 def mkTuple(self, sorts, terms):
882 """Create a tuple term. Terms are automatically converted if sorts are compatible.
884 :param sorts: The sorts of the elements in the tuple
885 :param terms: The elements in the tuple
886 :return: the tuple Term
888 cdef vector[c_Sort] csorts
889 cdef vector[c_Term] cterms
892 csorts.push_back((<Sort?> s).csort)
894 cterms.push_back((<Term?> s).cterm)
895 cdef Term result = Term(self)
896 result.cterm = self.csolver.mkTuple(csorts, cterms)
899 @expand_list_arg(num_req_args=0)
900 def mkOp(self, kind k, *args):
902 Supports the following uses:
904 - ``Op mkOp(Kind kind)``
905 - ``Op mkOp(Kind kind, Kind k)``
906 - ``Op mkOp(Kind kind, const string& arg)``
907 - ``Op mkOp(Kind kind, uint32_t arg)``
908 - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
910 cdef Op op = Op(self)
914 op.cop = self.csolver.mkOp(k.k)
916 if isinstance(args[0], str):
917 op.cop = self.csolver.mkOp(k.k,
920 elif isinstance(args[0], int):
921 op.cop = self.csolver.mkOp(k.k, <int?> args[0])
922 elif isinstance(args[0], list):
924 v.push_back((<int?> a))
925 op.cop = self.csolver.mkOp(k.k, <const vector[uint32_t]&> v)
927 raise ValueError("Unsupported signature"
928 " mkOp: {}".format(" X ".join([str(k), str(args[0])])))
930 if isinstance(args[0], int) and isinstance(args[1], int):
931 op.cop = self.csolver.mkOp(k.k, <int> args[0], <int> args[1])
933 raise ValueError("Unsupported signature"
934 " mkOp: {}".format(" X ".join([k, args[0], args[1]])))
938 """Create a Boolean true constant.
940 :return: the true constant
942 cdef Term term = Term(self)
943 term.cterm = self.csolver.mkTrue()
947 """Create a Boolean false constant.
949 :return: the false constant
951 cdef Term term = Term(self)
952 term.cterm = self.csolver.mkFalse()
955 def mkBoolean(self, bint val):
956 """Create a Boolean constant.
958 :return: the Boolean constant
959 :param val: the value of the constant
961 cdef Term term = Term(self)
962 term.cterm = self.csolver.mkBoolean(val)
966 """Create a constant representing the number Pi.
968 :return: a constant representing Pi
970 cdef Term term = Term(self)
971 term.cterm = self.csolver.mkPi()
974 def mkInteger(self, val):
975 """Create an integer constant.
977 :param val: representation of the constant: either a string or integer
978 :return: a constant of sort Integer
980 cdef Term term = Term(self)
981 if isinstance(val, str):
982 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
984 assert(isinstance(val, int))
985 term.cterm = self.csolver.mkInteger((<int?> val))
988 def mkReal(self, val, den=None):
989 """Create a real constant.
991 :param: `val` the value of the term. Can be an integer, float, or string. It will be formatted as a string before the term is built.
992 :param: `den` if not None, the value is `val`/`den`
993 :return: a real term with literal value
995 Can be used in various forms:
997 - Given a string ``"N/D"`` constructs the corresponding rational.
998 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
999 - Given a float ``f``, constructs the rational matching ``f``'s string representation. This means that ``mkReal(0.3)`` gives ``3/10`` and not the IEEE-754 approximation of ``3/10``.
1000 - Given a string ``"W"`` or an integer, constructs that integer.
1001 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1003 cdef Term term = Term(self)
1005 term.cterm = self.csolver.mkReal(str(val).encode())
1007 if not isinstance(val, int) or not isinstance(den, int):
1008 raise ValueError("Expecting integers when"
1009 " constructing a rational"
1010 " but got: {}".format((val, den)))
1011 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1014 def mkRegexpEmpty(self):
1015 """Create a regular expression empty term.
1017 :return: the empty term
1019 cdef Term term = Term(self)
1020 term.cterm = self.csolver.mkRegexpEmpty()
1023 def mkRegexpSigma(self):
1024 """Create a regular expression sigma term.
1026 :return: the sigma term
1028 cdef Term term = Term(self)
1029 term.cterm = self.csolver.mkRegexpSigma()
1032 def mkEmptySet(self, Sort s):
1033 """Create a constant representing an empty set of the given sort.
1035 :param sort: the sort of the set elements.
1036 :return: the empty set constant
1038 cdef Term term = Term(self)
1039 term.cterm = self.csolver.mkEmptySet(s.csort)
1042 def mkEmptyBag(self, Sort s):
1043 """Create a constant representing an empty bag of the given sort.
1045 :param sort: the sort of the bag elements.
1046 :return: the empty bag constant
1048 cdef Term term = Term(self)
1049 term.cterm = self.csolver.mkEmptyBag(s.csort)
1052 def mkSepNil(self, Sort sort):
1053 """Create a separation logic nil term.
1055 :param sort: the sort of the nil term
1056 :return: the separation logic nil term
1058 cdef Term term = Term(self)
1059 term.cterm = self.csolver.mkSepNil(sort.csort)
1062 def mkString(self, str s, useEscSequences = None):
1063 """Create a String constant from a `str` which may contain SMT-LIB
1064 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1066 :param s: the string this constant represents
1067 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1068 :return: the String constant
1070 cdef Term term = Term(self)
1071 cdef Py_ssize_t size
1072 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1073 if isinstance(useEscSequences, bool):
1074 term.cterm = self.csolver.mkString(
1075 s.encode(), <bint> useEscSequences)
1077 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1081 def mkEmptySequence(self, Sort sort):
1082 """Create an empty sequence of the given element sort.
1084 :param sort: The element sort of the sequence.
1085 :return: the empty sequence with given element sort.
1087 cdef Term term = Term(self)
1088 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1091 def mkUniverseSet(self, Sort sort):
1092 """Create a universe set of the given sort.
1094 :param sort: the sort of the set elements
1095 :return: the universe set constant
1097 cdef Term term = Term(self)
1098 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1101 @expand_list_arg(num_req_args=0)
1102 def mkBitVector(self, *args):
1104 Supports the following arguments:
1106 - ``Term mkBitVector(int size, int val=0)``
1107 - ``Term mkBitVector(int size, string val, int base)``
1109 :return: a bit-vector literal term
1110 :param: `size` an integer size.
1111 :param: `val` an integer representating the value, in the first form. In the second form, a string representing the value.
1112 :param: `base` the base of the string representation (second form only)
1114 cdef Term term = Term(self)
1116 raise ValueError("Missing arguments to mkBitVector")
1118 if not isinstance(size, int):
1120 "Invalid first argument to mkBitVector '{}', "
1121 "expected bit-vector size".format(size))
1123 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1124 elif len(args) == 2:
1126 if not isinstance(val, int):
1128 "Invalid second argument to mkBitVector '{}', "
1129 "expected integer value".format(size))
1130 term.cterm = self.csolver.mkBitVector(
1131 <uint32_t> size, <uint32_t> val)
1132 elif len(args) == 3:
1135 if not isinstance(val, str):
1137 "Invalid second argument to mkBitVector '{}', "
1138 "expected value string".format(size))
1139 if not isinstance(base, int):
1141 "Invalid third argument to mkBitVector '{}', "
1142 "expected base given as integer".format(size))
1143 term.cterm = self.csolver.mkBitVector(
1145 <const string&> str(val).encode(),
1148 raise ValueError("Unexpected inputs to mkBitVector")
1151 def mkConstArray(self, Sort sort, Term val):
1152 """ Create a constant array with the provided constant value stored at every
1155 :param sort: the sort of the constant array (must be an array sort)
1156 :param val: the constant value to store (must match the sort's element sort)
1157 :return: the constant array term
1159 cdef Term term = Term(self)
1160 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1163 def mkPosInf(self, int exp, int sig):
1164 """Create a positive infinity floating-point constant.
1166 :param exp: Number of bits in the exponent
1167 :param sig: Number of bits in the significand
1168 :return: the floating-point constant
1170 cdef Term term = Term(self)
1171 term.cterm = self.csolver.mkPosInf(exp, sig)
1174 def mkNegInf(self, int exp, int sig):
1175 """Create a negative infinity floating-point constant.
1177 :param exp: Number of bits in the exponent
1178 :param sig: Number of bits in the significand
1179 :return: the floating-point constant
1181 cdef Term term = Term(self)
1182 term.cterm = self.csolver.mkNegInf(exp, sig)
1185 def mkNaN(self, int exp, int sig):
1186 """Create a not-a-number (NaN) floating-point constant.
1188 :param exp: Number of bits in the exponent
1189 :param sig: Number of bits in the significand
1190 :return: the floating-point constant
1192 cdef Term term = Term(self)
1193 term.cterm = self.csolver.mkNaN(exp, sig)
1196 def mkPosZero(self, int exp, int sig):
1197 """Create a positive zero (+0.0) floating-point constant.
1199 :param exp: Number of bits in the exponent
1200 :param sig: Number of bits in the significand
1201 :return: the floating-point constant
1203 cdef Term term = Term(self)
1204 term.cterm = self.csolver.mkPosZero(exp, sig)
1207 def mkNegZero(self, int exp, int sig):
1208 """Create a negative zero (+0.0) floating-point constant.
1210 :param exp: Number of bits in the exponent
1211 :param sig: Number of bits in the significand
1212 :return: the floating-point constant
1214 cdef Term term = Term(self)
1215 term.cterm = self.csolver.mkNegZero(exp, sig)
1218 def mkRoundingMode(self, RoundingMode rm):
1219 """Create a roundingmode constant.
1221 :param rm: the floating point rounding mode this constant represents
1223 cdef Term term = Term(self)
1224 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
1227 def mkUninterpretedConst(self, Sort sort, int index):
1228 """Create uninterpreted constant.
1230 :param sort: Sort of the constant
1231 :param index: Index of the constant
1233 cdef Term term = Term(self)
1234 term.cterm = self.csolver.mkUninterpretedConst(sort.csort, index)
1237 def mkAbstractValue(self, index):
1238 """Create an abstract value constant.
1239 The given index needs to be positive.
1241 :param index: Index of the abstract value
1243 cdef Term term = Term(self)
1245 term.cterm = self.csolver.mkAbstractValue(str(index).encode())
1248 "mkAbstractValue expects a str representing a number"
1249 " or an int, but got{}".format(index))
1252 def mkFloatingPoint(self, int exp, int sig, Term val):
1253 """Create a floating-point constant.
1255 :param exp: Size of the exponent
1256 :param sig: Size of the significand
1257 :param val: Value of the floating-point constant as a bit-vector term
1259 cdef Term term = Term(self)
1260 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1263 def mkConst(self, Sort sort, symbol=None):
1265 Create (first-order) constant (0-arity function symbol).
1269 .. code-block:: smtlib
1271 ( declare-const <symbol> <sort> )
1272 ( declare-fun <symbol> ( ) <sort> )
1274 :param sort: the sort of the constant
1275 :param symbol: the name of the constant. If None, a default symbol is used.
1276 :return: the first-order constant
1278 cdef Term term = Term(self)
1280 term.cterm = self.csolver.mkConst(sort.csort)
1282 term.cterm = self.csolver.mkConst(sort.csort,
1283 (<str?> symbol).encode())
1286 def mkVar(self, Sort sort, symbol=None):
1287 """Create a bound variable to be used in a binder (i.e. a quantifier, a
1288 lambda, or a witness binder).
1290 :param sort: the sort of the variable
1291 :param symbol: the name of the variable
1292 :return: the variable
1294 cdef Term term = Term(self)
1296 term.cterm = self.csolver.mkVar(sort.csort)
1298 term.cterm = self.csolver.mkVar(sort.csort,
1299 (<str?> symbol).encode())
1302 def mkDatatypeConstructorDecl(self, str name):
1303 """ :return: a datatype constructor declaration
1304 :param: `name` the constructor's name
1306 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1307 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1310 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1311 """Create a datatype declaration.
1313 :param name: the name of the datatype
1314 :param isCoDatatype: true if a codatatype is to be constructed
1315 :return: the DatatypeDecl
1317 cdef DatatypeDecl dd = DatatypeDecl(self)
1318 cdef vector[c_Sort] v
1321 if sorts_or_bool is None and isCoDatatype is None:
1322 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1323 elif sorts_or_bool is not None and isCoDatatype is None:
1324 if isinstance(sorts_or_bool, bool):
1325 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1326 <bint> sorts_or_bool)
1327 elif isinstance(sorts_or_bool, Sort):
1328 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1329 (<Sort> sorts_or_bool).csort)
1330 elif isinstance(sorts_or_bool, list):
1331 for s in sorts_or_bool:
1332 v.push_back((<Sort?> s).csort)
1333 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1334 <const vector[c_Sort]&> v)
1336 raise ValueError("Unhandled second argument type {}"
1337 .format(type(sorts_or_bool)))
1338 elif sorts_or_bool is not None and isCoDatatype is not None:
1339 if isinstance(sorts_or_bool, Sort):
1340 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1341 (<Sort> sorts_or_bool).csort,
1342 <bint> isCoDatatype)
1343 elif isinstance(sorts_or_bool, list):
1344 for s in sorts_or_bool:
1345 v.push_back((<Sort?> s).csort)
1346 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1347 <const vector[c_Sort]&> v,
1348 <bint> isCoDatatype)
1350 raise ValueError("Unhandled second argument type {}"
1351 .format(type(sorts_or_bool)))
1353 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1360 def simplify(self, Term t):
1361 """Simplify a formula without doing "much" work. Does not involve the
1362 SAT Engine in the simplification, but uses the current definitions,
1363 assertions, and the current partial model, if one has been constructed.
1364 It also involves theory normalization.
1366 :param t: the formula to simplify
1367 :return: the simplified formula
1369 cdef Term term = Term(self)
1370 term.cterm = self.csolver.simplify(t.cterm)
1373 def assertFormula(self, Term term):
1374 """ Assert a formula
1378 .. code-block:: smtlib
1382 :param term: the formula to assert
1384 self.csolver.assertFormula(term.cterm)
1388 Check satisfiability.
1392 .. code-block:: smtlib
1396 :return: the result of the satisfiability check.
1398 cdef Result r = Result()
1399 r.cr = self.csolver.checkSat()
1402 def mkSygusGrammar(self, boundVars, ntSymbols):
1403 """Create a SyGuS grammar. The first non-terminal is treated as the
1404 starting non-terminal, so the order of non-terminals matters.
1406 :param boundVars: the parameters to corresponding synth-fun/synth-inv
1407 :param ntSymbols: the pre-declaration of the non-terminal symbols
1408 :return: the grammar
1410 cdef Grammar grammar = Grammar(self)
1411 cdef vector[c_Term] bvc
1412 cdef vector[c_Term] ntc
1413 for bv in boundVars:
1414 bvc.push_back((<Term?> bv).cterm)
1415 for nt in ntSymbols:
1416 ntc.push_back((<Term?> nt).cterm)
1417 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
1420 def mkSygusVar(self, Sort sort, str symbol=""):
1421 """Append symbol to the current list of universal variables.
1425 .. code-block:: smtlib
1427 ( declare-var <symbol> <sort> )
1429 :param sort: the sort of the universal variable
1430 :param symbol: the name of the universal variable
1431 :return: the universal variable
1433 cdef Term term = Term(self)
1434 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
1437 def addSygusConstraint(self, Term t):
1439 Add a formula to the set of SyGuS constraints.
1443 .. code-block:: smtlib
1445 ( constraint <term> )
1447 :param term: the formula to add as a constraint
1449 self.csolver.addSygusConstraint(t.cterm)
1451 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1452 """Add a set of SyGuS constraints to the current state that correspond to an
1453 invariant synthesis problem.
1457 .. code-block:: smtlib
1459 ( inv-constraint <inv> <pre> <trans> <post> )
1461 :param inv: the function-to-synthesize
1462 :param pre: the pre-condition
1463 :param trans: the transition relation
1464 :param post: the post-condition
1466 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1468 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1470 Synthesize n-ary function following specified syntactic constraints.
1474 .. code-block:: smtlib
1476 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1478 :param symbol: the name of the function
1479 :param boundVars: the parameters to this function
1480 :param sort: the sort of the return value of this function
1481 :param grammar: the syntactic constraints
1482 :return: the function
1484 cdef Term term = Term(self)
1485 cdef vector[c_Term] v
1486 for bv in bound_vars:
1487 v.push_back((<Term?> bv).cterm)
1489 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1491 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1494 def checkSynth(self):
1496 Try to find a solution for the synthesis conjecture corresponding to the
1497 current list of functions-to-synthesize, universal variables and
1502 .. code-block:: smtlib
1506 :return: the result of the synthesis conjecture.
1508 cdef Result r = Result()
1509 r.cr = self.csolver.checkSynth()
1512 def getSynthSolution(self, Term term):
1513 """Get the synthesis solution of the given term. This method should be
1514 called immediately after the solver answers unsat for sygus input.
1516 :param term: the term for which the synthesis solution is queried
1517 :return: the synthesis solution of the given term
1519 cdef Term t = Term(self)
1520 t.cterm = self.csolver.getSynthSolution(term.cterm)
1523 def getSynthSolutions(self, list terms):
1524 """Get the synthesis solutions of the given terms. This method should be
1525 called immediately after the solver answers unsat for sygus input.
1527 :param terms: the terms for which the synthesis solutions is queried
1528 :return: the synthesis solutions of the given terms
1531 cdef vector[c_Term] vec
1533 vec.push_back((<Term?> t).cterm)
1534 cresult = self.csolver.getSynthSolutions(vec)
1542 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1544 Synthesize invariant.
1548 .. code-block:: smtlib
1550 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1552 :param symbol: the name of the invariant
1553 :param boundVars: the parameters to this invariant
1554 :param grammar: the syntactic constraints
1555 :return: the invariant
1557 cdef Term term = Term(self)
1558 cdef vector[c_Term] v
1559 for bv in bound_vars:
1560 v.push_back((<Term?> bv).cterm)
1562 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1564 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1567 @expand_list_arg(num_req_args=0)
1568 def checkSatAssuming(self, *assumptions):
1569 """ Check satisfiability assuming the given formula.
1573 .. code-block:: smtlib
1575 ( check-sat-assuming ( <prop_literal> ) )
1577 :param assumptions: the formulas to assume, as a list or as distinct arguments
1578 :return: the result of the satisfiability check.
1580 cdef Result r = Result()
1581 # used if assumptions is a list of terms
1582 cdef vector[c_Term] v
1583 for a in assumptions:
1584 v.push_back((<Term?> a).cterm)
1585 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1588 @expand_list_arg(num_req_args=0)
1589 def checkEntailed(self, *assumptions):
1590 """Check entailment of the given formula w.r.t. the current set of assertions.
1592 :param terms: the formulas to check entailment for, as a list or as distinct arguments
1593 :return: the result of the entailment check.
1595 cdef Result r = Result()
1596 # used if assumptions is a list of terms
1597 cdef vector[c_Term] v
1598 for a in assumptions:
1599 v.push_back((<Term?> a).cterm)
1600 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
1603 @expand_list_arg(num_req_args=1)
1604 def declareDatatype(self, str symbol, *ctors):
1606 Create datatype sort.
1610 .. code-block:: smtlib
1612 ( declare-datatype <symbol> <datatype_decl> )
1614 :param symbol: the name of the datatype sort
1615 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1616 :return: the datatype sort
1618 cdef Sort sort = Sort(self)
1619 cdef vector[c_DatatypeConstructorDecl] v
1622 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1623 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1626 def declareFun(self, str symbol, list sorts, Sort sort):
1627 """Declare n-ary function symbol.
1631 .. code-block:: smtlib
1633 ( declare-fun <symbol> ( <sort>* ) <sort> )
1635 :param symbol: the name of the function
1636 :param sorts: the sorts of the parameters to this function
1637 :param sort: the sort of the return value of this function
1638 :return: the function
1640 cdef Term term = Term(self)
1641 cdef vector[c_Sort] v
1643 v.push_back((<Sort?> s).csort)
1644 term.cterm = self.csolver.declareFun(symbol.encode(),
1645 <const vector[c_Sort]&> v,
1649 def declareSort(self, str symbol, int arity):
1650 """Declare uninterpreted sort.
1654 .. code-block:: smtlib
1656 ( declare-sort <symbol> <numeral> )
1658 :param symbol: the name of the sort
1659 :param arity: the arity of the sort
1662 cdef Sort sort = Sort(self)
1663 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1666 def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1668 Define n-ary function.
1671 - ``Term defineFun(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1672 - ``Term defineFun(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1677 .. code-block:: smtlib
1679 ( define-fun <function_def> )
1681 :param symbol: the name of the function
1682 :param bound_vars: the parameters to this function
1683 :param sort: the sort of the return value of this function
1684 :param term: the function body
1685 :param global: determines whether this definition is global (i.e. persists when popping the context)
1686 :return: the function
1688 cdef Term term = Term(self)
1689 cdef vector[c_Term] v
1690 for bv in bound_vars:
1691 v.push_back((<Term?> bv).cterm)
1694 term.cterm = self.csolver.defineFun((<str?> sym_or_fun).encode(),
1695 <const vector[c_Term] &> v,
1696 (<Sort?> sort_or_term).csort,
1700 term.cterm = self.csolver.defineFun((<Term?> sym_or_fun).cterm,
1701 <const vector[c_Term]&> v,
1702 (<Term?> sort_or_term).cterm,
1707 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1708 """Define recursive functions.
1712 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1713 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1718 .. code-block:: smtlib
1720 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1722 Create elements of parameter ``funs`` with mkConst().
1724 :param funs: the sorted functions
1725 :param bound_vars: the list of parameters to the functions
1726 :param terms: the list of function bodies of the functions
1727 :param global: determines whether this definition is global (i.e. persists when popping the context)
1728 :return: the function
1730 cdef Term term = Term(self)
1731 cdef vector[c_Term] v
1732 for bv in bound_vars:
1733 v.push_back((<Term?> bv).cterm)
1736 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1737 <const vector[c_Term] &> v,
1738 (<Sort?> sort_or_term).csort,
1742 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1743 <const vector[c_Term]&> v,
1744 (<Term?> sort_or_term).cterm,
1749 def defineFunsRec(self, funs, bound_vars, terms):
1750 """Define recursive functions.
1754 .. code-block:: smtlib
1756 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1758 Create elements of parameter ``funs`` with mkConst().
1760 :param funs: the sorted functions
1761 :param bound_vars: the list of parameters to the functions
1762 :param terms: the list of function bodies of the functions
1763 :param global: determines whether this definition is global (i.e. persists when popping the context)
1764 :return: the function
1766 cdef vector[c_Term] vf
1767 cdef vector[vector[c_Term]] vbv
1768 cdef vector[c_Term] vt
1771 vf.push_back((<Term?> f).cterm)
1773 cdef vector[c_Term] temp
1774 for v in bound_vars:
1776 temp.push_back((<Term?> t).cterm)
1781 vf.push_back((<Term?> t).cterm)
1783 def getAssertions(self):
1784 """Get the list of asserted formulas.
1788 .. code-block:: smtlib
1792 :return: the list of asserted formulas
1795 for a in self.csolver.getAssertions():
1798 assertions.append(term)
1801 def getInfo(self, str flag):
1802 """Get info from the solver.
1806 .. code-block:: smtlib
1808 ( get-info <info_flag> )
1810 :param flag: the info flag
1813 return self.csolver.getInfo(flag.encode())
1815 def getOption(self, str option):
1816 """Get the value of a given option.
1820 .. code-block:: smtlib
1822 ( get-option <keyword> )
1824 :param option: the option for which the value is queried
1825 :return: a string representation of the option value
1827 return self.csolver.getOption(option.encode())
1829 def getUnsatAssumptions(self):
1831 Get the set of unsat ("failed") assumptions.
1835 .. code-block:: smtlib
1837 ( get-unsat-assumptions )
1839 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
1841 :return: the set of unsat assumptions.
1844 for a in self.csolver.getUnsatAssumptions():
1847 assumptions.append(term)
1850 def getUnsatCore(self):
1851 """Get the unsatisfiable core.
1855 .. code-block:: smtlib
1859 Requires to enable option :ref:`produce-unsat-cores <lbl-produce-unsat-cores>`.
1861 :return: a set of terms representing the unsatisfiable core
1864 for a in self.csolver.getUnsatCore():
1870 def getValue(self, Term t):
1871 """Get the value of the given term in the current model.
1875 .. code-block:: smtlib
1877 ( get-value ( <term> ) )
1879 :param term: the term for which the value is queried
1880 :return: the value of the given term
1882 cdef Term term = Term(self)
1883 term.cterm = self.csolver.getValue(t.cterm)
1886 def getModelDomainElements(self, Sort s):
1888 Get the domain elements of uninterpreted sort s in the current model. The
1889 current model interprets s as the finite sort whose domain elements are
1890 given in the return value of this method.
1892 :param s: The uninterpreted sort in question
1893 :return: the domain elements of s in the current model
1896 cresult = self.csolver.getModelDomainElements(s.csort)
1903 def isModelCoreSymbol(self, Term v):
1904 """This returns false if the model value of free constant v was not
1905 essential for showing the satisfiability of the last call to checkSat
1906 using the current model. This method will only return false (for any v)
1907 if the model-cores option has been set.
1909 :param v: The term in question
1910 :return: true if v is a model core symbol
1912 return self.csolver.isModelCoreSymbol(v.cterm)
1914 def getSeparationHeap(self):
1915 """When using separation logic, obtain the term for the heap.
1917 :return: The term for the heap
1919 cdef Term term = Term(self)
1920 term.cterm = self.csolver.getSeparationHeap()
1923 def getSeparationNilTerm(self):
1924 """When using separation logic, obtain the term for nil.
1926 :return: The term for nil
1928 cdef Term term = Term(self)
1929 term.cterm = self.csolver.getSeparationNilTerm()
1932 def declareSeparationHeap(self, Sort locType, Sort dataType):
1934 When using separation logic, this sets the location sort and the
1935 datatype sort to the given ones. This method should be invoked exactly
1936 once, before any separation logic constraints are provided.
1938 :param locSort: The location sort of the heap
1939 :param dataSort: The data sort of the heap
1941 self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
1943 def declarePool(self, str symbol, Sort sort, initValue):
1944 """Declare a symbolic pool of terms with the given initial value.
1948 .. code-block:: smtlib
1950 ( declare-pool <symbol> <sort> ( <term>* ) )
1952 :param symbol: The name of the pool
1953 :param sort: The sort of the elements of the pool.
1954 :param initValue: The initial value of the pool
1956 cdef Term term = Term(self)
1957 cdef vector[c_Term] niv
1959 niv.push_back((<Term?> v).cterm)
1960 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
1963 def pop(self, nscopes=1):
1964 """Pop ``nscopes`` level(s) from the assertion stack.
1968 .. code-block:: smtlib
1972 :param nscopes: the number of levels to pop
1974 self.csolver.pop(nscopes)
1976 def push(self, nscopes=1):
1977 """ Push ``nscopes`` level(s) to the assertion stack.
1981 .. code-block:: smtlib
1985 :param nscopes: the number of levels to push
1987 self.csolver.push(nscopes)
1989 def resetAssertions(self):
1991 Remove all assertions.
1995 .. code-block:: smtlib
1997 ( reset-assertions )
2000 self.csolver.resetAssertions()
2002 def setInfo(self, str keyword, str value):
2007 .. code-block:: smtlib
2009 ( set-info <attribute> )
2011 :param keyword: the info flag
2012 :param value: the value of the info flag
2014 self.csolver.setInfo(keyword.encode(), value.encode())
2016 def setLogic(self, str logic):
2021 .. code-block:: smtlib
2023 ( set-logic <symbol> )
2025 :param logic: the logic to set
2027 self.csolver.setLogic(logic.encode())
2029 def setOption(self, str option, str value):
2034 .. code-block:: smtlib
2036 ( set-option <option> )
2038 :param option: the option name
2039 :param value: the option value
2041 self.csolver.setOption(option.encode(), value.encode())
2047 def __cinit__(self, Solver solver):
2048 # csort always set by Solver
2049 self.solver = solver
2051 def __eq__(self, Sort other):
2052 return self.csort == other.csort
2054 def __ne__(self, Sort other):
2055 return self.csort != other.csort
2057 def __lt__(self, Sort other):
2058 return self.csort < other.csort
2060 def __gt__(self, Sort other):
2061 return self.csort > other.csort
2063 def __le__(self, Sort other):
2064 return self.csort <= other.csort
2066 def __ge__(self, Sort other):
2067 return self.csort >= other.csort
2070 return self.csort.toString().decode()
2073 return self.csort.toString().decode()
2076 return csorthash(self.csort)
2078 def isBoolean(self):
2079 return self.csort.isBoolean()
2081 def isInteger(self):
2082 return self.csort.isInteger()
2085 return self.csort.isReal()
2088 return self.csort.isString()
2091 return self.csort.isRegExp()
2093 def isRoundingMode(self):
2094 return self.csort.isRoundingMode()
2096 def isBitVector(self):
2097 return self.csort.isBitVector()
2099 def isFloatingPoint(self):
2100 return self.csort.isFloatingPoint()
2102 def isDatatype(self):
2103 return self.csort.isDatatype()
2105 def isParametricDatatype(self):
2106 return self.csort.isParametricDatatype()
2108 def isConstructor(self):
2109 return self.csort.isConstructor()
2111 def isSelector(self):
2112 return self.csort.isSelector()
2115 return self.csort.isTester()
2117 def isFunction(self):
2118 return self.csort.isFunction()
2120 def isPredicate(self):
2121 return self.csort.isPredicate()
2124 return self.csort.isTuple()
2127 return self.csort.isRecord()
2130 return self.csort.isArray()
2133 return self.csort.isSet()
2136 return self.csort.isBag()
2138 def isSequence(self):
2139 return self.csort.isSequence()
2141 def isUninterpretedSort(self):
2142 return self.csort.isUninterpretedSort()
2144 def isSortConstructor(self):
2145 return self.csort.isSortConstructor()
2147 def isFirstClass(self):
2148 return self.csort.isFirstClass()
2150 def isFunctionLike(self):
2151 return self.csort.isFunctionLike()
2153 def isSubsortOf(self, Sort sort):
2154 return self.csort.isSubsortOf(sort.csort)
2156 def isComparableTo(self, Sort sort):
2157 return self.csort.isComparableTo(sort.csort)
2159 def getDatatype(self):
2160 cdef Datatype d = Datatype(self.solver)
2161 d.cd = self.csort.getDatatype()
2164 def instantiate(self, params):
2165 cdef Sort sort = Sort(self.solver)
2166 cdef vector[c_Sort] v
2168 v.push_back((<Sort?> s).csort)
2169 sort.csort = self.csort.instantiate(v)
2172 def getConstructorArity(self):
2173 return self.csort.getConstructorArity()
2175 def getConstructorDomainSorts(self):
2177 for s in self.csort.getConstructorDomainSorts():
2178 sort = Sort(self.solver)
2180 domain_sorts.append(sort)
2183 def getConstructorCodomainSort(self):
2184 cdef Sort sort = Sort(self.solver)
2185 sort.csort = self.csort.getConstructorCodomainSort()
2188 def getSelectorDomainSort(self):
2189 cdef Sort sort = Sort(self.solver)
2190 sort.csort = self.csort.getSelectorDomainSort()
2193 def getSelectorCodomainSort(self):
2194 cdef Sort sort = Sort(self.solver)
2195 sort.csort = self.csort.getSelectorCodomainSort()
2198 def getTesterDomainSort(self):
2199 cdef Sort sort = Sort(self.solver)
2200 sort.csort = self.csort.getTesterDomainSort()
2203 def getTesterCodomainSort(self):
2204 cdef Sort sort = Sort(self.solver)
2205 sort.csort = self.csort.getTesterCodomainSort()
2208 def getFunctionArity(self):
2209 return self.csort.getFunctionArity()
2211 def getFunctionDomainSorts(self):
2213 for s in self.csort.getFunctionDomainSorts():
2214 sort = Sort(self.solver)
2216 domain_sorts.append(sort)
2219 def getFunctionCodomainSort(self):
2220 cdef Sort sort = Sort(self.solver)
2221 sort.csort = self.csort.getFunctionCodomainSort()
2224 def getArrayIndexSort(self):
2225 cdef Sort sort = Sort(self.solver)
2226 sort.csort = self.csort.getArrayIndexSort()
2229 def getArrayElementSort(self):
2230 cdef Sort sort = Sort(self.solver)
2231 sort.csort = self.csort.getArrayElementSort()
2234 def getSetElementSort(self):
2235 cdef Sort sort = Sort(self.solver)
2236 sort.csort = self.csort.getSetElementSort()
2239 def getBagElementSort(self):
2240 cdef Sort sort = Sort(self.solver)
2241 sort.csort = self.csort.getBagElementSort()
2244 def getSequenceElementSort(self):
2245 cdef Sort sort = Sort(self.solver)
2246 sort.csort = self.csort.getSequenceElementSort()
2249 def getUninterpretedSortName(self):
2250 return self.csort.getUninterpretedSortName().decode()
2252 def isUninterpretedSortParameterized(self):
2253 return self.csort.isUninterpretedSortParameterized()
2255 def getUninterpretedSortParamSorts(self):
2257 for s in self.csort.getUninterpretedSortParamSorts():
2258 sort = Sort(self.solver)
2260 param_sorts.append(sort)
2263 def getSortConstructorName(self):
2264 return self.csort.getSortConstructorName().decode()
2266 def getSortConstructorArity(self):
2267 return self.csort.getSortConstructorArity()
2269 def getBVSize(self):
2270 return self.csort.getBVSize()
2272 def getFPExponentSize(self):
2273 return self.csort.getFPExponentSize()
2275 def getFPSignificandSize(self):
2276 return self.csort.getFPSignificandSize()
2278 def getDatatypeParamSorts(self):
2280 for s in self.csort.getDatatypeParamSorts():
2281 sort = Sort(self.solver)
2283 param_sorts.append(sort)
2286 def getDatatypeArity(self):
2287 return self.csort.getDatatypeArity()
2289 def getTupleLength(self):
2290 return self.csort.getTupleLength()
2292 def getTupleSorts(self):
2294 for s in self.csort.getTupleSorts():
2295 sort = Sort(self.solver)
2297 tuple_sorts.append(sort)
2304 def __cinit__(self, Solver solver):
2305 # cterm always set in the Solver object
2306 self.solver = solver
2308 def __eq__(self, Term other):
2309 return self.cterm == other.cterm
2311 def __ne__(self, Term other):
2312 return self.cterm != other.cterm
2314 def __lt__(self, Term other):
2315 return self.cterm < other.cterm
2317 def __gt__(self, Term other):
2318 return self.cterm > other.cterm
2320 def __le__(self, Term other):
2321 return self.cterm <= other.cterm
2323 def __ge__(self, Term other):
2324 return self.cterm >= other.cterm
2326 def __getitem__(self, int index):
2327 cdef Term term = Term(self.solver)
2329 term.cterm = self.cterm[index]
2331 raise ValueError("Expecting a non-negative integer or string")
2335 return self.cterm.toString().decode()
2338 return self.cterm.toString().decode()
2341 for ci in self.cterm:
2342 term = Term(self.solver)
2347 return ctermhash(self.cterm)
2349 def getNumChildren(self):
2350 return self.cterm.getNumChildren()
2353 return self.cterm.getId()
2356 return kind(<int> self.cterm.getKind())
2359 cdef Sort sort = Sort(self.solver)
2360 sort.csort = self.cterm.getSort()
2363 def substitute(self, term_or_list_1, term_or_list_2):
2364 # The resulting term after substitution
2365 cdef Term term = Term(self.solver)
2366 # lists for substitutions
2367 cdef vector[c_Term] ces
2368 cdef vector[c_Term] creplacements
2370 # normalize the input parameters to be lists
2371 if isinstance(term_or_list_1, list):
2372 assert isinstance(term_or_list_2, list)
2374 replacements = term_or_list_2
2375 if len(es) != len(replacements):
2376 raise RuntimeError("Expecting list inputs to substitute to "
2377 "have the same length but got: "
2378 "{} and {}".format(len(es), len(replacements)))
2380 for e, r in zip(es, replacements):
2381 ces.push_back((<Term?> e).cterm)
2382 creplacements.push_back((<Term?> r).cterm)
2385 # add the single elements to the vectors
2386 ces.push_back((<Term?> term_or_list_1).cterm)
2387 creplacements.push_back((<Term?> term_or_list_2).cterm)
2389 # call the API substitute method with lists
2390 term.cterm = self.cterm.substitute(ces, creplacements)
2394 return self.cterm.hasOp()
2397 cdef Op op = Op(self.solver)
2398 op.cop = self.cterm.getOp()
2402 return self.cterm.isNull()
2405 cdef Term term = Term(self.solver)
2406 term.cterm = self.cterm.notTerm()
2409 def andTerm(self, Term t):
2410 cdef Term term = Term(self.solver)
2411 term.cterm = self.cterm.andTerm((<Term> t).cterm)
2414 def orTerm(self, Term t):
2415 cdef Term term = Term(self.solver)
2416 term.cterm = self.cterm.orTerm(t.cterm)
2419 def xorTerm(self, Term t):
2420 cdef Term term = Term(self.solver)
2421 term.cterm = self.cterm.xorTerm(t.cterm)
2424 def eqTerm(self, Term t):
2425 cdef Term term = Term(self.solver)
2426 term.cterm = self.cterm.eqTerm(t.cterm)
2429 def impTerm(self, Term t):
2430 cdef Term term = Term(self.solver)
2431 term.cterm = self.cterm.impTerm(t.cterm)
2434 def iteTerm(self, Term then_t, Term else_t):
2435 cdef Term term = Term(self.solver)
2436 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
2439 def isConstArray(self):
2440 return self.cterm.isConstArray()
2442 def getConstArrayBase(self):
2443 cdef Term term = Term(self.solver)
2444 term.cterm = self.cterm.getConstArrayBase()
2447 def isBooleanValue(self):
2448 return self.cterm.isBooleanValue()
2450 def getBooleanValue(self):
2451 return self.cterm.getBooleanValue()
2453 def isStringValue(self):
2454 return self.cterm.isStringValue()
2456 def getStringValue(self):
2457 cdef Py_ssize_t size
2458 cdef c_wstring s = self.cterm.getStringValue()
2459 return PyUnicode_FromWideChar(s.data(), s.size())
2461 def isIntegerValue(self):
2462 return self.cterm.isIntegerValue()
2463 def isAbstractValue(self):
2464 return self.cterm.isAbstractValue()
2466 def getAbstractValue(self):
2467 return self.cterm.getAbstractValue().decode()
2469 def isFloatingPointPosZero(self):
2470 return self.cterm.isFloatingPointPosZero()
2472 def isFloatingPointNegZero(self):
2473 return self.cterm.isFloatingPointNegZero()
2475 def isFloatingPointPosInf(self):
2476 return self.cterm.isFloatingPointPosInf()
2478 def isFloatingPointNegInf(self):
2479 return self.cterm.isFloatingPointNegInf()
2481 def isFloatingPointNaN(self):
2482 return self.cterm.isFloatingPointNaN()
2484 def isFloatingPointValue(self):
2485 return self.cterm.isFloatingPointValue()
2487 def getFloatingPointValue(self):
2488 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
2489 cdef Term term = Term(self.solver)
2490 term.cterm = get2(t)
2491 return (get0(t), get1(t), term)
2493 def isSetValue(self):
2494 return self.cterm.isSetValue()
2496 def getSetValue(self):
2498 for e in self.cterm.getSetValue():
2499 term = Term(self.solver)
2504 def isSequenceValue(self):
2505 return self.cterm.isSequenceValue()
2507 def getSequenceValue(self):
2509 for e in self.cterm.getSequenceValue():
2510 term = Term(self.solver)
2515 def isUninterpretedValue(self):
2516 return self.cterm.isUninterpretedValue()
2518 def getUninterpretedValue(self):
2519 cdef pair[c_Sort, int32_t] p = self.cterm.getUninterpretedValue()
2520 cdef Sort sort = Sort(self.solver)
2521 sort.csort = p.first
2525 def isTupleValue(self):
2526 return self.cterm.isTupleValue()
2528 def getTupleValue(self):
2530 for e in self.cterm.getTupleValue():
2531 term = Term(self.solver)
2536 def getIntegerValue(self):
2537 return int(self.cterm.getIntegerValue().decode())
2539 def isRealValue(self):
2540 return self.cterm.isRealValue()
2542 def getRealValue(self):
2543 """Returns the value of a real term as a Fraction"""
2544 return Fraction(self.cterm.getRealValue().decode())
2546 def isBitVectorValue(self):
2547 return self.cterm.isBitVectorValue()
2549 def getBitVectorValue(self, base = 2):
2550 """Returns the value of a bit-vector term as a 0/1 string"""
2551 return self.cterm.getBitVectorValue(base).decode()
2553 def toPythonObj(self):
2555 Converts a constant value Term to a Python object.
2558 Boolean -- returns a Python bool
2559 Int -- returns a Python int
2560 Real -- returns a Python Fraction
2561 BV -- returns a Python int (treats BV as unsigned)
2562 String -- returns a Python Unicode string
2563 Array -- returns a Python dict mapping indices to values
2564 -- the constant base is returned as the default value
2567 if self.isBooleanValue():
2568 return self.getBooleanValue()
2569 elif self.isIntegerValue():
2570 return self.getIntegerValue()
2571 elif self.isRealValue():
2572 return self.getRealValue()
2573 elif self.isBitVectorValue():
2574 return int(self.getBitVectorValue(), 2)
2575 elif self.isStringValue():
2576 return self.getStringValue()
2577 elif self.getSort().isArray():
2583 # Array models are represented as a series of store operations
2584 # on a constant array
2587 if t.getKind() == kinds.Store:
2589 keys.append(t[1].toPythonObj())
2590 values.append(t[2].toPythonObj())
2591 to_visit.append(t[0])
2593 assert t.getKind() == kinds.ConstArray
2594 base_value = t.getConstArrayBase().toPythonObj()
2596 assert len(keys) == len(values)
2597 assert base_value is not None
2599 # put everything in a dictionary with the constant
2600 # base as the result for any index not included in the stores
2601 res = defaultdict(lambda : base_value)
2602 for k, v in zip(keys, values):
2608 # Generate rounding modes
2609 cdef __rounding_modes = {
2610 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
2611 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
2612 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
2613 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
2614 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
2617 mod_ref = sys.modules[__name__]
2618 for rm_int, name in __rounding_modes.items():
2619 r = RoundingMode(rm_int)
2621 if name in dir(mod_ref):
2622 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
2624 setattr(mod_ref, name, r)
2631 # Generate unknown explanations
2632 cdef __unknown_explanations = {
2633 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
2634 <int> INCOMPLETE: "Incomplete",
2635 <int> TIMEOUT: "Timeout",
2636 <int> RESOURCEOUT: "Resourceout",
2637 <int> MEMOUT: "Memout",
2638 <int> INTERRUPTED: "Interrupted",
2639 <int> NO_STATUS: "NoStatus",
2640 <int> UNSUPPORTED: "Unsupported",
2641 <int> OTHER: "Other",
2642 <int> UNKNOWN_REASON: "UnknownReason"
2645 for ue_int, name in __unknown_explanations.items():
2646 u = UnknownExplanation(ue_int)
2648 if name in dir(mod_ref):
2649 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
2651 setattr(mod_ref, name, u)