1 from collections import defaultdict
2 from fractions import Fraction
3 from functools import wraps
6 from cython.operator cimport dereference, preincrement
8 from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
9 from libc.stddef cimport wchar_t
11 from libcpp cimport bool as c_bool
12 from libcpp.pair cimport pair
13 from libcpp.set cimport set as c_set
14 from libcpp.string cimport string
15 from libcpp.vector cimport vector
17 from cvc5 cimport cout
18 from cvc5 cimport Datatype as c_Datatype
19 from cvc5 cimport DatatypeConstructor as c_DatatypeConstructor
20 from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
21 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
22 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
23 from cvc5 cimport Result as c_Result
24 from cvc5 cimport SynthResult as c_SynthResult
25 from cvc5 cimport UnknownExplanation as c_UnknownExplanation
26 from cvc5 cimport Op as c_Op
27 from cvc5 cimport OptionInfo as c_OptionInfo
28 from cvc5 cimport holds as c_holds
29 from cvc5 cimport getVariant as c_getVariant
30 from cvc5 cimport Solver as c_Solver
31 from cvc5 cimport Statistics as c_Statistics
32 from cvc5 cimport Stat as c_Stat
33 from cvc5 cimport Grammar as c_Grammar
34 from cvc5 cimport Sort as c_Sort
35 from cvc5 cimport REQUIRES_FULL_CHECK, INCOMPLETE, TIMEOUT
36 from cvc5 cimport RESOURCEOUT, MEMOUT, INTERRUPTED
37 from cvc5 cimport NO_STATUS, UNSUPPORTED, UNKNOWN_REASON
38 from cvc5 cimport OTHER
39 from cvc5 cimport Term as c_Term
40 from cvc5 cimport hash as c_hash
41 from cvc5 cimport wstring as c_wstring
42 from cvc5 cimport tuple as c_tuple
43 from cvc5 cimport get0, get1, get2
44 from cvc5kinds cimport Kind as c_Kind
45 from cvc5types cimport RoundingMode as c_RoundingMode
47 cdef extern from "Python.h":
48 wchar_t* PyUnicode_AsWideCharString(object, Py_ssize_t *)
49 object PyUnicode_FromWideChar(const wchar_t*, Py_ssize_t)
50 void PyMem_Free(void*)
52 ################################## DECORATORS #################################
53 def expand_list_arg(num_req_args=0):
55 Creates a decorator that looks at index num_req_args of the args,
56 if it's a list, it expands it before calling the function.
60 def wrapper(owner, *args):
61 if len(args) == num_req_args + 1 and \
62 isinstance(args[num_req_args], list):
63 args = list(args[:num_req_args]) + args[num_req_args]
64 return func(owner, *args)
67 ###############################################################################
70 ### Using PEP-8 spacing recommendations
71 ### Limit linewidth to 79 characters
72 ### Break before binary operators
73 ### surround top level functions and classes with two spaces
74 ### separate methods by one space
75 ### use spaces in functions sparingly to separate logical blocks
76 ### can omit spaces between unrelated oneliners
77 ### always use c++ default arguments
78 #### only use default args of None at python level
80 # References and pointers
81 # The Solver object holds a pointer to a c_Solver.
82 # This is because the assignment operator is deleted in the C++ API for solvers.
83 # Cython has a limitation where you can't stack allocate objects
84 # that have constructors with arguments:
85 # https://groups.google.com/forum/#!topic/cython-users/fuKd-nQLpBs.
86 # To get around that you can either have a nullary constructor and assignment
87 # or, use a pointer (which is what we chose).
88 # An additional complication of this is that to free up resources, you must
89 # know when to delete the object.
90 # Python will not follow the same scoping rules as in C++, so it must be
91 # able to reference count. To do this correctly, the solver must be a
92 # reference in the Python class for any class that keeps a pointer to
93 # the solver in C++ (to ensure the solver is not deleted before something
94 # that depends on it).
97 ## Objects for hashing
98 cdef c_hash[c_Op] cophash = c_hash[c_Op]()
99 cdef c_hash[c_Sort] csorthash = c_hash[c_Sort]()
100 cdef c_hash[c_Term] ctermhash = c_hash[c_Term]()
106 Wrapper class for :cpp:class:`cvc5::Datatype`.
110 def __cinit__(self, Solver solver):
113 def __getitem__(self, index):
114 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
115 if isinstance(index, int) and index >= 0:
116 dc.cdc = self.cd[(<int?> index)]
117 elif isinstance(index, str):
118 dc.cdc = self.cd[(<const string &> index.encode())]
120 raise ValueError("Expecting a non-negative integer or string")
123 def getConstructor(self, str name):
125 :param name: the name of the constructor.
126 :return: a constructor by name.
128 cdef DatatypeConstructor dc = DatatypeConstructor(self.solver)
129 dc.cdc = self.cd.getConstructor(name.encode())
132 def getConstructorTerm(self, str name):
134 :param name: the name of the constructor.
135 :return: the term representing the datatype constructor with the given name (see :cpp:func:`Datatype::getConstructorTerm() <cvc5::Datatype::getConstructorTerm>`).
137 cdef Term term = Term(self.solver)
138 term.cterm = self.cd.getConstructorTerm(name.encode())
141 def getSelector(self, str name):
143 :param name: the name of the selector..
144 :return: a selector by name.
146 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
147 ds.cds = self.cd.getSelector(name.encode())
152 :return: the name of the datatype.
154 return self.cd.getName().decode()
156 def getNumConstructors(self):
158 :return: number of constructors in this datatype.
160 return self.cd.getNumConstructors()
162 def getParameters(self):
164 :return: the parameters of this datatype, if it is parametric. An exception is thrown if this datatype is not parametric.
167 for s in self.cd.getParameters():
168 sort = Sort(self.solver)
170 param_sorts.append(sort)
173 def isParametric(self):
175 .. warning:: This method is experimental and may change in future
177 :return: True if this datatype is parametric.
179 return self.cd.isParametric()
181 def isCodatatype(self):
182 """:return: True if this datatype corresponds to a co-datatype."""
183 return self.cd.isCodatatype()
186 """:return: True if this datatype corresponds to a tuple."""
187 return self.cd.isTuple()
191 .. warning:: This method is experimental and may change in future
193 :return: True if this datatype corresponds to a record.
195 return self.cd.isRecord()
198 """:return: True if this datatype is finite."""
199 return self.cd.isFinite()
201 def isWellFounded(self):
202 """:return: True if this datatype is well-founded (see :cpp:func:`Datatype::isWellFounded() <cvc5::Datatype::isWellFounded>`)."""
203 return self.cd.isWellFounded()
206 """:return: True if this Datatype is a null object."""
207 return self.cd.isNull()
210 return self.cd.toString().decode()
213 return self.cd.toString().decode()
217 dc = DatatypeConstructor(self.solver)
222 cdef class DatatypeConstructor:
224 A cvc5 datatype constructor.
225 Wrapper class for :cpp:class:`cvc5::DatatypeConstructor`.
227 cdef c_DatatypeConstructor cdc
229 def __cinit__(self, Solver solver):
230 self.cdc = c_DatatypeConstructor()
233 def __getitem__(self, index):
234 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
235 if isinstance(index, int) and index >= 0:
236 ds.cds = self.cdc[(<int?> index)]
237 elif isinstance(index, str):
238 ds.cds = self.cdc[(<const string &> index.encode())]
240 raise ValueError("Expecting a non-negative integer or string")
245 :return: the name of the constructor.
247 return self.cdc.getName().decode()
249 def getConstructorTerm(self):
251 :return: the constructor operator as a term.
253 cdef Term term = Term(self.solver)
254 term.cterm = self.cdc.getConstructorTerm()
257 def getInstantiatedConstructorTerm(self, Sort retSort):
259 Specialized method for parametric datatypes (see
260 :cpp:func:`DatatypeConstructor::getInstantiatedConstructorTerm()
261 <cvc5::DatatypeConstructor::getInstantiatedConstructorTerm>`).
263 .. warning:: This method is experimental and may change in future
266 :param retSort: the desired return sort of the constructor
267 :return: the constructor operator as a term.
269 cdef Term term = Term(self.solver)
270 term.cterm = self.cdc.getInstantiatedConstructorTerm(retSort.csort)
273 def getTesterTerm(self):
275 :return: the tester operator that is related to this constructor, as a term.
277 cdef Term term = Term(self.solver)
278 term.cterm = self.cdc.getTesterTerm()
281 def getNumSelectors(self):
283 :return: the number of selecters (so far) of this Datatype constructor.
285 return self.cdc.getNumSelectors()
287 def getSelector(self, str name):
289 :param name: the name of the datatype selector.
290 :return: the first datatype selector with the given name
292 cdef DatatypeSelector ds = DatatypeSelector(self.solver)
293 ds.cds = self.cdc.getSelector(name.encode())
296 def getSelectorTerm(self, str name):
298 :param name: the name of the datatype selector.
299 :return: a term representing the firstdatatype selector with the given name.
301 cdef Term term = Term(self.solver)
302 term.cterm = self.cdc.getSelectorTerm(name.encode())
306 """:return: True if this DatatypeConstructor is a null object."""
307 return self.cdc.isNull()
310 return self.cdc.toString().decode()
313 return self.cdc.toString().decode()
317 ds = DatatypeSelector(self.solver)
322 cdef class DatatypeConstructorDecl:
324 A cvc5 datatype constructor declaration.
325 Wrapper class for :cpp:class:`cvc5::DatatypeConstructorDecl`.
327 cdef c_DatatypeConstructorDecl cddc
330 def __cinit__(self, Solver solver):
333 def addSelector(self, str name, Sort sort):
335 Add datatype selector declaration.
337 :param name: the name of the datatype selector declaration to add.
338 :param sort: the codomain sort of the datatype selector declaration
341 self.cddc.addSelector(name.encode(), sort.csort)
343 def addSelectorSelf(self, str name):
345 Add datatype selector declaration whose codomain sort is the
348 :param name: the name of the datatype selector declaration to add.
350 self.cddc.addSelectorSelf(name.encode())
353 """:return: True if this DatatypeConstructorDecl is a null object."""
354 return self.cddc.isNull()
357 return self.cddc.toString().decode()
360 return self.cddc.toString().decode()
363 cdef class DatatypeDecl:
365 A cvc5 datatype declaration.
366 Wrapper class for :cpp:class:`cvc5::DatatypeDecl`.
368 cdef c_DatatypeDecl cdd
370 def __cinit__(self, Solver solver):
373 def addConstructor(self, DatatypeConstructorDecl ctor):
375 Add a datatype constructor declaration.
377 :param ctor: the datatype constructor declaration to add.
379 self.cdd.addConstructor(ctor.cddc)
381 def getNumConstructors(self):
383 :return: number of constructors (so far) for this datatype declaration.
385 return self.cdd.getNumConstructors()
387 def isParametric(self):
389 :return: is this datatype declaration parametric?
391 return self.cdd.isParametric()
395 :return: the name of this datatype declaration.
397 return self.cdd.getName().decode()
400 """:return: True if this DatatypeDecl is a null object."""
401 return self.cdd.isNull()
404 return self.cdd.toString().decode()
407 return self.cdd.toString().decode()
410 cdef class DatatypeSelector:
412 A cvc5 datatype selector.
413 Wrapper class for :cpp:class:`cvc5::DatatypeSelector`.
415 cdef c_DatatypeSelector cds
417 def __cinit__(self, Solver solver):
418 self.cds = c_DatatypeSelector()
423 :return: the name of this datatype selector.
425 return self.cds.getName().decode()
427 def getSelectorTerm(self):
429 :return: the selector opeartor of this datatype selector as a term.
431 cdef Term term = Term(self.solver)
432 term.cterm = self.cds.getSelectorTerm()
435 def getUpdaterTerm(self):
437 :return: the updater opeartor of this datatype selector as a term.
439 cdef Term term = Term(self.solver)
440 term.cterm = self.cds.getUpdaterTerm()
443 def getCodomainSort(self):
445 :return: the codomain sort of this selector.
447 cdef Sort sort = Sort(self.solver)
448 sort.csort = self.cds.getCodomainSort()
452 """:return: True if this DatatypeSelector is a null object."""
453 return self.cds.isNull()
456 return self.cds.toString().decode()
459 return self.cds.toString().decode()
465 An operator is a term that represents certain operators,
466 instantiated with its required parameters, e.g.,
467 a term of kind :cpp:enumerator:`BITVECTOR_EXTRACT`.
468 Wrapper class for :cpp:class:`cvc5::Op`.
472 def __cinit__(self, Solver solver):
476 def __eq__(self, Op other):
477 return self.cop == other.cop
479 def __ne__(self, Op other):
480 return self.cop != other.cop
483 return self.cop.toString().decode()
486 return self.cop.toString().decode()
489 return cophash(self.cop)
493 :return: the kind of this operator.
495 return Kind(<int> self.cop.getKind())
499 :return: True iff this operator is indexed.
501 return self.cop.isIndexed()
505 :return: True iff this operator is a null term.
507 return self.cop.isNull()
509 def getNumIndices(self):
511 :return: number of indices of this op.
513 return self.cop.getNumIndices()
515 def __getitem__(self, i):
517 Get the index at position i.
518 :param i: the position of the index to return
519 :return: the index at position i
521 cdef Term term = Term(self.solver)
522 term.cterm = self.cop[i]
529 Wrapper class for :cpp:class:`cvc5::Grammar`.
531 cdef c_Grammar cgrammar
533 def __cinit__(self, Solver solver):
535 self.cgrammar = c_Grammar()
537 def addRule(self, Term ntSymbol, Term rule):
539 Add ``rule`` to the set of rules corresponding to ``ntSymbol``.
541 :param ntSymbol: the non-terminal to which the rule is added.
542 :param rule: the rule to add.
544 self.cgrammar.addRule(ntSymbol.cterm, rule.cterm)
546 def addAnyConstant(self, Term ntSymbol):
548 Allow ``ntSymbol`` to be an arbitrary constant.
550 :param ntSymbol: the non-terminal allowed to be constant.
552 self.cgrammar.addAnyConstant(ntSymbol.cterm)
554 def addAnyVariable(self, Term ntSymbol):
556 Allow ``ntSymbol`` to be any input variable to corresponding synth-fun/synth-inv with the same sort as ``ntSymbol``.
558 :param ntSymbol: the non-terminal allowed to be any input variable.
560 self.cgrammar.addAnyVariable(ntSymbol.cterm)
562 def addRules(self, Term ntSymbol, rules):
564 Add ``ntSymbol`` to the set of rules corresponding to ``ntSymbol``.
566 :param ntSymbol: the non-terminal to which the rules are added.
567 :param rules: the rules to add.
569 cdef vector[c_Term] crules
571 crules.push_back((<Term?> r).cterm)
572 self.cgrammar.addRules(ntSymbol.cterm, crules)
576 Encapsulation of a three-valued solver result, with explanations.
577 Wrapper class for :cpp:class:`cvc5::Result`.
581 # gets populated by solver
586 :return: True if Result is empty, i.e., a nullary Result, and not an actual result returned from a
587 :cpp:func:`Solver::checkSat() <cvc5::Solver::checkSat>` (and friends) query.
589 return self.cr.isNull()
593 :return: True if query was a satisfiable :cpp:func:`Solver::checkSat() <cvc5::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::Solver::checkSatAssuming>` query.
595 return self.cr.isSat()
599 :return: True if query was an usatisfiable :cpp:func:`Solver::checkSat() <cvc5::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::Solver::checkSatAssuming>` query.
601 return self.cr.isUnsat()
605 :return: True if query was a :cpp:func:`Solver::checkSat() <cvc5::Solver::checkSat>` or :cpp:func:`Solver::checkSatAssuming() <cvc5::Solver::checkSatAssuming>` query and cvc5 was not able to determine (un)satisfiability.
607 return self.cr.isUnknown()
609 def getUnknownExplanation(self):
611 :return: an explanation for an unknown query result.
613 return UnknownExplanation(<int> self.cr.getUnknownExplanation())
615 def __eq__(self, Result other):
616 return self.cr == other.cr
618 def __ne__(self, Result other):
619 return self.cr != other.cr
622 return self.cr.toString().decode()
625 return self.cr.toString().decode()
627 cdef class SynthResult:
629 Encapsulation of a solver synth result. This is the return value of the
631 - :py:meth:`Solver.checkSynth()`
632 - :py:meth:`Solver.checkSynthNext()`
633 which we call synthesis queries. This class indicates whether the
634 synthesis query has a solution, has no solution, or is unknown.
636 cdef c_SynthResult cr
638 # gets populated by solver
639 self.cr = c_SynthResult()
643 :return: True if SynthResult is null, i.e. not a SynthResult returned from a synthesis query.
645 return self.cr.isNull()
647 def hasSolution(self):
649 :return: True if the synthesis query has a solution.
651 return self.cr.hasSolution()
653 def hasNoSolution(self):
655 :return: True if the synthesis query has no solution.
656 In this case, then it was determined there was no solution.
658 return self.cr.hasNoSolution()
662 :return: True if the result of the synthesis query could not be determined.
664 return self.cr.isUnknown()
667 return self.cr.toString().decode()
670 return self.cr.toString().decode()
672 cdef class UnknownExplanation:
674 Wrapper class for :cpp:enum:`cvc5::Result::UnknownExplanation`.
676 cdef c_UnknownExplanation cue
678 def __cinit__(self, int ue):
679 # crm always assigned externally
680 self.cue = <c_UnknownExplanation> ue
681 self.name = __unknown_explanations[ue]
683 def __eq__(self, UnknownExplanation other):
684 return (<int> self.cue) == (<int> other.cue)
686 def __ne__(self, UnknownExplanation other):
687 return not self.__eq__(other)
690 return hash((<int> self.crm, self.name))
700 """Wrapper class for :cpp:class:`cvc5::Solver`."""
701 cdef c_Solver* csolver
704 self.csolver = new c_Solver()
706 def __dealloc__(self):
709 def getBooleanSort(self):
710 """:return: sort Boolean
712 cdef Sort sort = Sort(self)
713 sort.csort = self.csolver.getBooleanSort()
716 def getIntegerSort(self):
717 """:return: sort Integer
719 cdef Sort sort = Sort(self)
720 sort.csort = self.csolver.getIntegerSort()
723 def getNullSort(self):
724 """:return: sort null
726 cdef Sort sort = Sort(self)
727 sort.csort = self.csolver.getNullSort()
730 def getRealSort(self):
731 """:return: sort Real
733 cdef Sort sort = Sort(self)
734 sort.csort = self.csolver.getRealSort()
737 def getRegExpSort(self):
738 """:return: sort of RegExp
740 cdef Sort sort = Sort(self)
741 sort.csort = self.csolver.getRegExpSort()
744 def getRoundingModeSort(self):
745 """:return: sort RoundingMode
747 cdef Sort sort = Sort(self)
748 sort.csort = self.csolver.getRoundingModeSort()
751 def getStringSort(self):
752 """:return: sort String
754 cdef Sort sort = Sort(self)
755 sort.csort = self.csolver.getStringSort()
758 def mkArraySort(self, Sort indexSort, Sort elemSort):
759 """Create an array sort.
761 :param indexSort: the array index sort
762 :param elemSort: the array element sort
763 :return: the array sort
765 cdef Sort sort = Sort(self)
766 sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
769 def mkBitVectorSort(self, uint32_t size):
770 """Create a bit-vector sort.
772 :param size: the bit-width of the bit-vector sort
773 :return: the bit-vector sort
775 cdef Sort sort = Sort(self)
776 sort.csort = self.csolver.mkBitVectorSort(size)
779 def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
780 """Create a floating-point sort.
782 :param exp: the bit-width of the exponent of the floating-point sort.
783 :param sig: the bit-width of the significand of the floating-point sort.
785 cdef Sort sort = Sort(self)
786 sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
789 def mkDatatypeSort(self, DatatypeDecl dtypedecl):
790 """Create a datatype sort.
792 :param dtypedecl: the datatype declaration from which the sort is created
793 :return: the datatype sort
795 cdef Sort sort = Sort(self)
796 sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
799 def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
801 Create a vector of datatype sorts using unresolved sorts. The names of
802 the datatype declarations in dtypedecls must be distinct.
804 This method is called when the DatatypeDecl objects dtypedecls have been
805 built using "unresolved" sorts.
807 We associate each sort in unresolvedSorts with exacly one datatype from
808 dtypedecls. In particular, it must have the same name as exactly one
809 datatype declaration in dtypedecls.
811 When constructing datatypes, unresolved sorts are replaced by the datatype
812 sort constructed for the datatype declaration it is associated with.
814 :param dtypedecls: the datatype declarations from which the sort is created
815 :param unresolvedSorts: the list of unresolved sorts
816 :return: the datatype sorts
818 if unresolvedSorts == None:
819 unresolvedSorts = set([])
821 assert isinstance(unresolvedSorts, set)
824 cdef vector[c_DatatypeDecl] decls
825 for decl in dtypedecls:
826 decls.push_back((<DatatypeDecl?> decl).cdd)
828 cdef c_set[c_Sort] usorts
829 for usort in unresolvedSorts:
830 usorts.insert((<Sort?> usort).csort)
832 csorts = self.csolver.mkDatatypeSorts(
833 <const vector[c_DatatypeDecl]&> decls, <const c_set[c_Sort]&> usorts)
841 def mkFunctionSort(self, sorts, Sort codomain):
842 """ Create function sort.
844 :param sorts: the sort of the function arguments
845 :param codomain: the sort of the function return value
846 :return: the function sort
849 cdef Sort sort = Sort(self)
850 # populate a vector with dereferenced c_Sorts
851 cdef vector[c_Sort] v
853 if isinstance(sorts, Sort):
854 sort.csort = self.csolver.mkFunctionSort((<Sort?> sorts).csort,
856 elif isinstance(sorts, list):
858 v.push_back((<Sort?>s).csort)
860 sort.csort = self.csolver.mkFunctionSort(<const vector[c_Sort]&> v,
864 def mkParamSort(self, symbolname):
865 """ Create a sort parameter.
867 .. warning:: This method is experimental and may change in future
870 :param symbol: the name of the sort
871 :return: the sort parameter
873 cdef Sort sort = Sort(self)
874 sort.csort = self.csolver.mkParamSort(symbolname.encode())
877 @expand_list_arg(num_req_args=0)
878 def mkPredicateSort(self, *sorts):
879 """Create a predicate sort.
881 :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
882 :return: the predicate sort
884 cdef Sort sort = Sort(self)
885 cdef vector[c_Sort] v
887 v.push_back((<Sort?> s).csort)
888 sort.csort = self.csolver.mkPredicateSort(<const vector[c_Sort]&> v)
891 @expand_list_arg(num_req_args=0)
892 def mkRecordSort(self, *fields):
893 """Create a record sort
895 .. warning:: This method is experimental and may change in future
898 :param fields: the list of fields of the record, as a list or as distinct arguments
899 :return: the record sort
901 cdef Sort sort = Sort(self)
902 cdef vector[pair[string, c_Sort]] v
903 cdef pair[string, c_Sort] p
907 p = pair[string, c_Sort](<string?> name, (<Sort?> sortarg).csort)
909 sort.csort = self.csolver.mkRecordSort(
910 <const vector[pair[string, c_Sort]] &> v)
913 def mkSetSort(self, Sort elemSort):
914 """Create a set sort.
916 :param elemSort: the sort of the set elements
917 :return: the set sort
919 cdef Sort sort = Sort(self)
920 sort.csort = self.csolver.mkSetSort(elemSort.csort)
923 def mkBagSort(self, Sort elemSort):
924 """Create a bag sort.
926 :param elemSort: the sort of the bag elements
927 :return: the bag sort
929 cdef Sort sort = Sort(self)
930 sort.csort = self.csolver.mkBagSort(elemSort.csort)
933 def mkSequenceSort(self, Sort elemSort):
934 """Create a sequence sort.
936 :param elemSort: the sort of the sequence elements
937 :return: the sequence sort
939 cdef Sort sort = Sort(self)
940 sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
943 def mkUninterpretedSort(self, str name):
944 """Create an uninterpreted sort.
946 :param symbol: the name of the sort
947 :return: the uninterpreted sort
949 cdef Sort sort = Sort(self)
950 sort.csort = self.csolver.mkUninterpretedSort(name.encode())
953 def mkUnresolvedSort(self, str name, size_t arity = 0):
954 """Create an unresolved sort.
956 This is for creating yet unresolved sort placeholders for mutually
959 :param symbol: the name of the sort
960 :param arity: the number of sort parameters of the sort
961 :return: the unresolved sort
963 cdef Sort sort = Sort(self)
964 sort.csort = self.csolver.mkUnresolvedSort(name.encode(), arity)
967 def mkUninterpretedSortConstructorSort(self, str symbol, size_t arity):
968 """Create a sort constructor sort.
970 An uninterpreted sort constructor is an uninterpreted sort with
973 :param symbol: the symbol of the sort
974 :param arity: the arity of the sort (must be > 0)
975 :return: the sort constructor sort
977 cdef Sort sort = Sort(self)
978 sort.csort = self.csolver.mkUninterpretedSortConstructorSort(
979 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, const string& arg)``
1047 - ``Op mkOp(Kind kind, uint32_t arg0, ...)``
1049 cdef Op op = Op(self)
1050 cdef vector[uint32_t] v
1053 op.cop = self.csolver.mkOp(<c_Kind> k.value)
1054 elif len(args) == 1 and isinstance(args[0], str):
1055 op.cop = self.csolver.mkOp(<c_Kind> k.value,
1060 if not isinstance(a, int):
1062 "Expected uint32_t for argument {}".format(a))
1063 if a < 0 or a >= 2 ** 31:
1065 "Argument {} must fit in a uint32_t".format(a))
1066 v.push_back((<uint32_t?> a))
1067 op.cop = self.csolver.mkOp(<c_Kind> k.value, v)
1071 """Create a Boolean true constant.
1073 :return: the true constant
1075 cdef Term term = Term(self)
1076 term.cterm = self.csolver.mkTrue()
1080 """Create a Boolean false constant.
1082 :return: the false constant
1084 cdef Term term = Term(self)
1085 term.cterm = self.csolver.mkFalse()
1088 def mkBoolean(self, bint val):
1089 """Create a Boolean constant.
1091 :return: the Boolean constant
1092 :param val: the value of the constant
1094 cdef Term term = Term(self)
1095 term.cterm = self.csolver.mkBoolean(val)
1099 """Create a constant representing the number Pi.
1101 :return: a constant representing Pi
1103 cdef Term term = Term(self)
1104 term.cterm = self.csolver.mkPi()
1107 def mkInteger(self, val):
1108 """Create an integer constant.
1110 :param val: representation of the constant: either a string or integer
1111 :return: a constant of sort Integer
1113 cdef Term term = Term(self)
1114 if isinstance(val, str):
1115 term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
1117 assert(isinstance(val, int))
1118 term.cterm = self.csolver.mkInteger((<int?> val))
1121 def mkReal(self, val, den=None):
1122 """Create a real constant.
1124 :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.
1125 :param den: if not None, the value is `val`/`den`
1126 :return: a real term with literal value
1128 Can be used in various forms:
1130 - Given a string ``"N/D"`` constructs the corresponding rational.
1131 - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
1132 - 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``.
1133 - Given a string ``"W"`` or an integer, constructs that integer.
1134 - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
1136 cdef Term term = Term(self)
1138 term.cterm = self.csolver.mkReal(str(val).encode())
1140 if not isinstance(val, int) or not isinstance(den, int):
1141 raise ValueError("Expecting integers when"
1142 " constructing a rational"
1143 " but got: {}".format((val, den)))
1144 term.cterm = self.csolver.mkReal("{}/{}".format(val, den).encode())
1147 def mkRegexpAll(self):
1148 """Create a regular expression all (re.all) term.
1150 :return: the all term
1152 cdef Term term = Term(self)
1153 term.cterm = self.csolver.mkRegexpAll()
1156 def mkRegexpAllchar(self):
1157 """Create a regular expression allchar (re.allchar) term.
1159 :return: the allchar term
1161 cdef Term term = Term(self)
1162 term.cterm = self.csolver.mkRegexpAllchar()
1165 def mkRegexpNone(self):
1166 """Create a regular expression none (re.none) term.
1168 :return: the none term
1170 cdef Term term = Term(self)
1171 term.cterm = self.csolver.mkRegexpNone()
1174 def mkEmptySet(self, Sort s):
1175 """Create a constant representing an empty set of the given sort.
1177 :param sort: the sort of the set elements.
1178 :return: the empty set constant
1180 cdef Term term = Term(self)
1181 term.cterm = self.csolver.mkEmptySet(s.csort)
1184 def mkEmptyBag(self, Sort s):
1185 """Create a constant representing an empty bag of the given sort.
1187 :param sort: the sort of the bag elements.
1188 :return: the empty bag constant
1190 cdef Term term = Term(self)
1191 term.cterm = self.csolver.mkEmptyBag(s.csort)
1195 """Create a separation logic empty term.
1197 .. warning:: This method is experimental and may change in future
1200 :return: the separation logic empty term
1202 cdef Term term = Term(self)
1203 term.cterm = self.csolver.mkSepEmp()
1206 def mkSepNil(self, Sort sort):
1207 """Create a separation logic nil term.
1209 .. warning:: This method is experimental and may change in future
1212 :param sort: the sort of the nil term
1213 :return: the separation logic nil term
1215 cdef Term term = Term(self)
1216 term.cterm = self.csolver.mkSepNil(sort.csort)
1219 def mkString(self, str s, useEscSequences = None):
1221 Create a String constant from a `str` which may contain SMT-LIB
1222 compatible escape sequences like ``\\u1234`` to encode unicode characters.
1224 :param s: the string this constant represents
1225 :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
1226 :return: the String constant
1228 cdef Term term = Term(self)
1229 cdef Py_ssize_t size
1230 cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
1231 if isinstance(useEscSequences, bool):
1232 term.cterm = self.csolver.mkString(
1233 s.encode(), <bint> useEscSequences)
1235 term.cterm = self.csolver.mkString(c_wstring(tmp, size))
1239 def mkEmptySequence(self, Sort sort):
1240 """Create an empty sequence of the given element sort.
1242 :param sort: The element sort of the sequence.
1243 :return: the empty sequence with given element sort.
1245 cdef Term term = Term(self)
1246 term.cterm = self.csolver.mkEmptySequence(sort.csort)
1249 def mkUniverseSet(self, Sort sort):
1250 """Create a universe set of the given sort.
1252 :param sort: the sort of the set elements
1253 :return: the universe set constant
1255 cdef Term term = Term(self)
1256 term.cterm = self.csolver.mkUniverseSet(sort.csort)
1259 @expand_list_arg(num_req_args=0)
1260 def mkBitVector(self, *args):
1262 Supports the following arguments:
1264 - ``Term mkBitVector(int size, int val=0)``
1265 - ``Term mkBitVector(int size, string val, int base)``
1267 :return: a bit-vector literal term
1268 :param size: an integer size.
1269 :param val: an integer representating the value, in the first form. In the second form, a string representing the value.
1270 :param base: the base of the string representation (second form only)
1272 cdef Term term = Term(self)
1274 raise ValueError("Missing arguments to mkBitVector")
1276 if not isinstance(size, int):
1278 "Invalid first argument to mkBitVector '{}', "
1279 "expected bit-vector size".format(size))
1281 term.cterm = self.csolver.mkBitVector(<uint32_t> size)
1282 elif len(args) == 2:
1284 if not isinstance(val, int):
1286 "Invalid second argument to mkBitVector '{}', "
1287 "expected integer value".format(size))
1288 term.cterm = self.csolver.mkBitVector(
1289 <uint32_t> size, <uint32_t> val)
1290 elif len(args) == 3:
1293 if not isinstance(val, str):
1295 "Invalid second argument to mkBitVector '{}', "
1296 "expected value string".format(size))
1297 if not isinstance(base, int):
1299 "Invalid third argument to mkBitVector '{}', "
1300 "expected base given as integer".format(size))
1301 term.cterm = self.csolver.mkBitVector(
1303 <const string&> str(val).encode(),
1306 raise ValueError("Unexpected inputs to mkBitVector")
1309 def mkConstArray(self, Sort sort, Term val):
1311 Create a constant array with the provided constant value stored at every
1314 :param sort: the sort of the constant array (must be an array sort)
1315 :param val: the constant value to store (must match the sort's element sort)
1316 :return: the constant array term
1318 cdef Term term = Term(self)
1319 term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
1322 def mkFloatingPointPosInf(self, int exp, int sig):
1323 """Create a positive infinity floating-point constant.
1325 :param exp: Number of bits in the exponent
1326 :param sig: Number of bits in the significand
1327 :return: the floating-point constant
1329 cdef Term term = Term(self)
1330 term.cterm = self.csolver.mkFloatingPointPosInf(exp, sig)
1333 def mkFloatingPointNegInf(self, int exp, int sig):
1334 """Create a negative infinity floating-point constant.
1336 :param exp: Number of bits in the exponent
1337 :param sig: Number of bits in the significand
1338 :return: the floating-point constant
1340 cdef Term term = Term(self)
1341 term.cterm = self.csolver.mkFloatingPointNegInf(exp, sig)
1344 def mkFloatingPointNaN(self, int exp, int sig):
1345 """Create a not-a-number (NaN) floating-point constant.
1347 :param exp: Number of bits in the exponent
1348 :param sig: Number of bits in the significand
1349 :return: the floating-point constant
1351 cdef Term term = Term(self)
1352 term.cterm = self.csolver.mkFloatingPointNaN(exp, sig)
1355 def mkFloatingPointPosZero(self, int exp, int sig):
1356 """Create a positive zero (+0.0) floating-point constant.
1358 :param exp: Number of bits in the exponent
1359 :param sig: Number of bits in the significand
1360 :return: the floating-point constant
1362 cdef Term term = Term(self)
1363 term.cterm = self.csolver.mkFloatingPointPosZero(exp, sig)
1366 def mkFloatingPointNegZero(self, int exp, int sig):
1367 """Create a negative zero (+0.0) floating-point constant.
1369 :param exp: Number of bits in the exponent
1370 :param sig: Number of bits in the significand
1371 :return: the floating-point constant
1373 cdef Term term = Term(self)
1374 term.cterm = self.csolver.mkFloatingPointNegZero(exp, sig)
1377 def mkRoundingMode(self, rm):
1378 """Create a roundingmode constant.
1380 :param rm: the floating point rounding mode this constant represents
1382 cdef Term term = Term(self)
1383 term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.value)
1386 def mkFloatingPoint(self, int exp, int sig, Term val):
1387 """Create a floating-point constant.
1389 :param exp: Size of the exponent
1390 :param sig: Size of the significand
1391 :param val: Value of the floating-point constant as a bit-vector term
1393 cdef Term term = Term(self)
1394 term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
1397 def mkCardinalityConstraint(self, Sort sort, int index):
1398 """Create cardinality constraint.
1400 .. warning:: This method is experimental and may change in future
1403 :param sort: Sort of the constraint
1404 :param index: The upper bound for the cardinality of the sort
1406 cdef Term term = Term(self)
1407 term.cterm = self.csolver.mkCardinalityConstraint(sort.csort, index)
1410 def mkConst(self, Sort sort, symbol=None):
1412 Create (first-order) constant (0-arity function symbol).
1416 .. code-block:: smtlib
1418 ( declare-const <symbol> <sort> )
1419 ( declare-fun <symbol> ( ) <sort> )
1421 :param sort: the sort of the constant
1422 :param symbol: the name of the constant. If None, a default symbol is used.
1423 :return: the first-order constant
1425 cdef Term term = Term(self)
1427 term.cterm = self.csolver.mkConst(sort.csort)
1429 term.cterm = self.csolver.mkConst(sort.csort,
1430 (<str?> symbol).encode())
1433 def mkVar(self, Sort sort, symbol=None):
1435 Create a bound variable to be used in a binder (i.e. a quantifier, a
1436 lambda, or a witness binder).
1438 :param sort: the sort of the variable
1439 :param symbol: the name of the variable
1440 :return: the variable
1442 cdef Term term = Term(self)
1444 term.cterm = self.csolver.mkVar(sort.csort)
1446 term.cterm = self.csolver.mkVar(sort.csort,
1447 (<str?> symbol).encode())
1450 def mkDatatypeConstructorDecl(self, str name):
1452 :param name: the constructor's name
1453 :return: the DatatypeConstructorDecl
1455 cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
1456 ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
1459 def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
1460 """Create a datatype declaration.
1462 :param name: the name of the datatype
1463 :param isCoDatatype: true if a codatatype is to be constructed
1464 :return: the DatatypeDecl
1466 cdef DatatypeDecl dd = DatatypeDecl(self)
1467 cdef vector[c_Sort] v
1470 if sorts_or_bool is None and isCoDatatype is None:
1471 dd.cdd = self.csolver.mkDatatypeDecl(name.encode())
1472 elif sorts_or_bool is not None and isCoDatatype is None:
1473 if isinstance(sorts_or_bool, bool):
1474 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1475 <bint> sorts_or_bool)
1476 elif isinstance(sorts_or_bool, Sort):
1477 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1478 (<Sort> sorts_or_bool).csort)
1479 elif isinstance(sorts_or_bool, list):
1480 for s in sorts_or_bool:
1481 v.push_back((<Sort?> s).csort)
1482 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1483 <const vector[c_Sort]&> v)
1485 raise ValueError("Unhandled second argument type {}"
1486 .format(type(sorts_or_bool)))
1487 elif sorts_or_bool is not None and isCoDatatype is not None:
1488 if isinstance(sorts_or_bool, Sort):
1489 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1490 (<Sort> sorts_or_bool).csort,
1491 <bint> isCoDatatype)
1492 elif isinstance(sorts_or_bool, list):
1493 for s in sorts_or_bool:
1494 v.push_back((<Sort?> s).csort)
1495 dd.cdd = self.csolver.mkDatatypeDecl(<const string &> name.encode(),
1496 <const vector[c_Sort]&> v,
1497 <bint> isCoDatatype)
1499 raise ValueError("Unhandled second argument type {}"
1500 .format(type(sorts_or_bool)))
1502 raise ValueError("Can't create DatatypeDecl with {}".format([type(a)
1509 def simplify(self, Term t):
1511 Simplify a formula without doing "much" work. Does not involve the
1512 SAT Engine in the simplification, but uses the current definitions,
1513 assertions, and the current partial model, if one has been constructed.
1514 It also involves theory normalization.
1516 .. warning:: This method is experimental and may change in future
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 declareSygusVar(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.declareSygusVar(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 addSygusAssume(self, Term t):
1607 Add a formula to the set of Sygus assumptions.
1611 .. code-block:: smtlib
1615 :param term: the formuula to add as an assumption
1617 self.csolver.addSygusAssume(t.cterm)
1619 def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
1621 Add a set of SyGuS constraints to the current state that correspond to an
1622 invariant synthesis problem.
1626 .. code-block:: smtlib
1628 ( inv-constraint <inv> <pre> <trans> <post> )
1630 :param inv: the function-to-synthesize
1631 :param pre: the pre-condition
1632 :param trans: the transition relation
1633 :param post: the post-condition
1635 self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
1637 def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
1639 Synthesize n-ary function following specified syntactic constraints.
1643 .. code-block:: smtlib
1645 ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
1647 :param symbol: the name of the function
1648 :param boundVars: the parameters to this function
1649 :param sort: the sort of the return value of this function
1650 :param grammar: the syntactic constraints
1651 :return: the function
1653 cdef Term term = Term(self)
1654 cdef vector[c_Term] v
1655 for bv in bound_vars:
1656 v.push_back((<Term?> bv).cterm)
1658 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort)
1660 term.cterm = self.csolver.synthFun(symbol.encode(), <const vector[c_Term]&> v, sort.csort, grammar.cgrammar)
1663 def checkSynth(self):
1665 Try to find a solution for the synthesis conjecture corresponding to the
1666 current list of functions-to-synthesize, universal variables and
1671 .. code-block:: smtlib
1675 :return: the result of the check, which is "solution" if the check
1676 found a solution in which case solutions are available via
1677 getSynthSolutions, "no solution" if it was determined there is
1678 no solution, or "unknown" otherwise.
1680 cdef SynthResult r = SynthResult()
1681 r.cr = self.csolver.checkSynth()
1684 def checkSynthNext(self):
1686 Try to find a next solution for the synthesis conjecture corresponding
1687 to the current list of functions-to-synthesize, universal variables and
1688 constraints. Must be called immediately after a successful call to
1689 check-synth or check-synth-next. Requires incremental mode.
1693 .. code-block:: smtlib
1697 :return: the result of the check, which is "solution" if the check
1698 found a solution in which case solutions are available via
1699 getSynthSolutions, "no solution" if it was determined there is
1700 no solution, or "unknown" otherwise.
1702 cdef SynthResult r = SynthResult()
1703 r.cr = self.csolver.checkSynthNext()
1706 def getSynthSolution(self, Term term):
1708 Get the synthesis solution of the given term. This method should be
1709 called immediately after the solver answers unsat for sygus input.
1711 :param term: the term for which the synthesis solution is queried
1712 :return: the synthesis solution of the given term
1714 cdef Term t = Term(self)
1715 t.cterm = self.csolver.getSynthSolution(term.cterm)
1718 def getSynthSolutions(self, list terms):
1720 Get the synthesis solutions of the given terms. This method should be
1721 called immediately after the solver answers unsat for sygus input.
1723 :param terms: the terms for which the synthesis solutions is queried
1724 :return: the synthesis solutions of the given terms
1727 cdef vector[c_Term] vec
1729 vec.push_back((<Term?> t).cterm)
1730 cresult = self.csolver.getSynthSolutions(vec)
1738 def synthInv(self, symbol, bound_vars, Grammar grammar=None):
1740 Synthesize invariant.
1744 .. code-block:: smtlib
1746 ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
1748 :param symbol: the name of the invariant
1749 :param boundVars: the parameters to this invariant
1750 :param grammar: the syntactic constraints
1751 :return: the invariant
1753 cdef Term term = Term(self)
1754 cdef vector[c_Term] v
1755 for bv in bound_vars:
1756 v.push_back((<Term?> bv).cterm)
1758 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v)
1760 term.cterm = self.csolver.synthInv(symbol.encode(), <const vector[c_Term]&> v, grammar.cgrammar)
1763 @expand_list_arg(num_req_args=0)
1764 def checkSatAssuming(self, *assumptions):
1765 """ Check satisfiability assuming the given formula.
1769 .. code-block:: smtlib
1771 ( check-sat-assuming ( <prop_literal> ) )
1773 :param assumptions: the formulas to assume, as a list or as distinct arguments
1774 :return: the result of the satisfiability check.
1776 cdef Result r = Result()
1777 # used if assumptions is a list of terms
1778 cdef vector[c_Term] v
1779 for a in assumptions:
1780 v.push_back((<Term?> a).cterm)
1781 r.cr = self.csolver.checkSatAssuming(<const vector[c_Term]&> v)
1784 @expand_list_arg(num_req_args=1)
1785 def declareDatatype(self, str symbol, *ctors):
1787 Create datatype sort.
1791 .. code-block:: smtlib
1793 ( declare-datatype <symbol> <datatype_decl> )
1795 :param symbol: the name of the datatype sort
1796 :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
1797 :return: the datatype sort
1799 cdef Sort sort = Sort(self)
1800 cdef vector[c_DatatypeConstructorDecl] v
1803 v.push_back((<DatatypeConstructorDecl?> c).cddc)
1804 sort.csort = self.csolver.declareDatatype(symbol.encode(), v)
1807 def declareFun(self, str symbol, list sorts, Sort sort):
1808 """Declare n-ary function symbol.
1812 .. code-block:: smtlib
1814 ( declare-fun <symbol> ( <sort>* ) <sort> )
1816 :param symbol: the name of the function
1817 :param sorts: the sorts of the parameters to this function
1818 :param sort: the sort of the return value of this function
1819 :return: the function
1821 cdef Term term = Term(self)
1822 cdef vector[c_Sort] v
1824 v.push_back((<Sort?> s).csort)
1825 term.cterm = self.csolver.declareFun(symbol.encode(),
1826 <const vector[c_Sort]&> v,
1830 def declareSort(self, str symbol, int arity):
1831 """Declare uninterpreted sort.
1835 .. code-block:: smtlib
1837 ( declare-sort <symbol> <numeral> )
1840 This corresponds to :py:meth:`Solver.mkUninterpretedSort()` if
1842 :py:meth:`Solver.mkUninterpretedSortConstructorSort()` if arity > 0.
1844 :param symbol: the name of the sort
1845 :param arity: the arity of the sort
1848 cdef Sort sort = Sort(self)
1849 sort.csort = self.csolver.declareSort(symbol.encode(), arity)
1852 def defineFun(self, str symbol, list bound_vars, Sort sort, Term term, glbl=False):
1853 """Define n-ary function.
1857 .. code-block:: smtlib
1859 ( define-fun <function_def> )
1861 :param symbol: the name of the function
1862 :param bound_vars: the parameters to this function
1863 :param sort: the sort of the return value of this function
1864 :param term: the function body
1865 :param glbl: determines whether this definition is global (i.e. persists when popping the context)
1866 :return: the function
1868 cdef Term fun = Term(self)
1869 cdef vector[c_Term] v
1870 for bv in bound_vars:
1871 v.push_back((<Term?> bv).cterm)
1873 fun.cterm = self.csolver.defineFun(symbol.encode(),
1874 <const vector[c_Term] &> v,
1880 def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
1881 """Define recursive functions.
1885 - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
1886 - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
1891 .. code-block:: smtlib
1893 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1895 Create elements of parameter ``funs`` with mkConst().
1897 :param funs: the sorted functions
1898 :param bound_vars: the list of parameters to the functions
1899 :param terms: the list of function bodies of the functions
1900 :param global: determines whether this definition is global (i.e. persists when popping the context)
1901 :return: the function
1903 cdef Term term = Term(self)
1904 cdef vector[c_Term] v
1905 for bv in bound_vars:
1906 v.push_back((<Term?> bv).cterm)
1909 term.cterm = self.csolver.defineFunRec((<str?> sym_or_fun).encode(),
1910 <const vector[c_Term] &> v,
1911 (<Sort?> sort_or_term).csort,
1915 term.cterm = self.csolver.defineFunRec((<Term?> sym_or_fun).cterm,
1916 <const vector[c_Term]&> v,
1917 (<Term?> sort_or_term).cterm,
1922 def defineFunsRec(self, funs, bound_vars, terms):
1923 """Define recursive functions.
1927 .. code-block:: smtlib
1929 ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
1931 Create elements of parameter ``funs`` with mkConst().
1933 :param funs: the sorted functions
1934 :param bound_vars: the list of parameters to the functions
1935 :param terms: the list of function bodies of the functions
1936 :param global: determines whether this definition is global (i.e. persists when popping the context)
1937 :return: the function
1939 cdef vector[c_Term] vf
1940 cdef vector[vector[c_Term]] vbv
1941 cdef vector[c_Term] vt
1944 vf.push_back((<Term?> f).cterm)
1946 cdef vector[c_Term] temp
1947 for v in bound_vars:
1949 temp.push_back((<Term?> t).cterm)
1954 vf.push_back((<Term?> t).cterm)
1957 """Get the refutation proof
1961 .. code-block:: smtlib
1965 Requires to enable option
1966 :ref:`produce-proofs <lbl-option-produce-proofs>`.
1968 .. warning:: This method is experimental and may change in future
1971 :return: a string representing the proof, according to the value of
1974 return self.csolver.getProof()
1976 def getLearnedLiterals(self):
1977 """Get a list of literals that are entailed by the current set of assertions
1981 .. code-block:: smtlib
1983 ( get-learned-literals )
1985 .. warning:: This method is experimental and may change in future
1988 :return: the list of literals
1991 for a in self.csolver.getLearnedLiterals():
1997 def getAssertions(self):
1998 """Get the list of asserted formulas.
2002 .. code-block:: smtlib
2006 :return: the list of asserted formulas
2009 for a in self.csolver.getAssertions():
2012 assertions.append(term)
2015 def getInfo(self, str flag):
2017 Get info from the solver.
2021 .. code-block:: smtlib
2023 ( get-info <info_flag> )
2025 :param flag: the info flag
2028 return self.csolver.getInfo(flag.encode())
2030 def getOption(self, str option):
2031 """Get the value of a given option.
2035 .. code-block:: smtlib
2037 ( get-option <keyword> )
2039 :param option: the option for which the value is queried
2040 :return: a string representation of the option value
2042 return self.csolver.getOption(option.encode()).decode()
2044 def getOptionNames(self):
2045 """Get all option names that can be used with `setOption`, `getOption` and `getOptionInfo`.
2047 :return: all option names
2049 return [s.decode() for s in self.csolver.getOptionNames()]
2051 def getOptionInfo(self, str option):
2052 """Get some information about the given option. Check the `OptionInfo`
2053 class for more details on which information is available.
2055 :return: information about the given option
2057 # declare all the variables we may need later
2058 cdef c_OptionInfo.ValueInfo[c_bool] vib
2059 cdef c_OptionInfo.ValueInfo[string] vis
2060 cdef c_OptionInfo.NumberInfo[int64_t] nii
2061 cdef c_OptionInfo.NumberInfo[uint64_t] niu
2062 cdef c_OptionInfo.NumberInfo[double] nid
2063 cdef c_OptionInfo.ModeInfo mi
2065 oi = self.csolver.getOptionInfo(option.encode())
2066 # generic information
2068 'name': oi.name.decode(),
2069 'aliases': [s.decode() for s in oi.aliases],
2070 'setByUser': oi.setByUser,
2073 # now check which type is actually in the variant
2074 if c_holds[c_OptionInfo.VoidInfo](oi.valueInfo):
2077 elif c_holds[c_OptionInfo.ValueInfo[c_bool]](oi.valueInfo):
2080 vib = c_getVariant[c_OptionInfo.ValueInfo[c_bool]](oi.valueInfo)
2081 res['current'] = vib.currentValue
2082 res['default'] = vib.defaultValue
2083 elif c_holds[c_OptionInfo.ValueInfo[string]](oi.valueInfo):
2086 vis = c_getVariant[c_OptionInfo.ValueInfo[string]](oi.valueInfo)
2087 res['current'] = vis.currentValue.decode()
2088 res['default'] = vis.defaultValue.decode()
2089 elif c_holds[c_OptionInfo.NumberInfo[int64_t]](oi.valueInfo):
2092 nii = c_getVariant[c_OptionInfo.NumberInfo[int64_t]](oi.valueInfo)
2093 res['current'] = nii.currentValue
2094 res['default'] = nii.defaultValue
2095 res['minimum'] = nii.minimum.value() if nii.minimum.has_value() else None
2096 res['maximum'] = nii.maximum.value() if nii.maximum.has_value() else None
2097 elif c_holds[c_OptionInfo.NumberInfo[uint64_t]](oi.valueInfo):
2100 niu = c_getVariant[c_OptionInfo.NumberInfo[uint64_t]](oi.valueInfo)
2101 res['current'] = niu.currentValue
2102 res['default'] = niu.defaultValue
2103 res['minimum'] = niu.minimum.value() if niu.minimum.has_value() else None
2104 res['maximum'] = niu.maximum.value() if niu.maximum.has_value() else None
2105 elif c_holds[c_OptionInfo.NumberInfo[double]](oi.valueInfo):
2108 nid = c_getVariant[c_OptionInfo.NumberInfo[double]](oi.valueInfo)
2109 res['current'] = nid.currentValue
2110 res['default'] = nid.defaultValue
2111 res['minimum'] = nid.minimum.value() if nid.minimum.has_value() else None
2112 res['maximum'] = nid.maximum.value() if nid.maximum.has_value() else None
2113 elif c_holds[c_OptionInfo.ModeInfo](oi.valueInfo):
2115 res['type'] = 'mode'
2116 mi = c_getVariant[c_OptionInfo.ModeInfo](oi.valueInfo)
2117 res['current'] = mi.currentValue.decode()
2118 res['default'] = mi.defaultValue.decode()
2119 res['modes'] = [s.decode() for s in mi.modes]
2122 def getOptionNames(self):
2123 """Get all option names that can be used with `setOption`, `getOption` and `getOptionInfo`.
2124 :return: all option names
2127 for n in self.csolver.getOptionNames():
2128 result += [n.decode()]
2131 def getUnsatAssumptions(self):
2133 Get the set of unsat ("failed") assumptions.
2137 .. code-block:: smtlib
2139 ( get-unsat-assumptions )
2141 Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
2143 :return: the set of unsat assumptions.
2146 for a in self.csolver.getUnsatAssumptions():
2149 assumptions.append(term)
2152 def getUnsatCore(self):
2153 """Get the unsatisfiable core.
2157 .. code-block:: smtlib
2161 Requires to enable option :ref:`produce-unsat-cores <lbl-option-produce-unsat-cores>`.
2164 In contrast to SMT-LIB, the API does not distinguish between named and
2165 unnamed assertions when producing an unsatisfiable core. Additionally,
2166 the API allows this option to be called after a check with assumptions.
2167 A subset of those assumptions may be included in the unsatisfiable core
2168 returned by this method.
2170 :return: a set of terms representing the unsatisfiable core
2173 for a in self.csolver.getUnsatCore():
2179 def getDifficulty(self):
2181 Get a difficulty estimate for an asserted formula. This method is intended to be called immediately after
2182 any response to a checkSat.
2184 .. warning:: This method is experimental and may change in future
2187 :return: a map from (a subset of) the input assertions to a real value that is an estimate of how difficult each assertion was to solver. Unmentioned assertions can be assumed to have zero difficulty.
2190 for p in self.csolver.getDifficulty():
2200 diffi[termk] = termv
2203 def getValue(self, Term t):
2204 """Get the value of the given term in the current model.
2208 .. code-block:: smtlib
2210 ( get-value ( <term> ) )
2212 :param term: the term for which the value is queried
2213 :return: the value of the given term
2215 cdef Term term = Term(self)
2216 term.cterm = self.csolver.getValue(t.cterm)
2219 def getModelDomainElements(self, Sort s):
2221 Get the domain elements of uninterpreted sort s in the current model. The
2222 current model interprets s as the finite sort whose domain elements are
2223 given in the return value of this method.
2225 :param s: The uninterpreted sort in question
2226 :return: the domain elements of s in the current model
2229 cresult = self.csolver.getModelDomainElements(s.csort)
2236 def isModelCoreSymbol(self, Term v):
2238 This returns false if the model value of free constant v was not
2239 essential for showing the satisfiability of the last call to checkSat
2240 using the current model. This method will only return false (for any v)
2241 if the model-cores option has been set.
2243 .. warning:: This method is experimental and may change in future
2246 :param v: The term in question
2247 :return: true if v is a model core symbol
2249 return self.csolver.isModelCoreSymbol(v.cterm)
2251 def getQuantifierElimination(self, Term term):
2252 """Do quantifier elimination.
2256 .. code-block:: smtlib
2260 Requires a logic that supports quantifier elimination.
2261 Currently, the only logics supported by quantifier elimination
2264 .. warning:: This method is experimental and may change in future
2267 :param q: a quantified formula of the form
2268 :math:`Q\bar{x}_1... Q\bar{x}_n. P( x_1...x_i, y_1...y_j)'
2270 :math:'Q\bar{x}' is a set of quantified variables of the form
2271 :math:'Q x_1...x_k' and
2272 :math:'P( x_1...x_i, y_1...y_j )' is a quantifier-free formula
2273 :return: a formula :math:'\phi' such that, given the current set of formulas
2274 :math:'A asserted to this solver:
2275 - :math:'(A \wedge q)' :math:'(A \wedge \phi)' are equivalent
2276 - :math:'\phi' is quantifier-free formula containing only free
2277 variables in :math:'y_1...y_n'.
2279 cdef Term result = Term(self)
2280 result.cterm = self.csolver.getQuantifierElimination(term.cterm)
2283 def getQuantifierEliminationDisjunct(self, Term term):
2284 """Do partial quantifier elimination, which can be used for incrementally computing
2285 the result of a quantifier elimination.
2289 .. code-block:: smtlib
2291 ( get-qe-disjunct <q> )
2293 Requires a logic that supports quantifier elimination.
2294 Currently, the only logics supported by quantifier elimination
2297 .. warning:: This method is experimental and may change in future
2300 :param q: a quantified formula of the form
2301 @f$Q\bar{x}_1... Q\bar{x}_n. P( x_1...x_i, y_1...y_j)@f$
2303 @f$Q\bar{x}@f$ is a set of quantified variables of the form
2304 @f$Q x_1...x_k@f$ and
2305 @f$P( x_1...x_i, y_1...y_j )@f$ is a quantifier-free formula
2306 :return: a formula @f$\phi@f$ such that, given the current set of formulas
2307 @f$A@f$ asserted to this solver:
2308 - @f$(A \wedge q \implies A \wedge \phi)@f$ if @f$Q@f$ is
2309 @f$\forall@f$, and @f$(A \wedge \phi \implies A \wedge q)@f$ if
2310 @f$Q@f$ is @f$\exists@f$
2311 - @f$\phi@f$ is quantifier-free formula containing only free
2312 variables in @f$y_1...y_n@f$
2313 - If @f$Q@f$ is @f$\exists@f$, let @f$(A \wedge Q_n)@f$ be the
2315 @f$(A \wedge \neg (\phi \wedge Q_1) \wedge ... \wedge
2316 \neg (\phi \wedge Q_n))@f$
2317 where for each @f$i = 1...n@f$,
2318 formula @f$(\phi \wedge Q_i)@f$ is the result of calling
2319 Solver::getQuantifierEliminationDisjunct() for @f$q@f$ with the
2320 set of assertions @f$(A \wedge Q_{i-1})@f$.
2321 Similarly, if @f$Q@f$ is @f$\forall@f$, then let
2322 @f$(A \wedge Q_n)@f$ be
2323 @f$(A \wedge (\phi \wedge Q_1) \wedge ... \wedge (\phi \wedge
2325 where @f$(\phi \wedge Q_i)@f$ is the same as above.
2326 In either case, we have that @f$(\phi \wedge Q_j)@f$ will
2327 eventually be true or false, for some finite j.
2329 cdef Term result = Term(self)
2330 result.cterm = self.csolver.getQuantifierEliminationDisjunct(term.cterm)
2333 def getModel(self, sorts, consts):
2342 Requires to enable option
2343 :ref:`produce-models <lbl-option-produce-models>`.
2345 .. warning:: This method is experimental and may change in future
2348 :param sorts: The list of uninterpreted sorts that should be printed in
2350 :param vars: The list of free constants that should be printed in the
2351 model. A subset of these may be printed based on
2353 :return: a string representing the model.
2356 cdef vector[c_Sort] csorts
2358 csorts.push_back((<Sort?> sort).csort)
2360 cdef vector[c_Term] cconsts
2361 for const in consts:
2362 cconsts.push_back((<Term?> const).cterm)
2364 return self.csolver.getModel(csorts, cconsts)
2366 def getValueSepHeap(self):
2367 """When using separation logic, obtain the term for the heap.
2369 .. warning:: This method is experimental and may change in future
2372 :return: The term for the heap
2374 cdef Term term = Term(self)
2375 term.cterm = self.csolver.getValueSepHeap()
2378 def getValueSepNil(self):
2379 """When using separation logic, obtain the term for nil.
2381 .. warning:: This method is experimental and may change in future
2384 :return: The term for nil
2386 cdef Term term = Term(self)
2387 term.cterm = self.csolver.getValueSepNil()
2390 def declareSepHeap(self, Sort locType, Sort dataType):
2392 When using separation logic, this sets the location sort and the
2393 datatype sort to the given ones. This method should be invoked exactly
2394 once, before any separation logic constraints are provided.
2396 .. warning:: This method is experimental and may change in future
2399 :param locSort: The location sort of the heap
2400 :param dataSort: The data sort of the heap
2402 self.csolver.declareSepHeap(locType.csort, dataType.csort)
2404 def declarePool(self, str symbol, Sort sort, initValue):
2405 """Declare a symbolic pool of terms with the given initial value.
2409 .. code-block:: smtlib
2411 ( declare-pool <symbol> <sort> ( <term>* ) )
2413 .. warning:: This method is experimental and may change in future
2416 :param symbol: The name of the pool
2417 :param sort: The sort of the elements of the pool.
2418 :param initValue: The initial value of the pool
2420 cdef Term term = Term(self)
2421 cdef vector[c_Term] niv
2423 niv.push_back((<Term?> v).cterm)
2424 term.cterm = self.csolver.declarePool(symbol.encode(), sort.csort, niv)
2427 def pop(self, nscopes=1):
2428 """Pop ``nscopes`` level(s) from the assertion stack.
2432 .. code-block:: smtlib
2436 :param nscopes: the number of levels to pop
2438 self.csolver.pop(nscopes)
2440 def push(self, nscopes=1):
2441 """ Push ``nscopes`` level(s) to the assertion stack.
2445 .. code-block:: smtlib
2449 :param nscopes: the number of levels to push
2451 self.csolver.push(nscopes)
2453 def resetAssertions(self):
2455 Remove all assertions.
2459 .. code-block:: smtlib
2461 ( reset-assertions )
2464 self.csolver.resetAssertions()
2466 def setInfo(self, str keyword, str value):
2471 .. code-block:: smtlib
2473 ( set-info <attribute> )
2475 :param keyword: the info flag
2476 :param value: the value of the info flag
2478 self.csolver.setInfo(keyword.encode(), value.encode())
2480 def setLogic(self, str logic):
2485 .. code-block:: smtlib
2487 ( set-logic <symbol> )
2489 :param logic: the logic to set
2491 self.csolver.setLogic(logic.encode())
2493 def setOption(self, str option, str value):
2498 .. code-block:: smtlib
2500 ( set-option <option> )
2502 :param option: the option name
2503 :param value: the option value
2505 self.csolver.setOption(option.encode(), value.encode())
2508 def getInterpolant(self, Term conj, *args):
2509 """Get an interpolant.
2513 .. code-block:: smtlib
2515 ( get-interpolant <conj> )
2516 ( get-interpolant <conj> <grammar> )
2518 Requires option :ref:`produce-interpolants <lbl-option-produce-interpolants>` to be set to a mode different from `none`.
2520 Supports the following variants:
2522 - ``Term getInteprolant(Term conj)``
2523 - ``Term getInteprolant(Term conj, Grammar grammar)``
2525 .. warning:: This method is experimental and may change in future
2528 :param conj: the conjecture term
2529 :param output: the term where the result will be stored
2530 :param grammar: a grammar for the inteprolant
2531 :return: True iff an interpolant was found
2533 cdef Term result = Term(self)
2535 result.cterm = self.csolver.getInterpolant(conj.cterm)
2537 assert len(args) == 1
2538 assert isinstance(args[0], Grammar)
2539 result.cterm = self.csolver.getInterpolant(conj.cterm, (<Grammar ?> args[0]).cgrammar)
2543 def getInterpolantNext(self):
2545 Get the next interpolant. Can only be called immediately after
2546 a succesful call to get-interpolant or get-interpolant-next.
2547 Is guaranteed to produce a syntactically different interpolant wrt the
2548 last returned interpolant if successful.
2552 .. code-block:: smtlib
2554 ( get-interpolant-next )
2556 Requires to enable incremental mode, and
2557 option :ref:`produce-interpolants <lbl-option-produce-interpolants>` to be set to a mode different from `none`.
2559 .. warning:: This method is experimental and may change in future
2562 :param output: the term where the result will be stored
2563 :return: True iff an interpolant was found
2565 cdef Term result = Term(self)
2566 result.cterm = self.csolver.getInterpolantNext()
2569 def getAbduct(self, Term conj, *args):
2574 .. code-block:: smtlib
2576 ( get-abduct <conj> )
2577 ( get-abduct <conj> <grammar> )
2579 Requires to enable option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2581 Supports the following variants:
2583 - ``Term getAbduct(Term conj)``
2584 - ``Term getAbduct(Term conj, Grammar grammar)``
2586 .. warning:: This method is experimental and may change in future
2589 :param conj: the conjecture term
2590 :param output: the term where the result will be stored
2591 :param grammar: a grammar for the abduct
2592 :return: True iff an abduct was found
2594 cdef Term result = Term(self)
2596 result.cterm = self.csolver.getAbduct(conj.cterm)
2598 assert len(args) == 1
2599 assert isinstance(args[0], Grammar)
2600 result.cterm = self.csolver.getAbduct(conj.cterm, (<Grammar ?> args[0]).cgrammar)
2603 def getAbductNext(self):
2605 Get the next abduct. Can only be called immediately after
2606 a succesful call to get-abduct or get-abduct-next.
2607 Is guaranteed to produce a syntactically different abduct wrt the
2608 last returned abduct if successful.
2612 .. code-block:: smtlib
2616 Requires to enable incremental mode, and
2617 option :ref:`produce-abducts <lbl-option-produce-abducts>`.
2619 .. warning:: This method is experimental and may change in future
2622 :param output: the term where the result will be stored
2623 :return: True iff an abduct was found
2625 cdef Term result = Term(self)
2626 result.cterm = self.csolver.getAbductNext()
2629 def blockModel(self):
2631 Block the current model. Can be called only if immediately preceded by a
2632 SAT or INVALID query.
2636 .. code-block:: smtlib
2640 Requires enabling option
2641 :ref:`produce-models <lbl-option-produce-models>`
2643 :ref:`block-models <lbl-option-block-models>`
2644 to a mode other than ``none``.
2646 .. warning:: This method is experimental and may change in future
2649 self.csolver.blockModel()
2651 def blockModelValues(self, terms):
2653 Block the current model values of (at least) the values in terms. Can be
2654 called only if immediately preceded by a SAT or NOT_ENTAILED query.
2658 .. code-block:: smtlib
2660 (block-model-values ( <terms>+ ))
2662 Requires enabling option
2663 :ref:`produce-models <lbl-option-produce-models>`.
2665 .. warning:: This method is experimental and may change in future
2668 cdef vector[c_Term] nts
2670 nts.push_back((<Term?> t).cterm)
2671 self.csolver.blockModelValues(nts)
2673 def getInstantiations(self):
2675 Return a string that contains information about all instantiations made
2676 by the quantifiers module.
2678 .. warning:: This method is experimental and may change in future
2681 return self.csolver.getInstantiations()
2683 def getStatistics(self):
2685 Returns a snapshot of the current state of the statistic values of this
2686 solver. The returned object is completely decoupled from the solver and
2687 will not change when the solver is used again.
2690 res.cstats = self.csolver.getStatistics()
2696 The sort of a cvc5 term.
2700 def __cinit__(self, Solver solver):
2701 # csort always set by Solver
2702 self.solver = solver
2704 def __eq__(self, Sort other):
2705 return self.csort == other.csort
2707 def __ne__(self, Sort other):
2708 return self.csort != other.csort
2710 def __lt__(self, Sort other):
2711 return self.csort < other.csort
2713 def __gt__(self, Sort other):
2714 return self.csort > other.csort
2716 def __le__(self, Sort other):
2717 return self.csort <= other.csort
2719 def __ge__(self, Sort other):
2720 return self.csort >= other.csort
2723 return self.csort.toString().decode()
2726 return self.csort.toString().decode()
2729 return csorthash(self.csort)
2731 def hasSymbol(self):
2732 """:return: True iff this sort has a symbol."""
2733 return self.csort.hasSymbol()
2735 def getSymbol(self):
2737 Asserts :py:meth:`hasSymbol()`.
2739 :return: the raw symbol of the sort.
2741 return self.csort.getSymbol().decode()
2744 """:return: True if this Sort is a null sort."""
2745 return self.csort.isNull()
2747 def isBoolean(self):
2749 Is this a Boolean sort?
2751 :return: True if the sort is the Boolean sort.
2753 return self.csort.isBoolean()
2755 def isInteger(self):
2757 Is this an integer sort?
2759 :return: True if the sort is the integer sort.
2761 return self.csort.isInteger()
2765 Is this a real sort?
2767 :return: True if the sort is the real sort.
2769 return self.csort.isReal()
2773 Is this a string sort?
2775 :return: True if the sort is the string sort.
2777 return self.csort.isString()
2781 Is this a regexp sort?
2783 :return: True if the sort is the regexp sort.
2785 return self.csort.isRegExp()
2787 def isRoundingMode(self):
2789 Is this a rounding mode sort?
2791 :return: True if the sort is the rounding mode sort.
2793 return self.csort.isRoundingMode()
2795 def isBitVector(self):
2797 Is this a bit-vector sort?
2799 :return: True if the sort is a bit-vector sort.
2801 return self.csort.isBitVector()
2803 def isFloatingPoint(self):
2805 Is this a floating-point sort?
2807 :return: True if the sort is a bit-vector sort.
2809 return self.csort.isFloatingPoint()
2811 def isDatatype(self):
2813 Is this a datatype sort?
2815 :return: True if the sort is a datatype sort.
2817 return self.csort.isDatatype()
2819 def isConstructor(self):
2821 Is this a constructor sort?
2823 :return: True if the sort is a constructor sort.
2825 return self.csort.isConstructor()
2827 def isSelector(self):
2829 Is this a selector sort?
2831 :return: True if the sort is a selector sort.
2833 return self.csort.isSelector()
2837 Is this a tester sort?
2839 :return: True if the sort is a selector sort.
2841 return self.csort.isTester()
2843 def isUpdater(self):
2845 Is this a datatype updater sort?
2847 :return: True if the sort is a datatype updater sort.
2849 return self.csort.isUpdater()
2851 def isFunction(self):
2853 Is this a function sort?
2855 :return: True if the sort is a function sort.
2857 return self.csort.isFunction()
2859 def isPredicate(self):
2861 Is this a predicate sort?
2862 That is, is this a function sort mapping to Boolean? All predicate
2863 sorts are also function sorts.
2865 :return: True if the sort is a predicate sort.
2867 return self.csort.isPredicate()
2871 Is this a tuple sort?
2873 :return: True if the sort is a tuple sort.
2875 return self.csort.isTuple()
2879 Is this a record sort?
2881 .. warning:: This method is experimental and may change in future
2884 :return: True if the sort is a record sort.
2886 return self.csort.isRecord()
2890 Is this an array sort?
2892 :return: True if the sort is an array sort.
2894 return self.csort.isArray()
2900 :return: True if the sort is a set sort.
2902 return self.csort.isSet()
2908 :return: True if the sort is a bag sort.
2910 return self.csort.isBag()
2912 def isSequence(self):
2914 Is this a sequence sort?
2916 :return: True if the sort is a sequence sort.
2918 return self.csort.isSequence()
2920 def isUninterpretedSort(self):
2922 Is this a sort uninterpreted?
2924 :return: True if the sort is uninterpreted.
2926 return self.csort.isUninterpretedSort()
2928 def isUninterpretedSortConstructor(self):
2930 Is this a sort constructor kind?
2932 An uninterpreted sort constructor is an uninterpreted sort with
2935 :return: True if this a sort constructor kind.
2937 return self.csort.isUninterpretedSortConstructor()
2939 def isInstantiated(self):
2941 Is this an instantiated (parametric datatype or uninterpreted sort
2944 An instantiated sort is a sort that has been constructed from
2945 instantiating a sort parameters with sort arguments
2946 (see Sort::instantiate()).
2948 :return: True if this is an instantiated sort.
2950 return self.csort.isInstantiated()
2952 def getDatatype(self):
2954 :return: the underlying datatype of a datatype sort
2956 cdef Datatype d = Datatype(self.solver)
2957 d.cd = self.csort.getDatatype()
2960 def instantiate(self, params):
2962 Instantiate a parameterized datatype sort or uninterpreted sort
2964 Create sorts parameter with :py:meth:`Solver.mkParamSort()`
2966 .. warning:: This method is experimental and may change in future
2969 :param params: the list of sort parameters to instantiate with
2970 :return: the instantiated sort
2972 cdef Sort sort = Sort(self.solver)
2973 cdef vector[c_Sort] v
2975 v.push_back((<Sort?> s).csort)
2976 sort.csort = self.csort.instantiate(v)
2979 def getInstantiatedParameters(self):
2981 Get the sorts used to instantiate the sort parameters of a
2982 parametric sort (parametric datatype or uninterpreted sort
2983 constructor sort, see Sort.instantiate()).
2985 :return the sorts used to instantiate the sort parameters of a
2988 instantiated_sorts = []
2989 for s in self.csort.getInstantiatedParameters():
2990 sort = Sort(self.solver)
2992 instantiated_sorts.append(sort)
2993 return instantiated_sorts
2995 def substitute(self, sort_or_list_1, sort_or_list_2):
2997 Substitution of Sorts.
2999 Note that this replacement is applied during a pre-order traversal and
3000 only once to the sort. It is not run until fix point. In the case that
3001 sort_or_list_1 contains duplicates, the replacement earliest in the list
3005 ``(Array A B) .substitute([A, C], [(Array C D), (Array A B)])`` will
3006 return ``(Array (Array C D) B)``.
3008 .. warning:: This method is experimental and may change in future
3011 :param sort_or_list_1: the subsort or subsorts to be substituted within this sort.
3012 :param sort_or_list_2: the sort or list of sorts replacing the substituted subsort.
3015 # The resulting sort after substitution
3016 cdef Sort sort = Sort(self.solver)
3017 # lists for substitutions
3018 cdef vector[c_Sort] ces
3019 cdef vector[c_Sort] creplacements
3021 # normalize the input parameters to be lists
3022 if isinstance(sort_or_list_1, list):
3023 assert isinstance(sort_or_list_2, list)
3025 replacements = sort_or_list_2
3026 if len(es) != len(replacements):
3027 raise RuntimeError("Expecting list inputs to substitute to "
3028 "have the same length but got: "
3029 "{} and {}".format(len(es), len(replacements)))
3031 for e, r in zip(es, replacements):
3032 ces.push_back((<Sort?> e).csort)
3033 creplacements.push_back((<Sort?> r).csort)
3036 # add the single elements to the vectors
3037 ces.push_back((<Sort?> sort_or_list_1).csort)
3038 creplacements.push_back((<Sort?> sort_or_list_2).csort)
3040 # call the API substitute method with lists
3041 sort.csort = self.csort.substitute(ces, creplacements)
3045 def getConstructorArity(self):
3047 :return: the arity of a constructor sort.
3049 return self.csort.getConstructorArity()
3051 def getConstructorDomainSorts(self):
3053 :return: the domain sorts of a constructor sort
3056 for s in self.csort.getConstructorDomainSorts():
3057 sort = Sort(self.solver)
3059 domain_sorts.append(sort)
3062 def getConstructorCodomainSort(self):
3064 :return: the codomain sort of a constructor sort
3066 cdef Sort sort = Sort(self.solver)
3067 sort.csort = self.csort.getConstructorCodomainSort()
3070 def getSelectorDomainSort(self):
3072 :return: the domain sort of a selector sort
3074 cdef Sort sort = Sort(self.solver)
3075 sort.csort = self.csort.getSelectorDomainSort()
3078 def getSelectorCodomainSort(self):
3080 :return: the codomain sort of a selector sort
3082 cdef Sort sort = Sort(self.solver)
3083 sort.csort = self.csort.getSelectorCodomainSort()
3086 def getTesterDomainSort(self):
3088 :return: the domain sort of a tester sort
3090 cdef Sort sort = Sort(self.solver)
3091 sort.csort = self.csort.getTesterDomainSort()
3094 def getTesterCodomainSort(self):
3096 :return: the codomain sort of a tester sort, which is the Boolean sort
3098 cdef Sort sort = Sort(self.solver)
3099 sort.csort = self.csort.getTesterCodomainSort()
3102 def getFunctionArity(self):
3104 :return: the arity of a function sort
3106 return self.csort.getFunctionArity()
3108 def getFunctionDomainSorts(self):
3110 :return: the domain sorts of a function sort
3113 for s in self.csort.getFunctionDomainSorts():
3114 sort = Sort(self.solver)
3116 domain_sorts.append(sort)
3119 def getFunctionCodomainSort(self):
3121 :return: the codomain sort of a function sort
3123 cdef Sort sort = Sort(self.solver)
3124 sort.csort = self.csort.getFunctionCodomainSort()
3127 def getArrayIndexSort(self):
3129 :return: the array index sort of an array sort
3131 cdef Sort sort = Sort(self.solver)
3132 sort.csort = self.csort.getArrayIndexSort()
3135 def getArrayElementSort(self):
3137 :return: the array element sort of an array sort
3139 cdef Sort sort = Sort(self.solver)
3140 sort.csort = self.csort.getArrayElementSort()
3143 def getSetElementSort(self):
3145 :return: the element sort of a set sort
3147 cdef Sort sort = Sort(self.solver)
3148 sort.csort = self.csort.getSetElementSort()
3151 def getBagElementSort(self):
3153 :return: the element sort of a bag sort
3155 cdef Sort sort = Sort(self.solver)
3156 sort.csort = self.csort.getBagElementSort()
3159 def getSequenceElementSort(self):
3161 :return: the element sort of a sequence sort
3163 cdef Sort sort = Sort(self.solver)
3164 sort.csort = self.csort.getSequenceElementSort()
3167 def getUninterpretedSortConstructorArity(self):
3169 :return: the arity of a sort constructor sort
3171 return self.csort.getUninterpretedSortConstructorArity()
3173 def getBitVectorSize(self):
3175 :return: the bit-width of the bit-vector sort
3177 return self.csort.getBitVectorSize()
3179 def getFloatingPointExponentSize(self):
3181 :return: the bit-width of the exponent of the floating-point sort
3183 return self.csort.getFloatingPointExponentSize()
3185 def getFloatingPointSignificandSize(self):
3187 :return: the width of the significand of the floating-point sort
3189 return self.csort.getFloatingPointSignificandSize()
3191 def getDatatypeArity(self):
3193 :return: the arity of a datatype sort
3195 return self.csort.getDatatypeArity()
3197 def getTupleLength(self):
3199 :return: the length of a tuple sort
3201 return self.csort.getTupleLength()
3203 def getTupleSorts(self):
3205 :return: the element sorts of a tuple sort
3208 for s in self.csort.getTupleSorts():
3209 sort = Sort(self.solver)
3211 tuple_sorts.append(sort)
3215 cdef class Statistics:
3217 The cvc5 Statistics.
3218 Wrapper class for :cpp:class:`cvc5::Statistics`.
3219 Obtain a single statistic value using ``stats["name"]`` and a dictionary
3220 with all (visible) statistics using ``stats.get(internal=False, defaulted=False)``.
3222 cdef c_Statistics cstats
3224 cdef __stat_to_dict(self, const c_Stat& s):
3231 res = s.getString().decode()
3232 elif s.isHistogram():
3233 res = { h.first.decode(): h.second for h in s.getHistogram() }
3235 'defaulted': s.isDefault(),
3236 'internal': s.isInternal(),
3240 def __getitem__(self, str name):
3241 """Get the statistics information for the statistic called ``name``."""
3242 return self.__stat_to_dict(self.cstats.get(name.encode()))
3244 def get(self, bint internal = False, bint defaulted = False):
3245 """Get all statistics. See :cpp:class:`cvc5::Statistics::begin()` for more information."""
3246 cdef c_Statistics.iterator it = self.cstats.begin(internal, defaulted)
3247 cdef pair[string,c_Stat]* s
3249 while it != self.cstats.end():
3250 s = &dereference(it)
3251 res[s.first.decode()] = self.__stat_to_dict(s.second)
3259 Wrapper class for :cpp:class:`cvc5::Term`.
3263 def __cinit__(self, Solver solver):
3264 # cterm always set in the Solver object
3265 self.solver = solver
3267 def __eq__(self, Term other):
3268 return self.cterm == other.cterm
3270 def __ne__(self, Term other):
3271 return self.cterm != other.cterm
3273 def __lt__(self, Term other):
3274 return self.cterm < other.cterm
3276 def __gt__(self, Term other):
3277 return self.cterm > other.cterm
3279 def __le__(self, Term other):
3280 return self.cterm <= other.cterm
3282 def __ge__(self, Term other):
3283 return self.cterm >= other.cterm
3285 def __getitem__(self, int index):
3286 cdef Term term = Term(self.solver)
3288 term.cterm = self.cterm[index]
3290 raise ValueError("Expecting a non-negative integer or string")
3294 return self.cterm.toString().decode()
3297 return self.cterm.toString().decode()
3300 for ci in self.cterm:
3301 term = Term(self.solver)
3306 return ctermhash(self.cterm)
3308 def getNumChildren(self):
3309 """:return: the number of children of this term."""
3310 return self.cterm.getNumChildren()
3313 """:return: the id of this term."""
3314 return self.cterm.getId()
3317 """:return: the :py:class:`cvc5.Kind` of this term."""
3318 return Kind(<int> self.cterm.getKind())
3321 """:return: the :py:class:`cvc5.Sort` of this term."""
3322 cdef Sort sort = Sort(self.solver)
3323 sort.csort = self.cterm.getSort()
3326 def substitute(self, term_or_list_1, term_or_list_2):
3328 :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.
3330 Note that this replacement is applied during a pre-order traversal and
3331 only once to the term. It is not run until fix point. In the case that
3332 terms contains duplicates, the replacement earliest in the list takes
3333 priority. For example, calling substitute on ``f(x,y)`` with
3337 term_or_list_1 = [ x, z ], term_or_list_2 = [ g(z), w ]
3339 results in the term ``f(g(z),y)``.
3341 # The resulting term after substitution
3342 cdef Term term = Term(self.solver)
3343 # lists for substitutions
3344 cdef vector[c_Term] ces
3345 cdef vector[c_Term] creplacements
3347 # normalize the input parameters to be lists
3348 if isinstance(term_or_list_1, list):
3349 assert isinstance(term_or_list_2, list)
3351 replacements = term_or_list_2
3352 if len(es) != len(replacements):
3353 raise RuntimeError("Expecting list inputs to substitute to "
3354 "have the same length but got: "
3355 "{} and {}".format(len(es), len(replacements)))
3357 for e, r in zip(es, replacements):
3358 ces.push_back((<Term?> e).cterm)
3359 creplacements.push_back((<Term?> r).cterm)
3362 # add the single elements to the vectors
3363 ces.push_back((<Term?> term_or_list_1).cterm)
3364 creplacements.push_back((<Term?> term_or_list_2).cterm)
3366 # call the API substitute method with lists
3367 term.cterm = self.cterm.substitute(ces, creplacements)
3371 """:return: True iff this term has an operator."""
3372 return self.cterm.hasOp()
3376 .. note:: This is safe to call when :py:meth:`hasOp()` returns True.
3378 :return: the :py:class:`cvc5.Op` used to create this Term.
3380 cdef Op op = Op(self.solver)
3381 op.cop = self.cterm.getOp()
3384 def hasSymbol(self):
3385 """:return: True iff this term has a symbol."""
3386 return self.cterm.hasSymbol()
3388 def getSymbol(self):
3390 Asserts :py:meth:`hasSymbol()`.
3392 :return: the raw symbol of the term.
3394 return self.cterm.getSymbol().decode()
3397 """:return: True iff this term is a null term."""
3398 return self.cterm.isNull()
3404 :return: the Boolean negation of this term.
3406 cdef Term term = Term(self.solver)
3407 term.cterm = self.cterm.notTerm()
3410 def andTerm(self, Term t):
3414 :param t: a Boolean term
3415 :return: the conjunction of this term and the given term
3417 cdef Term term = Term(self.solver)
3418 term.cterm = self.cterm.andTerm((<Term> t).cterm)
3421 def orTerm(self, Term t):
3425 :param t: a Boolean term
3426 :return: the disjunction of this term and the given term
3428 cdef Term term = Term(self.solver)
3429 term.cterm = self.cterm.orTerm(t.cterm)
3432 def xorTerm(self, Term t):
3434 Boolean exclusive or.
3436 :param t: a Boolean term
3437 :return: the exclusive disjunction of this term and the given term
3439 cdef Term term = Term(self.solver)
3440 term.cterm = self.cterm.xorTerm(t.cterm)
3443 def eqTerm(self, Term t):
3447 :param t: a Boolean term
3448 :return: the Boolean equivalence of this term and the given term
3450 cdef Term term = Term(self.solver)
3451 term.cterm = self.cterm.eqTerm(t.cterm)
3454 def impTerm(self, Term t):
3456 Boolean Implication.
3458 :param t: a Boolean term
3459 :return: the implication of this term and the given term
3461 cdef Term term = Term(self.solver)
3462 term.cterm = self.cterm.impTerm(t.cterm)
3465 def iteTerm(self, Term then_t, Term else_t):
3467 If-then-else with this term as the Boolean condition.
3469 :param then_t: the `then` term
3470 :param else_t: the `else` term
3471 :return: the if-then-else term with this term as the Boolean condition
3473 cdef Term term = Term(self.solver)
3474 term.cterm = self.cterm.iteTerm(then_t.cterm, else_t.cterm)
3477 def isConstArray(self):
3478 """:return: True iff this term is a constant array."""
3479 return self.cterm.isConstArray()
3481 def getConstArrayBase(self):
3483 Asserts :py:meth:`isConstArray()`.
3485 :return: the base (element stored at all indicies) of this constant array
3487 cdef Term term = Term(self.solver)
3488 term.cterm = self.cterm.getConstArrayBase()
3491 def isBooleanValue(self):
3492 """:return: True iff this term is a Boolean value."""
3493 return self.cterm.isBooleanValue()
3495 def getBooleanValue(self):
3497 Asserts :py:meth:`isBooleanValue()`
3499 :return: the representation of a Boolean value as a native Boolean value.
3501 return self.cterm.getBooleanValue()
3503 def isStringValue(self):
3504 """:return: True iff this term is a string value."""
3505 return self.cterm.isStringValue()
3507 def getStringValue(self):
3509 Asserts :py:meth:`isStringValue()`.
3512 This method is not to be confused with :py:meth:`__str__()` which
3513 returns the term in some string representation, whatever data it
3516 :return: the string term as a native string value.
3518 cdef Py_ssize_t size
3519 cdef c_wstring s = self.cterm.getStringValue()
3520 return PyUnicode_FromWideChar(s.data(), s.size())
3522 def getRealOrIntegerValueSign(self):
3524 Get integer or real value sign. Must be called on integer or real values,
3525 or otherwise an exception is thrown.
3527 :return: 0 if this term is zero, -1 if this term is a negative real or
3528 integer value, 1 if this term is a positive real or integer
3531 return self.cterm.getRealOrIntegerValueSign()
3533 def isIntegerValue(self):
3534 """:return: True iff this term is an integer value."""
3535 return self.cterm.isIntegerValue()
3537 def getIntegerValue(self):
3539 Asserts :py:meth:`isIntegerValue()`.
3541 :return: the integer term as a native python integer.
3543 return int(self.cterm.getIntegerValue().decode())
3545 def isFloatingPointPosZero(self):
3546 """:return: True iff the term is the floating-point value for positive zero."""
3547 return self.cterm.isFloatingPointPosZero()
3549 def isFloatingPointNegZero(self):
3550 """:return: True iff the term is the floating-point value for negative zero."""
3551 return self.cterm.isFloatingPointNegZero()
3553 def isFloatingPointPosInf(self):
3554 """:return: True iff the term is the floating-point value for positive infinity."""
3555 return self.cterm.isFloatingPointPosInf()
3557 def isFloatingPointNegInf(self):
3558 """:return: True iff the term is the floating-point value for negative infinity."""
3559 return self.cterm.isFloatingPointNegInf()
3561 def isFloatingPointNaN(self):
3562 """:return: True iff the term is the floating-point value for not a number."""
3563 return self.cterm.isFloatingPointNaN()
3565 def isFloatingPointValue(self):
3566 """:return: True iff this term is a floating-point value."""
3567 return self.cterm.isFloatingPointValue()
3569 def getFloatingPointValue(self):
3571 Asserts :py:meth:`isFloatingPointValue()`.
3573 :return: the representation of a floating-point value as a tuple of the exponent width, the significand width and a bit-vector value.
3575 cdef c_tuple[uint32_t, uint32_t, c_Term] t = self.cterm.getFloatingPointValue()
3576 cdef Term term = Term(self.solver)
3577 term.cterm = get2(t)
3578 return (get0(t), get1(t), term)
3580 def isSetValue(self):
3582 A term is a set value if it is considered to be a (canonical) constant
3583 set value. A canonical set value is one whose AST is:
3588 (singleton c1) ... (union (singleton c_{n-1}) (singleton c_n))))
3590 where ``c1 ... cn`` are values ordered by id such that
3591 ``c1 > ... > cn`` (see also :cpp:func:`cvc5::Term::operator>()`).
3594 A universe set term ``(kind SET_UNIVERSE)`` is not considered to be
3597 :return: True if the term is a set value.
3599 return self.cterm.isSetValue()
3601 def getSetValue(self):
3603 Asserts :py:meth:`isSetValue()`.
3605 :return: the representation of a set value as a set of terms.
3608 for e in self.cterm.getSetValue():
3609 term = Term(self.solver)
3614 def isSequenceValue(self):
3615 """:return: True iff this term is a sequence value."""
3616 return self.cterm.isSequenceValue()
3618 def getSequenceValue(self):
3620 Asserts :py:meth:`isSequenceValue()`.
3623 It is usually necessary for sequences to call
3624 :py:meth:`Solver.simplify()` to turn a sequence that is constructed
3625 by, e.g., concatenation of unit sequences, into a sequence value.
3627 :return: the representation of a sequence value as a vector of terms.
3630 for e in self.cterm.getSequenceValue():
3631 term = Term(self.solver)
3636 def isCardinalityConstraint(self):
3638 .. warning:: This method is experimental and may change in future
3640 :return: True if the term is a cardinality constraint.
3642 return self.cterm.isCardinalityConstraint()
3644 def getCardinalityConstraint(self):
3646 .. warning:: This method is experimental and may change in future
3648 :return: the sort the cardinality constraint is for and its upper bound.
3650 cdef pair[c_Sort, uint32_t] p
3651 p = self.cterm.getCardinalityConstraint()
3652 cdef Sort sort = Sort(self.solver)
3653 sort.csort = p.first
3654 return (sort, p.second)
3657 def isUninterpretedSortValue(self):
3658 """:return: True iff this term is a value from an uninterpreted sort."""
3659 return self.cterm.isUninterpretedSortValue()
3661 def getUninterpretedSortValue(self):
3663 Asserts :py:meth:`isUninterpretedSortValue()`.
3665 :return: the representation of an uninterpreted value as a pair of its sort and its index.
3667 return self.cterm.getUninterpretedSortValue()
3669 def isTupleValue(self):
3670 """:return: True iff this term is a tuple value."""
3671 return self.cterm.isTupleValue()
3673 def isRoundingModeValue(self):
3674 """:return: True if the term is a floating-point rounding mode value."""
3675 return self.cterm.isRoundingModeValue()
3677 def getRoundingModeValue(self):
3679 Asserts isRoundingModeValue().
3680 :return: the floating-point rounding mode value held by the term.
3682 return RoundingMode(<int> self.cterm.getRoundingModeValue())
3684 def getTupleValue(self):
3686 Asserts :py:meth:`isTupleValue()`.
3688 :return: the representation of a tuple value as a vector of terms.
3691 for e in self.cterm.getTupleValue():
3692 term = Term(self.solver)
3697 def isRealValue(self):
3699 .. note:: A term of kind PI is not considered to be a real value.
3701 :return: True iff this term is a rational value.
3703 return self.cterm.isRealValue()
3705 def getRealValue(self):
3707 Asserts :py:meth:`isRealValue()`.
3709 :return: the representation of a rational value as a python Fraction.
3711 return Fraction(self.cterm.getRealValue().decode())
3713 def isBitVectorValue(self):
3714 """:return: True iff this term is a bit-vector value."""
3715 return self.cterm.isBitVectorValue()
3717 def getBitVectorValue(self, base = 2):
3719 Asserts :py:meth:`isBitVectorValue()`.
3720 Supported bases are 2 (bit string), 10 (decimal string) or 16 (hexdecimal string).
3722 :return: the representation of a bit-vector value in string representation.
3724 return self.cterm.getBitVectorValue(base).decode()
3726 def toPythonObj(self):
3728 Converts a constant value Term to a Python object.
3732 - Boolean -- returns a Python bool
3733 - Int -- returns a Python int
3734 - Real -- returns a Python Fraction
3735 - BV -- returns a Python int (treats BV as unsigned)
3736 - String -- returns a Python Unicode string
3737 - Array -- returns a Python dict mapping indices to values. the constant base is returned as the default value
3741 if self.isBooleanValue():
3742 return self.getBooleanValue()
3743 elif self.isIntegerValue():
3744 return self.getIntegerValue()
3745 elif self.isRealValue():
3746 return self.getRealValue()
3747 elif self.isBitVectorValue():
3748 return int(self.getBitVectorValue(), 2)
3749 elif self.isStringValue():
3750 return self.getStringValue()
3751 elif self.getSort().isArray():
3757 # Array models are represented as a series of store operations
3758 # on a constant array
3761 if t.getKind().value == c_Kind.STORE:
3763 keys.append(t[1].toPythonObj())
3764 values.append(t[2].toPythonObj())
3765 to_visit.append(t[0])
3767 assert t.getKind().value == c_Kind.CONST_ARRAY
3768 base_value = t.getConstArrayBase().toPythonObj()
3770 assert len(keys) == len(values)
3771 assert base_value is not None
3773 # put everything in a dictionary with the constant
3774 # base as the result for any index not included in the stores
3775 res = defaultdict(lambda : base_value)
3776 for k, v in zip(keys, values):
3782 # Generate unknown explanations
3783 cdef __unknown_explanations = {
3784 <int> REQUIRES_FULL_CHECK: "RequiresFullCheck",
3785 <int> INCOMPLETE: "Incomplete",
3786 <int> TIMEOUT: "Timeout",
3787 <int> RESOURCEOUT: "Resourceout",
3788 <int> MEMOUT: "Memout",
3789 <int> INTERRUPTED: "Interrupted",
3790 <int> NO_STATUS: "NoStatus",
3791 <int> UNSUPPORTED: "Unsupported",
3792 <int> OTHER: "Other",
3793 <int> UNKNOWN_REASON: "UnknownReason"
3796 mod_ref = sys.modules[__name__]
3797 for ue_int, name in __unknown_explanations.items():
3798 u = UnknownExplanation(ue_int)
3800 if name in dir(mod_ref):
3801 raise RuntimeError("Redefinition of Python UnknownExplanation %s."%name)
3803 setattr(mod_ref, name, u)