1 from collections import defaultdict
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]()
100 Wrapper class for :cpp:class:`cvc5::api::Datatype`.
104 def __cinit__(self, Solver solver):
107 def __getitem__(self, index):
108 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
109 if isinstance(index, int) and index >= 0:
110 dc.cdc = self.cd[(<int?> index)]
111 elif isinstance(index, str):
112 dc.cdc = self.cd[(<const string &> index.encode())]
114 raise ValueError("Expecting a non-negative integer or string")
117 def getConstructor(self, str name):
119 :param name: the name of the constructor.
120 :return: a constructor by name.
122 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
123 dc.cdc = self.cd.getConstructor(name.encode())
126 def getConstructorTerm(self, str name):
128 :param name: the name of the constructor.
129 :return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::api::Datatype::getConstructorTerm>`).
131 cdef Term term = Term(self.solver)
132 term.cterm = self.cd.getConstructorTerm(name.encode())
135 def getSelector(self, str name):
137 :param name: the name of the selector..
138 :return: a selector by name.
140 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
141 ds.cds = self.cd.getSelector(name.encode())
146 :return: the name of the datatype.
148 return self.cd.getName().decode()
150 def getNumConstructors(self):
152 :return: number of constructors in this datatype.
154 return self.cd.getNumConstructors()
156 def getParameters(self):
158 :return: the parameters of this datatype, if it is parametric. An
159 exception is thrown if this datatype is not parametric.
162 for s in self.cd.getParameters():
163 sort = Sort(self.solver)
165 param_sorts.append(sort)
168 def isParametric(self):
169 """:return: True if this datatype is parametric."""
170 return self.cd.isParametric()
172 def isCodatatype(self):
173 """:return: True if this datatype corresponds to a co-datatype."""
174 return self.cd.isCodatatype()
177 """:return: True if this datatype corresponds to a tuple."""
178 return self.cd.isTuple()
181 """:return: True if this datatype corresponds to a record."""
182 return self.cd.isRecord()
185 """:return: True if this datatype is finite."""
186 return self.cd.isFinite()
188 def isWellFounded(self):
189 """:return: True if this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::api::Datatype::isWellFounded>`)."""
190 return self.cd.isWellFounded()
193 """:return: True if this Datatype is a null object."""
194 return self.cd.isNull()
197 return self.cd.toString().decode()
200 return self.cd.toString().decode()
204 dc = DatatypeConstructor(self.solver)
209 cdef class DatatypeConstructor:
211 A cvc5 datatype constructor.
212 Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructor`.
214 cdef c_DatatypeConstructor cdc
216 def __cinit__(self, Solver solver):
217 self.cdc = c_DatatypeConstructor()
220 def __getitem__(self, index):
221 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
222 if isinstance(index, int) and index >= 0:
223 ds.cds = self.cdc[(<int?> index)]
224 elif isinstance(index, str):
225 ds.cds = self.cdc[(<const string &> index.encode())]
227 raise ValueError("Expecting a non-negative integer or string")
232 :return: the name of the constructor.
234 return self.cdc.getName().decode()
236 def getConstructorTerm(self):
238 :return: the constructor operator as a term.
240 cdef Term term = Term(self.solver)
241 term.cterm = self.cdc.getConstructorTerm()
244 def getInstantiatedConstructorTerm(self, Sort retSort):
246 Specialized method for parametric datatypes (see
247 :cpp:func:`DatatypeConstructor::getInstantiatedConstructorTerm()
248 <cvc5::api::DatatypeConstructor::getInstantiatedConstructorTerm>`).
250 :param retSort: the desired return sort of the constructor
251 :return: the constructor operator as a term.
253 cdef Term term = Term(self.solver)
254 term.cterm = self.cdc.getInstantiatedConstructorTerm(retSort.csort)
257 def getTesterTerm(self):
259 :return: the tester operator that is related to this constructor, as a term.
261 cdef Term term = Term(self.solver)
262 term.cterm = self.cdc.getTesterTerm()
265 def getNumSelectors(self):
267 :return: the number of selecters (so far) of this Datatype constructor.
269 return self.cdc.getNumSelectors()
271 def getSelector(self, str name):
273 :param name: the name of the datatype selector.
274 :return: the first datatype selector with the given name
276 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
277 ds.cds = self.cdc.getSelector(name.encode())
280 def getSelectorTerm(self, str name):
282 :param name: the name of the datatype selector.
283 :return: a term representing the firstdatatype selector with the given name.
285 cdef Term term = Term(self.solver)
286 term.cterm = self.cdc.getSelectorTerm(name.encode())
290 """:return: True if this DatatypeConstructor is a null object."""
291 return self.cdc.isNull()
294 return self.cdc.toString().decode()
297 return self.cdc.toString().decode()
301 ds = DatatypeSelector(self.solver)
306 cdef class DatatypeConstructorDecl:
308 A cvc5 datatype constructor declaration.
309 Wrapper class for :cpp:class:`cvc5::api::DatatypeConstructorDecl`.
311 cdef c_DatatypeConstructorDecl cddc
314 def __cinit__(self, Solver solver):
317 def addSelector(self, str name, Sort sort):
319 Add datatype selector declaration.
321 :param name: the name of the datatype selector declaration to add.
322 :param sort: the codomain sort of the datatype selector declaration
325 self.cddc.addSelector(name.encode(), sort.csort)
327 def addSelectorSelf(self, str name):
329 Add datatype selector declaration whose codomain sort is the
332 :param name: the name of the datatype selector declaration to add.
334 self.cddc.addSelectorSelf(name.encode())
337 """:return: True if this DatatypeConstructorDecl is a null object."""
338 return self.cddc.isNull()
341 return self.cddc.toString().decode()
344 return self.cddc.toString().decode()
347 cdef class DatatypeDecl:
349 A cvc5 datatype declaration.
350 Wrapper class for :cpp:class:`cvc5::api::DatatypeDecl`.
352 cdef c_DatatypeDecl cdd
354 def __cinit__(self, Solver solver):
357 def addConstructor(self, DatatypeConstructorDecl ctor):
359 Add a datatype constructor declaration.
361 :param ctor: the datatype constructor declaration to add.
363 self.cdd.addConstructor(ctor.cddc)
365 def getNumConstructors(self):
367 :return: number of constructors (so far) for this datatype declaration.
369 return self.cdd.getNumConstructors()
371 def isParametric(self):
373 :return: is this datatype declaration parametric?
375 return self.cdd.isParametric()
379 :return: the name of this datatype declaration.
381 return self.cdd.getName().decode()
384 """:return: True if this DatatypeDecl is a null object."""
385 return self.cdd.isNull()
388 return self.cdd.toString().decode()
391 return self.cdd.toString().decode()
394 cdef class DatatypeSelector:
396 A cvc5 datatype selector.
397 Wrapper class for :cpp:class:`cvc5::api::DatatypeSelector`.
399 cdef c_DatatypeSelector cds
401 def __cinit__(self, Solver solver):
402 self.cds = c_DatatypeSelector()
407 :return: the name of this datatype selector.
409 return self.cds.getName().decode()
411 def getSelectorTerm(self):
413 :return: the selector opeartor of this datatype selector as a term.
415 cdef Term term = Term(self.solver)
416 term.cterm = self.cds.getSelectorTerm()
419 def getUpdaterTerm(self):
421 :return: the updater opeartor of this datatype selector as a term.
423 cdef Term term = Term(self.solver)
424 term.cterm = self.cds.getUpdaterTerm()
427 def getCodomainSort(self):
429 :return: the codomain sort of this selector.
431 cdef Sort sort = Sort(self.solver)
432 sort.csort = self.cds.getCodomainSort()
436 """:return: True if this DatatypeSelector is a null object."""
437 return self.cds.isNull()
440 return self.cds.toString().decode()
443 return self.cds.toString().decode()
449 An operator is a term that represents certain operators,
450 instantiated with its required parameters, e.g.,
451 a term of kind :cpp:enumerator:`BITVECTOR_EXTRACT`.
452 Wrapper class for :cpp:class:`cvc5::api::Op`.
456 def __cinit__(self, Solver solver):
460 def __eq__(self, Op other):
461 return self.cop == other.cop
463 def __ne__(self, Op other):
464 return self.cop != other.cop
467 return self.cop.toString().decode()
470 return self.cop.toString().decode()
473 return cophash(self.cop)
477 :return: the kind of this operator.
479 return Kind(<int> self.cop.getKind())
483 :return: True iff this operator is indexed.
485 return self.cop.isIndexed()
489 :return: True iff this operator is a null term.
491 return self.cop.isNull()
493 def getNumIndices(self):
495 :return: number of indices of this op.
497 return self.cop.getNumIndices()
499 def getIndices(self):
501 :return: the indices used to create this Op (see :cpp:func:`Op::getIndices() <cvc5::api::Op::getIndices>`).
505 indices = self.cop.getIndices[string]().decode()
510 indices = self.cop.getIndices[uint32_t]()
515 indices = self.cop.getIndices[pair[uint32_t, uint32_t]]()
520 raise RuntimeError("Unable to retrieve indices from {}".format(self))
527 Wrapper class for :cpp:class:`cvc5::api::Grammar`.
529 cdef c_Grammar cgrammar
531 def __cinit__(self, Solver solver):
533 self.cgrammar = c_Grammar()
535 def addRule(self, Term ntSymbol, Term rule):
537 Add ``rule`` to the set of rules corresponding to ``ntSymbol``.
539 :param ntSymbol: the non-terminal to which the rule is added.
540 :param rule: the rule to add.
542 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
544 def addAnyConstant(self, Term ntSymbol):
546 Allow ``ntSymbol`` to be an arbitrary constant.
548 :param ntSymbol: the non-terminal allowed to be constant.
550 self.cgrammar.addAnyConstant(ntSymbol.cterm)
552 def addAnyVariable(self, Term ntSymbol):
554 Allow ``ntSymbol`` to be any input variable to corresponding synth-fun/synth-inv with the same sort as ``ntSymbol``.
556 :param ntSymbol: the non-terminal allowed to be any input variable.
558 self.cgrammar.addAnyVariable(ntSymbol.cterm)
560 def addRules(self, Term ntSymbol, rules):
562 Add ``ntSymbol`` to the set of rules corresponding to ``ntSymbol``.
564 :param ntSymbol: the non-terminal to which the rules are added.
565 :param rules: the rules to add.
567 cdef vector[c_Term] crules
569 crules.push_back((<Term?> r).cterm)
570 self.cgrammar.addRules(ntSymbol.cterm, crules)
574 Encapsulation of a three-valued solver result, with explanations.
575 Wrapper class for :cpp:class:`cvc5::api::Result`.
579 # gets populated by solver
584 :return: True if Result is empty, i.e., a nullary Result, and not an actual result returned from a
585 :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` (and friends) query.
587 return self.cr.isNull()
591 :return: True if query was a satisfiable :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query.
593 return self.cr.isSat()
597 :return: True if query was an usatisfiable :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query.
599 return self.cr.isUnsat()
601 def isSatUnknown(self):
603 :return: True if query was a :cpp:func:`Solver::checkSat() <cvc5::api::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::api::Solver::checkSatAssuming>` query and cvc5 was not able to determine (un)satisfiability.
605 return self.cr.isSatUnknown()
607 def isEntailed(self):
609 :return: True if corresponding query was an entailed :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query.
611 return self.cr.isEntailed()
613 def isNotEntailed(self):
615 :return: True if corresponding query was a :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query that is not entailed.
617 return self.cr.isNotEntailed()
619 def isEntailmentUnknown(self):
621 :return: True if query was a :cpp:func:`Solver::checkEntailed() <cvc5::api::Solver::checkEntailed>` query query and cvc5 was not able to determine if it is entailed.
623 return self.cr.isEntailmentUnknown()
625 def getUnknownExplanation(self):
627 :return: an explanation for an unknown query result.
629 return UnknownExplanation(<int> self.cr.getUnknownExplanation())
631 def __eq__(self, Result other):
632 return self.cr == other.cr
634 def __ne__(self, Result other):
635 return self.cr != other.cr
638 return self.cr.toString().decode()
641 return self.cr.toString().decode()
644 cdef class RoundingMode:
646 Rounding modes for floating-point numbers.
648 For many floating-point operations, infinitely precise results may not be
649 representable with the number of available bits. Thus, the results are
650 rounded in a certain way to one of the representable floating-point numbers.
652 These rounding modes directly follow the SMT-LIB theory for floating-point
653 arithmetic, which in turn is based on IEEE Standard 754 :cite:`IEEE754`.
654 The rounding modes are specified in Sections 4.3.1 and 4.3.2 of the IEEE
657 Wrapper class for :cpp:enum:`cvc5::api::RoundingMode`.
659 cdef c_RoundingMode crm
661 def __cinit__(self, int rm):
662 # crm always assigned externally
663 self.crm = <c_RoundingMode> rm
664 self.name = __rounding_modes[rm]
666 def __eq__(self, RoundingMode other):
667 return (<int> self.crm) == (<int> other.crm)
669 def __ne__(self, RoundingMode other):
670 return not self.__eq__(other)
673 return hash((<int> self.crm, self.name))
682 cdef class UnknownExplanation:
684 Wrapper class for :cpp:enum:`cvc5::api::Result::UnknownExplanation`.
686 cdef c_UnknownExplanation cue
688 def __cinit__(self, int ue):
689 # crm always assigned externally
690 self.cue = <c_UnknownExplanation> ue
691 self.name = __unknown_explanations[ue]
693 def __eq__(self, UnknownExplanation other):
694 return (<int> self.cue) == (<int> other.cue)
696 def __ne__(self, UnknownExplanation other):
697 return not self.__eq__(other)
700 return hash((<int> self.crm, self.name))
710 """Wrapper class for :cpp:class:`cvc5::api::Solver`."""
711 cdef c_Solver* csolver
714 self.csolver = new c_Solver()
716 def __dealloc__(self):
719 def getBooleanSort(self):
720 """:return: sort Boolean
722 cdef Sort sort = Sort(self)
723 sort.csort = self.csolver.getBooleanSort()
726 def getIntegerSort(self):
727 """:return: sort Integer
729 cdef Sort sort = Sort(self)
730 sort.csort = self.csolver.getIntegerSort()
733 def getNullSort(self):
734 """:return: sort null
736 cdef Sort sort = Sort(self)
737 sort.csort = self.csolver.getNullSort()
740 def getRealSort(self):
741 """:return: sort Real
743 cdef Sort sort = Sort(self)
744 sort.csort = self.csolver.getRealSort()
747 def getRegExpSort(self):
748 """:return: sort of RegExp
750 cdef Sort sort = Sort(self)
751 sort.csort = self.csolver.getRegExpSort()
754 def getRoundingModeSort(self):
755 """:return: sort RoundingMode
757 cdef Sort sort = Sort(self)
758 sort.csort = self.csolver.getRoundingModeSort()
761 def getStringSort(self):
762 """:return: sort String
764 cdef Sort sort = Sort(self)
765 sort.csort = self.csolver.getStringSort()
768 def mkArraySort(self, Sort indexSort, Sort elemSort):
769 """Create an array sort.
771 :param indexSort: the array index sort
772 :param elemSort: the array element sort
773 :return: the array sort
775 cdef Sort sort = Sort(self)
776 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
779 def mkBitVectorSort(self, uint32_t size):
780 """Create a bit-vector sort.
782 :param size: the bit-width of the bit-vector sort
783 :return: the bit-vector sort
785 cdef Sort sort = Sort(self)
786 sort.csort = self.csolver.mkBitVectorSort(size)
789 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
790 """Create a floating-point sort.
792 :param exp: the bit-width of the exponent of the floating-point sort.
793 :param sig: the bit-width of the significand of the floating-point sort.
795 cdef Sort sort = Sort(self)
796 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
799 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
800 """Create a datatype sort.
802 :param dtypedecl: the datatype declaration from which the sort is created
803 :return: the datatype sort
805 cdef Sort sort = Sort(self)
806 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
809 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
811 Create a vector of datatype sorts using unresolved sorts. The names of
812 the datatype declarations in dtypedecls must be distinct.
814 This method is called when the DatatypeDecl objects dtypedecls have been
815 built using "unresolved" sorts.
817 We associate each sort in unresolvedSorts with exacly one datatype from
818 dtypedecls. In particular, it must have the same name as exactly one
819 datatype declaration in dtypedecls.
821 When constructing datatypes, unresolved sorts are replaced by the datatype
822 sort constructed for the datatype declaration it is associated with.
824 :param dtypedecls: the datatype declarations from which the sort is created
825 :param unresolvedSorts: the list of unresolved sorts
826 :return: the datatype sorts
828 if unresolvedSorts == None:
829 unresolvedSorts = set([])
831 assert isinstance(unresolvedSorts, set)
834 cdef vector[c_DatatypeDecl] decls
835 for decl in dtypedecls:
836 decls.push_back((<DatatypeDecl?> decl).cdd)
838 cdef c_set[c_Sort] usorts
839 for usort in unresolvedSorts:
840 usorts.insert((<Sort?> usort).csort)
842 csorts = self.csolver.mkDatatypeSorts(
843 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
851 def mkFunctionSort(self, sorts, Sort codomain):
852 """ Create function sort.
854 :param sorts: the sort of the function arguments
855 :param codomain: the sort of the function return value
856 :return: the function sort
859 cdef Sort sort = Sort(self)
860 # populate a vector with dereferenced c_Sorts
861 cdef vector[c_Sort] v
863 if isinstance(sorts, Sort):
864 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
866 elif isinstance(sorts, list):
868 v.push_back((<Sort?>s).csort)
870 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
874 def mkParamSort(self, symbolname):
875 """ Create a sort parameter.
877 :param symbol: the name of the sort
878 :return: the sort parameter
880 cdef Sort sort = Sort(self)
881 sort.csort = self.csolver.mkParamSort(symbolname.encode())
884 @expand_list_arg(num_req_args=0)
885 def mkPredicateSort(self, *sorts):
886 """Create a predicate sort.
888 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
889 :return: the predicate sort
891 cdef Sort sort = Sort(self)
892 cdef vector[c_Sort] v
894 v.push_back((<Sort?> s).csort)
895 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
898 @expand_list_arg(num_req_args=0)
899 def mkRecordSort(self, *fields):
900 """Create a record sort
902 :param fields: the list of fields of the record, as a list or as distinct arguments
903 :return: the record sort
905 cdef Sort sort = Sort(self)
906 cdef vector[pair[string, c_Sort]] v
907 cdef pair[string, c_Sort] p
911 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
913 sort.csort = self.csolver.mkRecordSort(
914 <const vector[pair[string, c_Sort]] &> v)
917 def mkSetSort(self, Sort elemSort):
918 """Create a set sort.
920 :param elemSort: the sort of the set elements
921 :return: the set sort
923 cdef Sort sort = Sort(self)
924 sort.csort = self.csolver.mkSetSort(elemSort.csort)
927 def mkBagSort(self, Sort elemSort):
928 """Create a bag sort.
930 :param elemSort: the sort of the bag elements
931 :return: the bag sort
933 cdef Sort sort = Sort(self)
934 sort.csort = self.csolver.mkBagSort(elemSort.csort)
937 def mkSequenceSort(self, Sort elemSort):
938 """Create a sequence sort.
940 :param elemSort: the sort of the sequence elements
941 :return: the sequence sort
943 cdef Sort sort = Sort(self)
944 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
947 def mkUninterpretedSort(self, str name):
948 """Create an uninterpreted sort.
950 :param symbol: the name of the sort
951 :return: the uninterpreted sort
953 cdef Sort sort = Sort(self)
954 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
957 def mkUnresolvedSort(self, str name, size_t arity = 0):
958 """Create an unresolved sort.
960 This is for creating yet unresolved sort placeholders for mutually
963 :param symbol: the name of the sort
964 :param arity: the number of sort parameters of the sort
965 :return: the unresolved sort
967 cdef Sort sort = Sort(self)
968 sort.csort = self.csolver.mkUnresolvedSort(name.encode(), arity)
971 def mkSortConstructorSort(self, str symbol, size_t arity):
972 """Create a sort constructor sort.
974 :param symbol: the symbol of the sort
975 :param arity: the arity of the sort
976 :return: the sort constructor sort
978 cdef Sort sort = Sort(self)
979 sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
982 @expand_list_arg(num_req_args=0)
983 def mkTupleSort(self, *sorts):
984 """Create a tuple sort.
986 :param sorts: of the elements of the tuple, as a list or as distinct arguments
987 :return: the tuple sort
989 cdef Sort sort = Sort(self)
990 cdef vector[c_Sort] v
992 v.push_back((<Sort?> s).csort)
993 sort.csort = self.csolver.mkTupleSort(v)
996 @expand_list_arg(num_req_args=1)
997 def mkTerm(self, kind_or_op, *args):
999 Supports the following arguments:
1001 - ``Term mkTerm(Kind kind)``
1002 - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
1003 - ``Term mkTerm(Kind kind, List[Term] children)``
1005 where ``List[Term]`` can also be comma-separated arguments
1007 cdef Term term = Term(self)
1008 cdef vector[c_Term] v
1011 if isinstance(kind_or_op, Kind):
1012 op = self.mkOp(kind_or_op)
1015 term.cterm = self.csolver.mkTerm((<Op?> op).cop)
1018 v.push_back((<Term?> a).cterm)
1019 term.cterm = self.csolver.mkTerm((<Op?> op).cop, v)
1022 def mkTuple(self, sorts, terms):
1023 """Create a tuple term. Terms are automatically converted if sorts are compatible.
1025 :param sorts: The sorts of the elements in the tuple
1026 :param terms: The elements in the tuple
1027 :return: the tuple Term
1029 cdef vector[c_Sort] csorts
1030 cdef vector[c_Term] cterms
1033 csorts.push_back((<Sort?> s).csort)
1035 cterms.push_back((<Term?> s).cterm)
1036 cdef Term result = Term(self)
1037 result.cterm = self.csolver.mkTuple(csorts, cterms)
1040 @expand_list_arg(num_req_args=0)
1041 def mkOp(self, k, *args):
1043 Supports the following uses:
1045 - ``Op mkOp(Kind kind)``
1046 - ``Op mkOp(Kind kind, Kind k)``
1047 - ``Op mkOp(Kind kind, const string& arg)``
1048 - ``Op mkOp(Kind kind, uint32_t arg)``
1049 - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
1050 - ``Op mkOp(Kind kind, [uint32_t arg0, ...])`` (used for the TupleProject kind)
1052 cdef Op op = Op(self)
1053 cdef vector[uint32_t] v
1056 op.cop = self.csolver.mkOp(<c_Kind> k.value)
1057 elif len(args) == 1:
1058 if isinstance(args[0], str):
1059 op.cop = self.csolver.mkOp(<c_Kind> k.value,
1062 elif isinstance(args[0], int):
1063 op.cop = self.csolver.mkOp(<c_Kind> k.value, <int?> args[0])
1064 elif isinstance(args[0], list):
1066 if a < 0 or a >= 2 ** 31:
1067 raise ValueError("Argument {} must fit in a uint32_t".format(a))
1069 v.push_back((<uint32_t?> a))
1070 op.cop = self.csolver.mkOp(<c_Kind> k.value, <const vector[uint32_t]&> v)
1072 raise ValueError("Unsupported signature"
1073 " mkOp: {}".format(" X ".join([str(k), str(args[0])])))
1074 elif len(args) == 2:
1075 if isinstance(args[0], int) and isinstance(args[1], int):
1076 op.cop = self.csolver.mkOp(<c_Kind> k.value, <int> args[0], <int> args[1])
1078 raise ValueError("Unsupported signature"
1079 " mkOp: {}".format(" X ".join([k, args[0], args[1]])))
1083 """Create a Boolean true constant.
1085 :return: the true constant
1087 cdef Term term = Term(self)
1088 term.cterm = self.csolver.mkTrue()
1092 """Create a Boolean false constant.
1094 :return: the false constant
1096 cdef Term term = Term(self)
1097 term.cterm = self.csolver.mkFalse()
1100 def mkBoolean(self, bint val):
1101 """Create a Boolean constant.
1103 :return: the Boolean constant
1104 :param val: the value of the constant
1106 cdef Term term = Term(self)
1107 term.cterm = self.csolver.mkBoolean(val)
1111 """Create a constant representing the number Pi.
1113 :return: a constant representing Pi
1115 cdef Term term = Term(self)
1116 term.cterm = self.csolver.mkPi()
1119 def mkInteger(self, val):
1120 """Create an integer constant.
1122 :param val: representation of the constant: either a string or integer
1123 :return: a constant of sort Integer
1125 cdef Term term = Term(self)
1126 if isinstance(val, str):
1127 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
1129 assert(isinstance(val, int))
1130 term.cterm = self.csolver.mkInteger((<int?> val))
1133 def mkReal(self, val, den=None):
1134 """Create a real constant.
1136 :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.
1137 :param den: if not None, the value is `val`/`den`
1138 :return: a real term with literal value
1140 Can be used in various forms:
1142 - Given a string ``"N/D"`` constructs the corresponding rational.
1143 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
1144 - 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``.
1145 - Given a string ``"W"`` or an integer, constructs that integer.
1146 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1148 cdef Term term = Term(self)
1150 term.cterm = self.csolver.mkReal(str(val).encode())
1152 if not isinstance(val, int) or not isinstance(den, int):
1153 raise ValueError("Expecting integers when"
1154 " constructing a rational"
1155 " but got: {}".format((val, den)))
1156 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1159 def mkRegexpAll(self):
1160 """Create a regular expression all (re.all) term.
1162 :return: the all term
1164 cdef Term term = Term(self)
1165 term.cterm = self.csolver.mkRegexpAll()
1168 def mkRegexpAllchar(self):
1169 """Create a regular expression allchar (re.allchar) term.
1171 :return: the allchar term
1173 cdef Term term = Term(self)
1174 term.cterm = self.csolver.mkRegexpAllchar()
1177 def mkRegexpNone(self):
1178 """Create a regular expression none (re.none) term.
1180 :return: the none term
1182 cdef Term term = Term(self)
1183 term.cterm = self.csolver.mkRegexpNone()
1186 def mkEmptySet(self, Sort s):
1187 """Create a constant representing an empty set of the given sort.
1189 :param sort: the sort of the set elements.
1190 :return: the empty set constant
1192 cdef Term term = Term(self)
1193 term.cterm = self.csolver.mkEmptySet(s.csort)
1196 def mkEmptyBag(self, Sort s):
1197 """Create a constant representing an empty bag of the given sort.
1199 :param sort: the sort of the bag elements.
1200 :return: the empty bag constant
1202 cdef Term term = Term(self)
1203 term.cterm = self.csolver.mkEmptyBag(s.csort)
1207 """Create a separation logic empty term.
1209 :return: the separation logic empty term
1211 cdef Term term = Term(self)
1212 term.cterm = self.csolver.mkSepEmp()
1215 def mkSepNil(self, Sort sort):
1216 """Create a separation logic nil term.
1218 :param sort: the sort of the nil term
1219 :return: the separation logic nil term
1221 cdef Term term = Term(self)
1222 term.cterm = self.csolver.mkSepNil(sort.csort)
1225 def mkString(self, str s, useEscSequences = None):
1227 Create a String constant from a `str` which may contain SMT-LIB
1228 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1230 :param s: the string this constant represents
1231 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1232 :return: the String constant
1234 cdef Term term = Term(self)
1235 cdef Py_ssize_t size
1236 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1237 if isinstance(useEscSequences, bool):
1238 term.cterm = self.csolver.mkString(
1239 s.encode(), <bint> useEscSequences)
1241 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1245 def mkEmptySequence(self, Sort sort):
1246 """Create an empty sequence of the given element sort.
1248 :param sort: The element sort of the sequence.
1249 :return: the empty sequence with given element sort.
1251 cdef Term term = Term(self)
1252 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1255 def mkUniverseSet(self, Sort sort):
1256 """Create a universe set of the given sort.
1258 :param sort: the sort of the set elements
1259 :return: the universe set constant
1261 cdef Term term = Term(self)
1262 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1265 @expand_list_arg(num_req_args=0)
1266 def mkBitVector(self, *args):
1268 Supports the following arguments:
1270 - ``Term mkBitVector(int size, int val=0)``
1271 - ``Term mkBitVector(int size, string val, int base)``
1273 :return: a bit-vector literal term
1274 :param size: an integer size.
1275 :param val: an integer representating the value, in the first form. In the second form, a string representing the value.
1276 :param base: the base of the string representation (second form only)
1278 cdef Term term = Term(self)
1280 raise ValueError("Missing arguments to mkBitVector")
1282 if not isinstance(size, int):
1284 "Invalid first argument to mkBitVector '{}', "
1285 "expected bit-vector size".format(size))
1287 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1288 elif len(args) == 2:
1290 if not isinstance(val, int):
1292 "Invalid second argument to mkBitVector '{}', "
1293 "expected integer value".format(size))
1294 term.cterm = self.csolver.mkBitVector(
1295 <uint32_t> size, <uint32_t> val)
1296 elif len(args) == 3:
1299 if not isinstance(val, str):
1301 "Invalid second argument to mkBitVector '{}', "
1302 "expected value string".format(size))
1303 if not isinstance(base, int):
1305 "Invalid third argument to mkBitVector '{}', "
1306 "expected base given as integer".format(size))
1307 term.cterm = self.csolver.mkBitVector(
1309 <const string&> str(val).encode(),
1312 raise ValueError("Unexpected inputs to mkBitVector")
1315 def mkConstArray(self, Sort sort, Term val):
1317 Create a constant array with the provided constant value stored at every
1320 :param sort: the sort of the constant array (must be an array sort)
1321 :param val: the constant value to store (must match the sort's element sort)
1322 :return: the constant array term
1324 cdef Term term = Term(self)
1325 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1328 def mkFloatingPointPosInf(self, int exp, int sig):
1329 """Create a positive infinity floating-point constant.
1331 :param exp: Number of bits in the exponent
1332 :param sig: Number of bits in the significand
1333 :return: the floating-point constant
1335 cdef Term term = Term(self)
1336 term.cterm = self.csolver.mkFloatingPointPosInf(exp, sig)
1339 def mkFloatingPointNegInf(self, int exp, int sig):
1340 """Create a negative infinity floating-point constant.
1342 :param exp: Number of bits in the exponent
1343 :param sig: Number of bits in the significand
1344 :return: the floating-point constant
1346 cdef Term term = Term(self)
1347 term.cterm = self.csolver.mkFloatingPointNegInf(exp, sig)
1350 def mkFloatingPointNaN(self, int exp, int sig):
1351 """Create a not-a-number (NaN) floating-point constant.
1353 :param exp: Number of bits in the exponent
1354 :param sig: Number of bits in the significand
1355 :return: the floating-point constant
1357 cdef Term term = Term(self)
1358 term.cterm = self.csolver.mkFloatingPointNaN(exp, sig)
1361 def mkFloatingPointPosZero(self, int exp, int sig):
1362 """Create a positive zero (+0.0) floating-point constant.
1364 :param exp: Number of bits in the exponent
1365 :param sig: Number of bits in the significand
1366 :return: the floating-point constant
1368 cdef Term term = Term(self)
1369 term.cterm = self.csolver.mkFloatingPointPosZero(exp, sig)
1372 def mkFloatingPointNegZero(self, int exp, int sig):
1373 """Create a negative zero (+0.0) floating-point constant.
1375 :param exp: Number of bits in the exponent
1376 :param sig: Number of bits in the significand
1377 :return: the floating-point constant
1379 cdef Term term = Term(self)
1380 term.cterm = self.csolver.mkFloatingPointNegZero(exp, sig)
1383 def mkRoundingMode(self, RoundingMode rm):
1384 """Create a roundingmode constant.
1386 :param rm: the floating point rounding mode this constant represents
1388 cdef Term term = Term(self)
1389 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
1392 def mkFloatingPoint(self, int exp, int sig, Term val):
1393 """Create a floating-point constant.
1395 :param exp: Size of the exponent
1396 :param sig: Size of the significand
1397 :param val: Value of the floating-point constant as a bit-vector term
1399 cdef Term term = Term(self)
1400 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1403 def mkCardinalityConstraint(self, Sort sort, int index):
1404 """Create cardinality constraint.
1406 :param sort: Sort of the constraint
1407 :param index: The upper bound for the cardinality of the sort
1409 cdef Term term = Term(self)
1410 term.cterm = self.csolver.mkCardinalityConstraint(sort.csort, index)
1413 def mkConst(self, Sort sort, symbol=None):
1415 Create (first-order) constant (0-arity function symbol).
1419 .. code-block:: smtlib
1421 ( declare-const <symbol> <sort> )
1422 ( declare-fun <symbol> ( ) <sort> )
1424 :param sort: the sort of the constant
1425 :param symbol: the name of the constant. If None, a default symbol is used.
1426 :return: the first-order constant
1428 cdef Term term = Term(self)
1430 term.cterm = self.csolver.mkConst(sort.csort)
1432 term.cterm = self.csolver.mkConst(sort.csort,
1433 (<str?> symbol).encode())
1436 def mkVar(self, Sort sort, symbol=None):
1438 Create a bound variable to be used in a binder (i.e. a quantifier, a
1439 lambda, or a witness binder).
1441 :param sort: the sort of the variable
1442 :param symbol: the name of the variable
1443 :return: the variable
1445 cdef Term term = Term(self)
1447 term.cterm = self.csolver.mkVar(sort.csort)
1449 term.cterm = self.csolver.mkVar(sort.csort,
1450 (<str?> symbol).encode())
1453 def mkDatatypeConstructorDecl(self, str name):
1455 :return: a datatype constructor declaration
1456 :param name: the constructor's name
1458 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1459 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1462 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1463 """Create a datatype declaration.
1465 :param name: the name of the datatype
1466 :param isCoDatatype: true if a codatatype is to be constructed
1467 :return: the DatatypeDecl
1469 cdef DatatypeDecl dd = DatatypeDecl(self)
1470 cdef vector[c_Sort] v
1473 if sorts_or_bool is None and isCoDatatype is None:
1474 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1475 elif sorts_or_bool is not None and isCoDatatype is None:
1476 if isinstance(sorts_or_bool, bool):
1477 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1478 <bint> sorts_or_bool)
1479 elif isinstance(sorts_or_bool, Sort):
1480 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1481 (<Sort> sorts_or_bool).csort)
1482 elif isinstance(sorts_or_bool, list):
1483 for s in sorts_or_bool:
1484 v.push_back((<Sort?> s).csort)
1485 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1486 <const vector[c_Sort]&> v)
1488 raise ValueError("Unhandled second argument type {}"
1489 .format(type(sorts_or_bool)))
1490 elif sorts_or_bool is not None and isCoDatatype is not None:
1491 if isinstance(sorts_or_bool, Sort):
1492 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1493 (<Sort> sorts_or_bool).csort,
1494 <bint> isCoDatatype)
1495 elif isinstance(sorts_or_bool, list):
1496 for s in sorts_or_bool:
1497 v.push_back((<Sort?> s).csort)
1498 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1499 <const vector[c_Sort]&> v,
1500 <bint> isCoDatatype)
1502 raise ValueError("Unhandled second argument type {}"
1503 .format(type(sorts_or_bool)))
1505 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1512 def simplify(self, Term t):
1514 Simplify a formula without doing "much" work. Does not involve the
1515 SAT Engine in the simplification, but uses the current definitions,
1516 assertions, and the current partial model, if one has been constructed.
1517 It also involves theory normalization.
1519 :param t: the formula to simplify
1520 :return: the simplified formula
1522 cdef Term term = Term(self)
1523 term.cterm = self.csolver.simplify(t.cterm)
1526 def assertFormula(self, Term term):
1527 """ Assert a formula
1531 .. code-block:: smtlib
1535 :param term: the formula to assert
1537 self.csolver.assertFormula(term.cterm)
1541 Check satisfiability.
1545 .. code-block:: smtlib
1549 :return: the result of the satisfiability check.
1551 cdef Result r = Result()
1552 r.cr = self.csolver.checkSat()
1555 def mkSygusGrammar(self, boundVars, ntSymbols):
1557 Create a SyGuS grammar. The first non-terminal is treated as the
1558 starting non-terminal, so the order of non-terminals matters.
1560 :param boundVars: the parameters to corresponding synth-fun/synth-inv
1561 :param ntSymbols: the pre-declaration of the non-terminal symbols
1562 :return: the grammar
1564 cdef Grammar grammar = Grammar(self)
1565 cdef vector[c_Term] bvc
1566 cdef vector[c_Term] ntc
1567 for bv in boundVars:
1568 bvc.push_back((<Term?> bv).cterm)
1569 for nt in ntSymbols:
1570 ntc.push_back((<Term?> nt).cterm)
1571 grammar.cgrammar = self.csolver.mkSygusGrammar(<const vector[c_Term]&> bvc, <const vector[c_Term]&> ntc)
1574 def mkSygusVar(self, Sort sort, str symbol=""):
1575 """Append symbol to the current list of universal variables.
1579 .. code-block:: smtlib
1581 ( declare-var <symbol> <sort> )
1583 :param sort: the sort of the universal variable
1584 :param symbol: the name of the universal variable
1585 :return: the universal variable
1587 cdef Term term = Term(self)
1588 term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
1591 def addSygusConstraint(self, Term t):
1593 Add a formula to the set of SyGuS constraints.
1597 .. code-block:: smtlib
1599 ( constraint <term> )
1601 :param term: the formula to add as a constraint
1603 self.csolver.addSygusConstraint(t.cterm)
1605 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1607 Add a set of SyGuS constraints to the current state that correspond to an
1608 invariant synthesis problem.
1612 .. code-block:: smtlib
1614 ( inv-constraint <inv> <pre> <trans> <post> )
1616 :param inv: the function-to-synthesize
1617 :param pre: the pre-condition
1618 :param trans: the transition relation
1619 :param post: the post-condition
1621 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1623 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1625 Synthesize n-ary function following specified syntactic constraints.
1629 .. code-block:: smtlib
1631 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1633 :param symbol: the name of the function
1634 :param boundVars: the parameters to this function
1635 :param sort: the sort of the return value of this function
1636 :param grammar: the syntactic constraints
1637 :return: the function
1639 cdef Term term = Term(self)
1640 cdef vector[c_Term] v
1641 for bv in bound_vars:
1642 v.push_back((<Term?> bv).cterm)
1644 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1646 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1649 def checkSynth(self):
1651 Try to find a solution for the synthesis conjecture corresponding to the
1652 current list of functions-to-synthesize, universal variables and
1657 .. code-block:: smtlib
1661 :return: the result of the synthesis conjecture.
1663 cdef Result r = Result()
1664 r.cr = self.csolver.checkSynth()
1667 def checkSynthNext(self):
1669 Try to find a next solution for the synthesis conjecture corresponding
1670 to the current list of functions-to-synthesize, universal variables and
1671 constraints. Must be called immediately after a successful call to
1672 check-synth or check-synth-next. Requires incremental mode.
1676 .. code-block:: smtlib
1680 :return: the result of the check, which is unsat if the check succeeded,
1681 in which case solutions are available via getSynthSolutions.
1683 cdef Result r = Result()
1684 r.cr = self.csolver.checkSynthNext()
1687 def getSynthSolution(self, Term term):
1689 Get the synthesis solution of the given term. This method should be
1690 called immediately after the solver answers unsat for sygus input.
1692 :param term: the term for which the synthesis solution is queried
1693 :return: the synthesis solution of the given term
1695 cdef Term t = Term(self)
1696 t.cterm = self.csolver.getSynthSolution(term.cterm)
1699 def getSynthSolutions(self, list terms):
1701 Get the synthesis solutions of the given terms. This method should be
1702 called immediately after the solver answers unsat for sygus input.
1704 :param terms: the terms for which the synthesis solutions is queried
1705 :return: the synthesis solutions of the given terms
1708 cdef vector[c_Term] vec
1710 vec.push_back((<Term?> t).cterm)
1711 cresult = self.csolver.getSynthSolutions(vec)
1719 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1721 Synthesize invariant.
1725 .. code-block:: smtlib
1727 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1729 :param symbol: the name of the invariant
1730 :param boundVars: the parameters to this invariant
1731 :param grammar: the syntactic constraints
1732 :return: the invariant
1734 cdef Term term = Term(self)
1735 cdef vector[c_Term] v
1736 for bv in bound_vars:
1737 v.push_back((<Term?> bv).cterm)
1739 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1741 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1744 @expand_list_arg(num_req_args=0)
1745 def checkSatAssuming(self, *assumptions):
1746 """ Check satisfiability assuming the given formula.
1750 .. code-block:: smtlib
1752 ( check-sat-assuming ( <prop_literal> ) )
1754 :param assumptions: the formulas to assume, as a list or as distinct arguments
1755 :return: the result of the satisfiability check.
1757 cdef Result r = Result()
1758 # used if assumptions is a list of terms
1759 cdef vector[c_Term] v
1760 for a in assumptions:
1761 v.push_back((<Term?> a).cterm)
1762 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1765 @expand_list_arg(num_req_args=0)
1766 def checkEntailed(self, *assumptions):
1767 """Check entailment of the given formula w.r.t. the current set of assertions.
1769 :param terms: the formulas to check entailment for, as a list or as distinct arguments
1770 :return: the result of the entailment check.
1772 cdef Result r = Result()
1773 # used if assumptions is a list of terms
1774 cdef vector[c_Term] v
1775 for a in assumptions:
1776 v.push_back((<Term?> a).cterm)
1777 r.cr = self.csolver.checkEntailed(<const vector[c_Term]&> v)
1780 @expand_list_arg(num_req_args=1)
1781 def declareDatatype(self, str symbol, *ctors):
1783 Create datatype sort.
1787 .. code-block:: smtlib
1789 ( declare-datatype <symbol> <datatype_decl> )
1791 :param symbol: the name of the datatype sort
1792 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1793 :return: the datatype sort
1795 cdef Sort sort = Sort(self)
1796 cdef vector[c_DatatypeConstructorDecl] v
1799 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1800 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1803 def declareFun(self, str symbol, list sorts, Sort sort):
1804 """Declare n-ary function symbol.
1808 .. code-block:: smtlib
1810 ( declare-fun <symbol> ( <sort>* ) <sort> )
1812 :param symbol: the name of the function
1813 :param sorts: the sorts of the parameters to this function
1814 :param sort: the sort of the return value of this function
1815 :return: the function
1817 cdef Term term = Term(self)
1818 cdef vector[c_Sort] v
1820 v.push_back((<Sort?> s).csort)
1821 term.cterm = self.csolver.declareFun(symbol.encode(),
1822 <const vector[c_Sort]&> v,
1826 def declareSort(self, str symbol, int arity):
1827 """Declare uninterpreted sort.
1831 .. code-block:: smtlib
1833 ( declare-sort <symbol> <numeral> )
1835 :param symbol: the name of the sort
1836 :param arity: the arity of the sort
1839 cdef Sort sort = Sort(self)
1840 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1843 def defineFun(self, str symbol, list bound_vars, Sort sort, Term term, glbl=False):
1844 """Define n-ary function.
1848 .. code-block:: smtlib
1850 ( define-fun <function_def> )
1852 :param symbol: the name of the function
1853 :param bound_vars: the parameters to this function
1854 :param sort: the sort of the return value of this function
1855 :param term: the function body
1856 :param glbl: determines whether this definition is global (i.e. persists when popping the context)
1857 :return: the function
1859 cdef Term fun = Term(self)
1860 cdef vector[c_Term] v
1861 for bv in bound_vars:
1862 v.push_back((<Term?> bv).cterm)
1864 fun.cterm = self.csolver.defineFun(symbol.encode(),
1865 <const vector[c_Term] &> v,
1871 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1872 """Define recursive functions.
1876 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1877 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1882 .. code-block:: smtlib
1884 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1886 Create elements of parameter ``funs`` with mkConst().
1888 :param funs: the sorted functions
1889 :param bound_vars: the list of parameters to the functions
1890 :param terms: the list of function bodies of the functions
1891 :param global: determines whether this definition is global (i.e. persists when popping the context)
1892 :return: the function
1894 cdef Term term = Term(self)
1895 cdef vector[c_Term] v
1896 for bv in bound_vars:
1897 v.push_back((<Term?> bv).cterm)
1900 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1901 <const vector[c_Term] &> v,
1902 (<Sort?> sort_or_term).csort,
1906 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1907 <const vector[c_Term]&> v,
1908 (<Term?> sort_or_term).cterm,
1913 def defineFunsRec(self, funs, bound_vars, terms):
1914 """Define recursive functions.
1918 .. code-block:: smtlib
1920 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1922 Create elements of parameter ``funs`` with mkConst().
1924 :param funs: the sorted functions
1925 :param bound_vars: the list of parameters to the functions
1926 :param terms: the list of function bodies of the functions
1927 :param global: determines whether this definition is global (i.e. persists when popping the context)
1928 :return: the function
1930 cdef vector[c_Term] vf
1931 cdef vector[vector[c_Term]] vbv
1932 cdef vector[c_Term] vt
1935 vf.push_back((<Term?> f).cterm)
1937 cdef vector[c_Term] temp
1938 for v in bound_vars:
1940 temp.push_back((<Term?> t).cterm)
1945 vf.push_back((<Term?> t).cterm)
1947 def getAssertions(self):
1948 """Get the list of asserted formulas.
1952 .. code-block:: smtlib
1956 :return: the list of asserted formulas
1959 for a in self.csolver.getAssertions():
1962 assertions.append(term)
1965 def getInfo(self, str flag):
1966 """Get info from the solver.
1970 .. code-block:: smtlib
1972 ( get-info <info_flag> )
1974 :param flag: the info flag
1977 return self.csolver.getInfo(flag.encode())
1979 def getOption(self, str option):
1980 """Get the value of a given option.
1984 .. code-block:: smtlib
1986 ( get-option <keyword> )
1988 :param option: the option for which the value is queried
1989 :return: a string representation of the option value
1991 return self.csolver.getOption(option.encode())
1993 def getUnsatAssumptions(self):
1995 Get the set of unsat ("failed") assumptions.
1999 .. code-block:: smtlib
2001 ( get-unsat-assumptions )
2003 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
2005 :return: the set of unsat assumptions.
2008 for a in self.csolver.getUnsatAssumptions():
2011 assumptions.append(term)
2014 def getUnsatCore(self):
2015 """Get the unsatisfiable core.
2019 .. code-block:: smtlib
2023 Requires to enable option :ref:`produce-unsat-cores <lbl-option-produce-unsat-cores>`.
2025 :return: a set of terms representing the unsatisfiable core
2028 for a in self.csolver.getUnsatCore():
2034 def getValue(self, Term t):
2035 """Get the value of the given term in the current model.
2039 .. code-block:: smtlib
2041 ( get-value ( <term> ) )
2043 :param term: the term for which the value is queried
2044 :return: the value of the given term
2046 cdef Term term = Term(self)
2047 term.cterm = self.csolver.getValue(t.cterm)
2050 def getModelDomainElements(self, Sort s):
2052 Get the domain elements of uninterpreted sort s in the current model. The
2053 current model interprets s as the finite sort whose domain elements are
2054 given in the return value of this method.
2056 :param s: The uninterpreted sort in question
2057 :return: the domain elements of s in the current model
2060 cresult = self.csolver.getModelDomainElements(s.csort)
2067 def isModelCoreSymbol(self, Term v):
2069 This returns false if the model value of free constant v was not
2070 essential for showing the satisfiability of the last call to checkSat
2071 using the current model. This method will only return false (for any v)
2072 if the model-cores option has been set.
2074 :param v: The term in question
2075 :return: true if v is a model core symbol
2077 return self.csolver.isModelCoreSymbol(v.cterm)
2079 def getValueSepHeap(self):
2080 """When using separation logic, obtain the term for the heap.
2082 :return: The term for the heap
2084 cdef Term term = Term(self)
2085 term.cterm = self.csolver.getValueSepHeap()
2088 def getValueSepNil(self):
2089 """When using separation logic, obtain the term for nil.
2091 :return: The term for nil
2093 cdef Term term = Term(self)
2094 term.cterm = self.csolver.getValueSepNil()
2097 def declareSepHeap(self, Sort locType, Sort dataType):
2099 When using separation logic, this sets the location sort and the
2100 datatype sort to the given ones. This method should be invoked exactly
2101 once, before any separation logic constraints are provided.
2103 :param locSort: The location sort of the heap
2104 :param dataSort: The data sort of the heap
2106 self.csolver.declareSepHeap(locType.csort, dataType.csort)
2108 def declarePool(self, str symbol, Sort sort, initValue):
2109 """Declare a symbolic pool of terms with the given initial value.
2113 .. code-block:: smtlib
2115 ( declare-pool <symbol> <sort> ( <term>* ) )
2117 :param symbol: The name of the pool
2118 :param sort: The sort of the elements of the pool.
2119 :param initValue: The initial value of the pool
2121 cdef Term term = Term(self)
2122 cdef vector[c_Term] niv
2124 niv.push_back((<Term?> v).cterm)
2125 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
2128 def pop(self, nscopes=1):
2129 """Pop ``nscopes`` level(s) from the assertion stack.
2133 .. code-block:: smtlib
2137 :param nscopes: the number of levels to pop
2139 self.csolver.pop(nscopes)
2141 def push(self, nscopes=1):
2142 """ Push ``nscopes`` level(s) to the assertion stack.
2146 .. code-block:: smtlib
2150 :param nscopes: the number of levels to push
2152 self.csolver.push(nscopes)
2154 def resetAssertions(self):
2156 Remove all assertions.
2160 .. code-block:: smtlib
2162 ( reset-assertions )
2165 self.csolver.resetAssertions()
2167 def setInfo(self, str keyword, str value):
2172 .. code-block:: smtlib
2174 ( set-info <attribute> )
2176 :param keyword: the info flag
2177 :param value: the value of the info flag
2179 self.csolver.setInfo(keyword.encode(), value.encode())
2181 def setLogic(self, str logic):
2186 .. code-block:: smtlib
2188 ( set-logic <symbol> )
2190 :param logic: the logic to set
2192 self.csolver.setLogic(logic.encode())
2194 def setOption(self, str option, str value):
2199 .. code-block:: smtlib
2201 ( set-option <option> )
2203 :param option: the option name
2204 :param value: the option value
2206 self.csolver.setOption(option.encode(), value.encode())
2208 def getInterpolant(self, Term conj, *args):
2209 """Get an interpolant.
2213 .. code-block:: smtlib
2215 ( get-interpol <conj> )
2216 ( get-interpol <conj> <grammar> )
2218 Requires option :ref:`produce-interpols <lbl-option-produce-interpols>` to be set to a mode different from `none`.
2220 Supports the following variants:
2222 - ``bool getInteprolant(Term conj, Term output)``
2223 - ``bool getInteprolant(Term conj, Grammar grammar, Term output)``
2225 :param conj: the conjecture term
2226 :param output: the term where the result will be stored
2227 :param grammar: a grammar for the inteprolant
2228 :return: True iff an interpolant was found
2232 assert isinstance(args[0], Term)
2233 result = self.csolver.getInterpolant(conj.cterm, (<Term ?> args[0]).cterm)
2235 assert len(args) == 2
2236 assert isinstance(args[0], Grammar)
2237 assert isinstance(args[1], Term)
2238 result = self.csolver.getInterpolant(conj.cterm, (<Grammar ?> args[0]).cgrammar, (<Term ?> args[1]).cterm)
2242 def getInterpolantNext(self, Term output):
2244 Get the next interpolant. Can only be called immediately after
2245 a succesful call to get-interpol or get-interpol-next.
2246 Is guaranteed to produce a syntactically different interpolant wrt the
2247 last returned interpolant if successful.
2251 .. code-block:: smtlib
2253 ( get-interpol-next )
2255 Requires to enable incremental mode, and
2256 option :ref:`produce-interpols <lbl-option-produce-interpols>` to be set to a mode different from `none`.
2258 :param output: the term where the result will be stored
2259 :return: True iff an interpolant was found
2261 result = self.csolver.getInterpolantNext(output.cterm)
2264 def getAbduct(self, Term conj, *args):
2269 .. code-block:: smtlib
2271 ( get-abduct <conj> )
2272 ( get-abduct <conj> <grammar> )
2274 Requires to enable option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2276 Supports the following variants:
2278 - ``bool getAbduct(Term conj, Term output)``
2279 - ``bool getAbduct(Term conj, Grammar grammar, Term output)``
2281 :param conj: the conjecture term
2282 :param output: the term where the result will be stored
2283 :param grammar: a grammar for the abduct
2284 :return: True iff an abduct was found
2288 assert isinstance(args[0], Term)
2289 result = self.csolver.getAbduct(conj.cterm, (<Term ?> args[0]).cterm)
2291 assert len(args) == 2
2292 assert isinstance(args[0], Grammar)
2293 assert isinstance(args[1], Term)
2294 result = self.csolver.getAbduct(conj.cterm, (<Grammar ?> args[0]).cgrammar, (<Term ?> args[1]).cterm)
2297 def getAbductNext(self, Term output):
2299 Get the next abduct. Can only be called immediately after
2300 a succesful call to get-abduct or get-abduct-next.
2301 Is guaranteed to produce a syntactically different abduct wrt the
2302 last returned abduct if successful.
2306 .. code-block:: smtlib
2310 Requires to enable incremental mode, and
2311 option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2312 :param output: the term where the result will be stored
2313 :return: True iff an abduct was found
2315 result = self.csolver.getAbductNext(output.cterm)
2322 The sort of a cvc5 term.
2326 def __cinit__(self, Solver solver):
2327 # csort always set by Solver
2328 self.solver = solver
2330 def __eq__(self, Sort other):
2331 return self.csort == other.csort
2333 def __ne__(self, Sort other):
2334 return self.csort != other.csort
2336 def __lt__(self, Sort other):
2337 return self.csort < other.csort
2339 def __gt__(self, Sort other):
2340 return self.csort > other.csort
2342 def __le__(self, Sort other):
2343 return self.csort <= other.csort
2345 def __ge__(self, Sort other):
2346 return self.csort >= other.csort
2349 return self.csort.toString().decode()
2352 return self.csort.toString().decode()
2355 return csorthash(self.csort)
2357 def hasSymbol(self):
2358 """:return: True iff this sort has a symbol."""
2359 return self.csort.hasSymbol()
2361 def getSymbol(self):
2363 Asserts :py:meth:`hasSymbol()`.
2365 :return: the raw symbol of the sort.
2367 return self.csort.getSymbol().decode()
2370 """:return: True if this Sort is a null sort."""
2371 return self.csort.isNull()
2373 def isBoolean(self):
2375 Is this a Boolean sort?
2377 :return: True if the sort is the Boolean sort.
2379 return self.csort.isBoolean()
2381 def isInteger(self):
2383 Is this an integer sort?
2385 :return: True if the sort is the integer sort.
2387 return self.csort.isInteger()
2391 Is this a real sort?
2393 :return: True if the sort is the real sort.
2395 return self.csort.isReal()
2399 Is this a string sort?
2401 :return: True if the sort is the string sort.
2403 return self.csort.isString()
2407 Is this a regexp sort?
2409 :return: True if the sort is the regexp sort.
2411 return self.csort.isRegExp()
2413 def isRoundingMode(self):
2415 Is this a rounding mode sort?
2417 :return: True if the sort is the rounding mode sort.
2419 return self.csort.isRoundingMode()
2421 def isBitVector(self):
2423 Is this a bit-vector sort?
2425 :return: True if the sort is a bit-vector sort.
2427 return self.csort.isBitVector()
2429 def isFloatingPoint(self):
2431 Is this a floating-point sort?
2433 :return: True if the sort is a bit-vector sort.
2435 return self.csort.isFloatingPoint()
2437 def isDatatype(self):
2439 Is this a datatype sort?
2441 :return: True if the sort is a datatype sort.
2443 return self.csort.isDatatype()
2445 def isParametricDatatype(self):
2447 Is this a parametric datatype sort?
2449 :return: True if the sort is a parametric datatype sort.
2451 return self.csort.isParametricDatatype()
2453 def isConstructor(self):
2455 Is this a constructor sort?
2457 :return: True if the sort is a constructor sort.
2459 return self.csort.isConstructor()
2461 def isSelector(self):
2463 Is this a selector sort?
2465 :return: True if the sort is a selector sort.
2467 return self.csort.isSelector()
2471 Is this a tester sort?
2473 :return: True if the sort is a selector sort.
2475 return self.csort.isTester()
2477 def isUpdater(self):
2479 Is this a datatype updater sort?
2481 :return: True if the sort is a datatype updater sort.
2483 return self.csort.isUpdater()
2485 def isFunction(self):
2487 Is this a function sort?
2489 :return: True if the sort is a function sort.
2491 return self.csort.isFunction()
2493 def isPredicate(self):
2495 Is this a predicate sort?
2496 That is, is this a function sort mapping to Boolean? All predicate
2497 sorts are also function sorts.
2499 :return: True if the sort is a predicate sort.
2501 return self.csort.isPredicate()
2505 Is this a tuple sort?
2507 :return: True if the sort is a tuple sort.
2509 return self.csort.isTuple()
2513 Is this a record sort?
2515 :return: True if the sort is a record sort.
2517 return self.csort.isRecord()
2521 Is this an array sort?
2523 :return: True if the sort is an array sort.
2525 return self.csort.isArray()
2531 :return: True if the sort is a set sort.
2533 return self.csort.isSet()
2539 :return: True if the sort is a bag sort.
2541 return self.csort.isBag()
2543 def isSequence(self):
2545 Is this a sequence sort?
2547 :return: True if the sort is a sequence sort.
2549 return self.csort.isSequence()
2551 def isUninterpretedSort(self):
2553 Is this a sort uninterpreted?
2555 :return: True if the sort is uninterpreted.
2557 return self.csort.isUninterpretedSort()
2559 def isSortConstructor(self):
2561 Is this a sort constructor kind?
2563 :return: True if this a sort constructor kind.
2565 return self.csort.isSortConstructor()
2567 def isFirstClass(self):
2569 Is this a first-class sort?
2570 First-class sorts are sorts for which:
2572 1. we handle equalities between terms of that type, and
2573 2. they are allowed to be parameters of parametric sorts
2574 (e.g. index or element sorts of arrays).
2576 Examples of sorts that are not first-class include sort constructor
2577 sorts and regular expression sorts.
2579 :return: True if the sort is a first-class sort.
2581 return self.csort.isFirstClass()
2583 def isFunctionLike(self):
2585 Is this a function-LIKE sort?
2587 Anything function-like except arrays (e.g., datatype selectors) is
2588 considered a function here. Function-like terms can not be the argument
2589 or return value for any term that is function-like.
2590 This is mainly to avoid higher order.
2592 .. note:: Arrays are explicitly not considered function-like here.
2594 :return: True if this is a function-like sort
2596 return self.csort.isFunctionLike()
2598 def isSubsortOf(self, Sort sort):
2600 Is this sort a subsort of the given sort?
2602 :return: True if this sort is a subsort of s
2604 return self.csort.isSubsortOf(sort.csort)
2606 def getDatatype(self):
2608 :return: the underlying datatype of a datatype sort
2610 cdef Datatype d = Datatype(self.solver)
2611 d.cd = self.csort.getDatatype()
2614 def instantiate(self, params):
2616 Instantiate a parameterized datatype/sort sort.
2617 Create sorts parameter with :py:meth:`Solver.mkParamSort()`
2619 :param params: the list of sort parameters to instantiate with
2621 cdef Sort sort = Sort(self.solver)
2622 cdef vector[c_Sort] v
2624 v.push_back((<Sort?> s).csort)
2625 sort.csort = self.csort.instantiate(v)
2628 def substitute(self, sort_or_list_1, sort_or_list_2):
2630 Substitution of Sorts.
2632 :param sort_or_list_1: the subsort or subsorts to be substituted within this sort.
2633 :param sort_or_list_2: the sort or list of sorts replacing the substituted subsort.
2635 Note that this replacement is applied during a pre-order traversal and
2636 only once to the sort. It is not run until fix point. In the case that
2637 sort_or_list_1 contains duplicates, the replacement earliest in the list
2641 (Array A B) .substitute([A, C], [(Array C D), (Array A B)]) will
2642 return (Array (Array C D) B).
2645 # The resulting sort after substitution
2646 cdef Sort sort = Sort(self.solver)
2647 # lists for substitutions
2648 cdef vector[c_Sort] ces
2649 cdef vector[c_Sort] creplacements
2651 # normalize the input parameters to be lists
2652 if isinstance(sort_or_list_1, list):
2653 assert isinstance(sort_or_list_2, list)
2655 replacements = sort_or_list_2
2656 if len(es) != len(replacements):
2657 raise RuntimeError("Expecting list inputs to substitute to "
2658 "have the same length but got: "
2659 "{} and {}".format(len(es), len(replacements)))
2661 for e, r in zip(es, replacements):
2662 ces.push_back((<Sort?> e).csort)
2663 creplacements.push_back((<Sort?> r).csort)
2666 # add the single elements to the vectors
2667 ces.push_back((<Sort?> sort_or_list_1).csort)
2668 creplacements.push_back((<Sort?> sort_or_list_2).csort)
2670 # call the API substitute method with lists
2671 sort.csort = self.csort.substitute(ces, creplacements)
2675 def getConstructorArity(self):
2677 :return: the arity of a constructor sort.
2679 return self.csort.getConstructorArity()
2681 def getConstructorDomainSorts(self):
2683 :return: the domain sorts of a constructor sort
2686 for s in self.csort.getConstructorDomainSorts():
2687 sort = Sort(self.solver)
2689 domain_sorts.append(sort)
2692 def getConstructorCodomainSort(self):
2694 :return: the codomain sort of a constructor sort
2696 cdef Sort sort = Sort(self.solver)
2697 sort.csort = self.csort.getConstructorCodomainSort()
2700 def getSelectorDomainSort(self):
2702 :return: the domain sort of a selector sort
2704 cdef Sort sort = Sort(self.solver)
2705 sort.csort = self.csort.getSelectorDomainSort()
2708 def getSelectorCodomainSort(self):
2710 :return: the codomain sort of a selector sort
2712 cdef Sort sort = Sort(self.solver)
2713 sort.csort = self.csort.getSelectorCodomainSort()
2716 def getTesterDomainSort(self):
2718 :return: the domain sort of a tester sort
2720 cdef Sort sort = Sort(self.solver)
2721 sort.csort = self.csort.getTesterDomainSort()
2724 def getTesterCodomainSort(self):
2726 :return: the codomain sort of a tester sort, which is the Boolean sort
2728 cdef Sort sort = Sort(self.solver)
2729 sort.csort = self.csort.getTesterCodomainSort()
2732 def getFunctionArity(self):
2734 :return: the arity of a function sort
2736 return self.csort.getFunctionArity()
2738 def getFunctionDomainSorts(self):
2740 :return: the domain sorts of a function sort
2743 for s in self.csort.getFunctionDomainSorts():
2744 sort = Sort(self.solver)
2746 domain_sorts.append(sort)
2749 def getFunctionCodomainSort(self):
2751 :return: the codomain sort of a function sort
2753 cdef Sort sort = Sort(self.solver)
2754 sort.csort = self.csort.getFunctionCodomainSort()
2757 def getArrayIndexSort(self):
2759 :return: the array index sort of an array sort
2761 cdef Sort sort = Sort(self.solver)
2762 sort.csort = self.csort.getArrayIndexSort()
2765 def getArrayElementSort(self):
2767 :return: the array element sort of an array sort
2769 cdef Sort sort = Sort(self.solver)
2770 sort.csort = self.csort.getArrayElementSort()
2773 def getSetElementSort(self):
2775 :return: the element sort of a set sort
2777 cdef Sort sort = Sort(self.solver)
2778 sort.csort = self.csort.getSetElementSort()
2781 def getBagElementSort(self):
2783 :return: the element sort of a bag sort
2785 cdef Sort sort = Sort(self.solver)
2786 sort.csort = self.csort.getBagElementSort()
2789 def getSequenceElementSort(self):
2791 :return: the element sort of a sequence sort
2793 cdef Sort sort = Sort(self.solver)
2794 sort.csort = self.csort.getSequenceElementSort()
2797 def getUninterpretedSortName(self):
2799 :return: the name of an uninterpreted sort
2801 return self.csort.getUninterpretedSortName().decode()
2803 def isUninterpretedSortParameterized(self):
2805 :return: True if an uninterpreted sort is parameterized
2807 return self.csort.isUninterpretedSortParameterized()
2809 def getUninterpretedSortParamSorts(self):
2811 :return: the parameter sorts of an uninterpreted sort
2814 for s in self.csort.getUninterpretedSortParamSorts():
2815 sort = Sort(self.solver)
2817 param_sorts.append(sort)
2820 def getSortConstructorName(self):
2822 :return: the name of a sort constructor sort
2824 return self.csort.getSortConstructorName().decode()
2826 def getSortConstructorArity(self):
2828 :return: the arity of a sort constructor sort
2830 return self.csort.getSortConstructorArity()
2832 def getBitVectorSize(self):
2834 :return: the bit-width of the bit-vector sort
2836 return self.csort.getBitVectorSize()
2838 def getFloatingPointExponentSize(self):
2840 :return: the bit-width of the exponent of the floating-point sort
2842 return self.csort.getFloatingPointExponentSize()
2844 def getFloatingPointSignificandSize(self):
2846 :return: the width of the significand of the floating-point sort
2848 return self.csort.getFloatingPointSignificandSize()
2850 def getDatatypeParamSorts(self):
2852 Return the parameters of a parametric datatype sort. If this sort
2853 is a non-instantiated parametric datatype, this returns the
2854 parameter sorts of the underlying datatype. If this sort is an
2855 instantiated parametric datatype, then this returns the sort
2856 parameters that were used to construct the sort via
2857 :py:meth:`instantiate()`.
2859 :return: the parameter sorts of a parametric datatype sort
2862 for s in self.csort.getDatatypeParamSorts():
2863 sort = Sort(self.solver)
2865 param_sorts.append(sort)
2868 def getDatatypeArity(self):
2870 :return: the arity of a datatype sort
2872 return self.csort.getDatatypeArity()
2874 def getTupleLength(self):
2876 :return: the length of a tuple sort
2878 return self.csort.getTupleLength()
2880 def getTupleSorts(self):
2882 :return: the element sorts of a tuple sort
2885 for s in self.csort.getTupleSorts():
2886 sort = Sort(self.solver)
2888 tuple_sorts.append(sort)
2895 Wrapper class for :cpp:class:`cvc5::api::Term`.
2899 def __cinit__(self, Solver solver):
2900 # cterm always set in the Solver object
2901 self.solver = solver
2903 def __eq__(self, Term other):
2904 return self.cterm == other.cterm
2906 def __ne__(self, Term other):
2907 return self.cterm != other.cterm
2909 def __lt__(self, Term other):
2910 return self.cterm < other.cterm
2912 def __gt__(self, Term other):
2913 return self.cterm > other.cterm
2915 def __le__(self, Term other):
2916 return self.cterm <= other.cterm
2918 def __ge__(self, Term other):
2919 return self.cterm >= other.cterm
2921 def __getitem__(self, int index):
2922 cdef Term term = Term(self.solver)
2924 term.cterm = self.cterm[index]
2926 raise ValueError("Expecting a non-negative integer or string")
2930 return self.cterm.toString().decode()
2933 return self.cterm.toString().decode()
2936 for ci in self.cterm:
2937 term = Term(self.solver)
2942 return ctermhash(self.cterm)
2944 def getNumChildren(self):
2945 """:return: the number of children of this term."""
2946 return self.cterm.getNumChildren()
2949 """:return: the id of this term."""
2950 return self.cterm.getId()
2953 """:return: the :py:class:`cvc5.Kind` of this term."""
2954 return Kind(<int> self.cterm.getKind())
2957 """:return: the :py:class:`cvc5.Sort` of this term."""
2958 cdef Sort sort = Sort(self.solver)
2959 sort.csort = self.cterm.getSort()
2962 def substitute(self, term_or_list_1, term_or_list_2):
2964 :return: the result of simultaneously replacing the term(s) stored in ``term_or_list_1`` by the term(s) stored in ``term_or_list_2`` in this term.
2966 Note that this replacement is applied during a pre-order traversal and
2967 only once to the term. It is not run until fix point. In the case that
2968 terms contains duplicates, the replacement earliest in the list takes
2969 priority. For example, calling substitute on f(x,y) with
2970 term_or_list_1 = [ x, z ], term_or_list_2 = [ g(z), w ]
2971 results in the term f(g(z),y).
2973 # The resulting term after substitution
2974 cdef Term term = Term(self.solver)
2975 # lists for substitutions
2976 cdef vector[c_Term] ces
2977 cdef vector[c_Term] creplacements
2979 # normalize the input parameters to be lists
2980 if isinstance(term_or_list_1, list):
2981 assert isinstance(term_or_list_2, list)
2983 replacements = term_or_list_2
2984 if len(es) != len(replacements):
2985 raise RuntimeError("Expecting list inputs to substitute to "
2986 "have the same length but got: "
2987 "{} and {}".format(len(es), len(replacements)))
2989 for e, r in zip(es, replacements):
2990 ces.push_back((<Term?> e).cterm)
2991 creplacements.push_back((<Term?> r).cterm)
2994 # add the single elements to the vectors
2995 ces.push_back((<Term?> term_or_list_1).cterm)
2996 creplacements.push_back((<Term?> term_or_list_2).cterm)
2998 # call the API substitute method with lists
2999 term.cterm = self.cterm.substitute(ces, creplacements)
3003 """:return: True iff this term has an operator."""
3004 return self.cterm.hasOp()
3008 .. note:: This is safe to call when :py:meth:`hasOp()` returns True.
3010 :return: the :py:class:`cvc5.Op` used to create this Term.
3012 cdef Op op = Op(self.solver)
3013 op.cop = self.cterm.getOp()
3016 def hasSymbol(self):
3017 """:return: True iff this term has a symbol."""
3018 return self.cterm.hasSymbol()
3020 def getSymbol(self):
3022 Asserts :py:meth:`hasSymbol()`.
3024 :return: the raw symbol of the term.
3026 return self.cterm.getSymbol().decode()
3029 """:return: True iff this term is a null term."""
3030 return self.cterm.isNull()
3036 :return: the Boolean negation of this term.
3038 cdef Term term = Term(self.solver)
3039 term.cterm = self.cterm.notTerm()
3042 def andTerm(self, Term t):
3046 :param t: a Boolean term
3047 :return: the conjunction of this term and the given term
3049 cdef Term term = Term(self.solver)
3050 term.cterm = self.cterm.andTerm((<Term> t).cterm)
3053 def orTerm(self, Term t):
3057 :param t: a Boolean term
3058 :return: the disjunction of this term and the given term
3060 cdef Term term = Term(self.solver)
3061 term.cterm = self.cterm.orTerm(t.cterm)
3064 def xorTerm(self, Term t):
3066 Boolean exclusive or.
3068 :param t: a Boolean term
3069 :return: the exclusive disjunction of this term and the given term
3071 cdef Term term = Term(self.solver)
3072 term.cterm = self.cterm.xorTerm(t.cterm)
3075 def eqTerm(self, Term t):
3079 :param t: a Boolean term
3080 :return: the Boolean equivalence of this term and the given term
3082 cdef Term term = Term(self.solver)
3083 term.cterm = self.cterm.eqTerm(t.cterm)
3086 def impTerm(self, Term t):
3088 Boolean Implication.
3090 :param t: a Boolean term
3091 :return: the implication of this term and the given term
3093 cdef Term term = Term(self.solver)
3094 term.cterm = self.cterm.impTerm(t.cterm)
3097 def iteTerm(self, Term then_t, Term else_t):
3099 If-then-else with this term as the Boolean condition.
3101 :param then_t: the `then` term
3102 :param else_t: the `else` term
3103 :return: the if-then-else term with this term as the Boolean condition
3105 cdef Term term = Term(self.solver)
3106 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
3109 def isConstArray(self):
3110 """:return: True iff this term is a constant array."""
3111 return self.cterm.isConstArray()
3113 def getConstArrayBase(self):
3115 Asserts :py:meth:`isConstArray()`.
3117 :return: the base (element stored at all indicies) of this constant array
3119 cdef Term term = Term(self.solver)
3120 term.cterm = self.cterm.getConstArrayBase()
3123 def isBooleanValue(self):
3124 """:return: True iff this term is a Boolean value."""
3125 return self.cterm.isBooleanValue()
3127 def getBooleanValue(self):
3129 Asserts :py:meth:`isBooleanValue()`
3131 :return: the representation of a Boolean value as a native Boolean value.
3133 return self.cterm.getBooleanValue()
3135 def isStringValue(self):
3136 """:return: True iff this term is a string value."""
3137 return self.cterm.isStringValue()
3139 def getStringValue(self):
3141 Asserts :py:meth:`isStringValue()`.
3144 This method is not to be confused with :py:meth:`__str__()` which
3145 returns the term in some string representation, whatever data it
3148 :return: the string term as a native string value.
3150 cdef Py_ssize_t size
3151 cdef c_wstring s = self.cterm.getStringValue()
3152 return PyUnicode_FromWideChar(s.data(), s.size())
3154 def getRealOrIntegerValueSign(self):
3156 Get integer or real value sign. Must be called on integer or real values,
3157 or otherwise an exception is thrown.
3159 :return: 0 if this term is zero, -1 if this term is a negative real or
3160 integer value, 1 if this term is a positive real or integer value.
3162 return self.cterm.getRealOrIntegerValueSign()
3164 def isIntegerValue(self):
3165 """:return: True iff this term is an integer value."""
3166 return self.cterm.isIntegerValue()
3168 def getIntegerValue(self):
3170 Asserts :py:meth:`isIntegerValue()`.
3172 :return: the integer term as a native python integer.
3174 return int(self.cterm.getIntegerValue().decode())
3176 def isFloatingPointPosZero(self):
3177 """:return: True iff the term is the floating-point value for positive zero."""
3178 return self.cterm.isFloatingPointPosZero()
3180 def isFloatingPointNegZero(self):
3181 """:return: True iff the term is the floating-point value for negative zero."""
3182 return self.cterm.isFloatingPointNegZero()
3184 def isFloatingPointPosInf(self):
3185 """:return: True iff the term is the floating-point value for positive infinity."""
3186 return self.cterm.isFloatingPointPosInf()
3188 def isFloatingPointNegInf(self):
3189 """:return: True iff the term is the floating-point value for negative infinity."""
3190 return self.cterm.isFloatingPointNegInf()
3192 def isFloatingPointNaN(self):
3193 """:return: True iff the term is the floating-point value for not a number."""
3194 return self.cterm.isFloatingPointNaN()
3196 def isFloatingPointValue(self):
3197 """:return: True iff this term is a floating-point value."""
3198 return self.cterm.isFloatingPointValue()
3200 def getFloatingPointValue(self):
3202 Asserts :py:meth:`isFloatingPointValue()`.
3204 :return: the representation of a floating-point value as a tuple of the exponent width, the significand width and a bit-vector value.
3206 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
3207 cdef Term term = Term(self.solver)
3208 term.cterm = get2(t)
3209 return (get0(t), get1(t), term)
3211 def isSetValue(self):
3213 A term is a set value if it is considered to be a (canonical) constant
3214 set value. A canonical set value is one whose AST is:
3219 (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
3221 where ``c1 ... cn`` are values ordered by id such that
3222 ``c1 > ... > cn`` (see also :cpp:func:`cvc5::api::Term::operator>()`).
3225 A universe set term ``(kind SET_UNIVERSE)`` is not considered to be
3228 :return: True if the term is a set value.
3230 return self.cterm.isSetValue()
3232 def getSetValue(self):
3234 Asserts :py:meth:`isSetValue()`.
3236 :return: the representation of a set value as a set of terms.
3239 for e in self.cterm.getSetValue():
3240 term = Term(self.solver)
3245 def isSequenceValue(self):
3246 """:return: True iff this term is a sequence value."""
3247 return self.cterm.isSequenceValue()
3249 def getSequenceValue(self):
3251 Asserts :py:meth:`isSequenceValue()`.
3254 It is usually necessary for sequences to call
3255 :py:meth:`Solver.simplify()` to turn a sequence that is constructed
3256 by, e.g., concatenation of unit sequences, into a sequence value.
3258 :return: the representation of a sequence value as a vector of terms.
3261 for e in self.cterm.getSequenceValue():
3262 term = Term(self.solver)
3267 def isUninterpretedSortValue(self):
3268 """:return: True iff this term is a value from an uninterpreted sort."""
3269 return self.cterm.isUninterpretedSortValue()
3271 def getUninterpretedSortValue(self):
3273 Asserts :py:meth:`isUninterpretedSortValue()`.
3275 :return: the representation of an uninterpreted value as a pair of its sort and its index.
3277 return self.cterm.getUninterpretedSortValue()
3279 def isTupleValue(self):
3280 """:return: True iff this term is a tuple value."""
3281 return self.cterm.isTupleValue()
3283 def getTupleValue(self):
3285 Asserts :py:meth:`isTupleValue()`.
3287 :return: the representation of a tuple value as a vector of terms.
3290 for e in self.cterm.getTupleValue():
3291 term = Term(self.solver)
3296 def isRealValue(self):
3298 .. note:: A term of kind PI is not considered to be a real value.
3300 :return: True iff this term is a rational value.
3302 return self.cterm.isRealValue()
3304 def getRealValue(self):
3306 Asserts :py:meth:`isRealValue()`.
3308 :return: the representation of a rational value as a python Fraction.
3310 return Fraction(self.cterm.getRealValue().decode())
3312 def isBitVectorValue(self):
3313 """:return: True iff this term is a bit-vector value."""
3314 return self.cterm.isBitVectorValue()
3316 def getBitVectorValue(self, base = 2):
3318 Asserts :py:meth:`isBitVectorValue()`.
3319 Supported bases are 2 (bit string), 10 (decimal string) or 16 (hexdecimal string).
3321 :return: the representation of a bit-vector value in string representation.
3323 return self.cterm.getBitVectorValue(base).decode()
3325 def toPythonObj(self):
3327 Converts a constant value Term to a Python object.
3331 - Boolean -- returns a Python bool
3332 - Int -- returns a Python int
3333 - Real -- returns a Python Fraction
3334 - BV -- returns a Python int (treats BV as unsigned)
3335 - String -- returns a Python Unicode string
3336 - Array -- returns a Python dict mapping indices to values. the constant base is returned as the default value
3340 if self.isBooleanValue():
3341 return self.getBooleanValue()
3342 elif self.isIntegerValue():
3343 return self.getIntegerValue()
3344 elif self.isRealValue():
3345 return self.getRealValue()
3346 elif self.isBitVectorValue():
3347 return int(self.getBitVectorValue(), 2)
3348 elif self.isStringValue():
3349 return self.getStringValue()
3350 elif self.getSort().isArray():
3356 # Array models are represented as a series of store operations
3357 # on a constant array
3360 if t.getKind().value == c_Kind.STORE:
3362 keys.append(t[1].toPythonObj())
3363 values.append(t[2].toPythonObj())
3364 to_visit.append(t[0])
3366 assert t.getKind().value == c_Kind.CONST_ARRAY
3367 base_value = t.getConstArrayBase().toPythonObj()
3369 assert len(keys) == len(values)
3370 assert base_value is not None
3372 # put everything in a dictionary with the constant
3373 # base as the result for any index not included in the stores
3374 res = defaultdict(lambda : base_value)
3375 for k, v in zip(keys, values):
3381 # Generate rounding modes
3382 cdef __rounding_modes = {
3383 <int> ROUND_NEAREST_TIES_TO_EVEN: "RoundNearestTiesToEven",
3384 <int> ROUND_TOWARD_POSITIVE: "RoundTowardPositive",
3385 <int> ROUND_TOWARD_NEGATIVE: "RoundTowardNegative",
3386 <int> ROUND_TOWARD_ZERO: "RoundTowardZero",
3387 <int> ROUND_NEAREST_TIES_TO_AWAY: "RoundNearestTiesToAway"
3390 mod_ref = sys.modules[__name__]
3391 for rm_int, name in __rounding_modes.items():
3392 r = RoundingMode(rm_int)
3394 if name in dir(mod_ref):
3395 raise RuntimeError("Redefinition of Python RoundingMode %s."%name)
3397 setattr(mod_ref, name, r)
3404 # Generate unknown explanations
3405 cdef __unknown_explanations = {
3406 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
3407 <int> INCOMPLETE: "Incomplete",
3408 <int> TIMEOUT: "Timeout",
3409 <int> RESOURCEOUT: "Resourceout",
3410 <int> MEMOUT: "Memout",
3411 <int> INTERRUPTED: "Interrupted",
3412 <int> NO_STATUS: "NoStatus",
3413 <int> UNSUPPORTED: "Unsupported",
3414 <int> OTHER: "Other",
3415 <int> UNKNOWN_REASON: "UnknownReason"
3418 for ue_int, name in __unknown_explanations.items():
3419 u = UnknownExplanation(ue_int)
3421 if name in dir(mod_ref):
3422 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
3424 setattr(mod_ref, name, u)