from collections import defaultdict, Set
from fractions import Fraction
+from functools import wraps
import sys
from libc.stdint cimport int32_t, int64_t, uint32_t, uint64_t
################################## DECORATORS #################################
def expand_list_arg(num_req_args=0):
- '''
+ """
Creates a decorator that looks at index num_req_args of the args,
if it's a list, it expands it before calling the function.
- '''
+ """
def decorator(func):
+ @wraps(func)
def wrapper(owner, *args):
if len(args) == num_req_args + 1 and \
isinstance(args[num_req_args], list):
def getKind(self):
return kind(<int> self.cop.getKind())
-
+
def isIndexed(self):
return self.cop.isIndexed()
cdef class Solver:
+ """Wrapper class for :cpp:class:`cvc5::api::Solver`."""
cdef c_Solver* csolver
def __cinit__(self):
del self.csolver
def getBooleanSort(self):
+ """:return: sort Boolean
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getBooleanSort()
return sort
def getIntegerSort(self):
+ """:return: sort Integer
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getIntegerSort()
return sort
def getNullSort(self):
+ """:return: sort null
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getNullSort()
return sort
def getRealSort(self):
+ """:return: sort Real
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getRealSort()
return sort
def getRegExpSort(self):
+ """:return: sort of RegExp
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getRegExpSort()
return sort
def getRoundingModeSort(self):
+ """:return: sort RoundingMode
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getRoundingModeSort()
return sort
def getStringSort(self):
+ """:return: sort String
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.getStringSort()
return sort
def mkArraySort(self, Sort indexSort, Sort elemSort):
+ """Create an array sort.
+
+ :param indexSort: the array index sort
+ :param elemSort: the array element sort
+ :return: the array sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkArraySort(indexSort.csort, elemSort.csort)
return sort
def mkBitVectorSort(self, uint32_t size):
+ """Create a bit-vector sort.
+
+ :param size: the bit-width of the bit-vector sort
+ :return: the bit-vector sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkBitVectorSort(size)
return sort
def mkFloatingPointSort(self, uint32_t exp, uint32_t sig):
+ """Create a floating-point sort.
+
+ :param exp: the bit-width of the exponent of the floating-point sort.
+ :param sig: the bit-width of the significand of the floating-point sort.
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkFloatingPointSort(exp, sig)
return sort
def mkDatatypeSort(self, DatatypeDecl dtypedecl):
+ """Create a datatype sort.
+
+ :param dtypedecl: the datatype declaration from which the sort is created
+ :return: the datatype sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkDatatypeSort(dtypedecl.cdd)
return sort
def mkDatatypeSorts(self, list dtypedecls, unresolvedSorts = None):
- """:return: A list of datatype sorts that correspond to dtypedecls and unresolvedSorts"""
+ """Create a vector of datatype sorts using unresolved sorts. The names of
+ the datatype declarations in dtypedecls must be distinct.
+
+ This method is called when the DatatypeDecl objects dtypedecls have been
+ built using "unresolved" sorts.
+
+ We associate each sort in unresolvedSorts with exacly one datatype from
+ dtypedecls. In particular, it must have the same name as exactly one
+ datatype declaration in dtypedecls.
+
+ When constructing datatypes, unresolved sorts are replaced by the datatype
+ sort constructed for the datatype declaration it is associated with.
+
+ :param dtypedecls: the datatype declarations from which the sort is created
+ :param unresolvedSorts: the list of unresolved sorts
+ :return: the datatype sorts
+ """
if unresolvedSorts == None:
unresolvedSorts = set([])
else:
return sorts
def mkFunctionSort(self, sorts, Sort codomain):
+ """ Create function sort.
+
+ :param sorts: the sort of the function arguments
+ :param codomain: the sort of the function return value
+ :return: the function sort
+ """
cdef Sort sort = Sort(self)
# populate a vector with dereferenced c_Sorts
return sort
def mkParamSort(self, symbolname):
+ """ Create a sort parameter.
+
+ :param symbol: the name of the sort
+ :return: the sort parameter
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkParamSort(symbolname.encode())
return sort
@expand_list_arg(num_req_args=0)
def mkPredicateSort(self, *sorts):
- '''
- Supports the following arguments:
- Sort mkPredicateSort(List[Sort] sorts)
+ """Create a predicate sort.
- where sorts can also be comma-separated arguments of
- type Sort
- '''
+ :param sorts: the list of sorts of the predicate, as a list or as distinct arguments.
+ :return: the predicate sort
+ """
cdef Sort sort = Sort(self)
cdef vector[c_Sort] v
for s in sorts:
@expand_list_arg(num_req_args=0)
def mkRecordSort(self, *fields):
- '''
- Supports the following arguments:
- Sort mkRecordSort(List[Tuple[str, Sort]] fields)
+ """Create a record sort
- where fields can also be comma-separated arguments of
- type Tuple[str, Sort]
- '''
+ :param fields: the list of fields of the record, as a list or as distinct arguments
+ :return: the record sort
+ """
cdef Sort sort = Sort(self)
cdef vector[pair[string, c_Sort]] v
cdef pair[string, c_Sort] p
return sort
def mkSetSort(self, Sort elemSort):
+ """Create a set sort.
+
+ :param elemSort: the sort of the set elements
+ :return: the set sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkSetSort(elemSort.csort)
return sort
def mkBagSort(self, Sort elemSort):
+ """Create a bag sort.
+
+ :param elemSort: the sort of the bag elements
+ :return: the bag sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkBagSort(elemSort.csort)
return sort
def mkSequenceSort(self, Sort elemSort):
+ """Create a sequence sort.
+
+ :param elemSort: the sort of the sequence elements
+ :return: the sequence sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkSequenceSort(elemSort.csort)
return sort
def mkUninterpretedSort(self, str name):
+ """Create an uninterpreted sort.
+
+ :param symbol: the name of the sort
+ :return: the uninterpreted sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.mkUninterpretedSort(name.encode())
return sort
def mkSortConstructorSort(self, str symbol, size_t arity):
+ """Create a sort constructor sort.
+
+ :param symbol: the symbol of the sort
+ :param arity: the arity of the sort
+ :return: the sort constructor sort
+ """
cdef Sort sort = Sort(self)
sort.csort =self.csolver.mkSortConstructorSort(symbol.encode(), arity)
return sort
@expand_list_arg(num_req_args=0)
def mkTupleSort(self, *sorts):
- '''
- Supports the following arguments:
- Sort mkTupleSort(List[Sort] sorts)
+ """Create a tuple sort.
- where sorts can also be comma-separated arguments of
- type Sort
- '''
+ :param sorts: of the elements of the tuple, as a list or as distinct arguments
+ :return: the tuple sort
+ """
cdef Sort sort = Sort(self)
cdef vector[c_Sort] v
for s in sorts:
@expand_list_arg(num_req_args=1)
def mkTerm(self, kind_or_op, *args):
- '''
- Supports the following arguments:
- Term mkTerm(Kind kind)
- Term mkTerm(Kind kind, Op child1, List[Term] children)
- Term mkTerm(Kind kind, List[Term] children)
-
- where List[Term] can also be comma-separated arguments
- '''
+ """
+ Supports the following arguments:
+
+ - ``Term mkTerm(Kind kind)``
+ - ``Term mkTerm(Kind kind, Op child1, List[Term] children)``
+ - ``Term mkTerm(Kind kind, List[Term] children)``
+
+ where ``List[Term]`` can also be comma-separated arguments
+ """
cdef Term term = Term(self)
cdef vector[c_Term] v
return term
def mkTuple(self, sorts, terms):
+ """Create a tuple term. Terms are automatically converted if sorts are compatible.
+
+ :param sorts: The sorts of the elements in the tuple
+ :param terms: The elements in the tuple
+ :return: the tuple Term
+ """
cdef vector[c_Sort] csorts
cdef vector[c_Term] cterms
@expand_list_arg(num_req_args=0)
def mkOp(self, kind k, *args):
- '''
+ """
Supports the following uses:
- Op mkOp(Kind kind)
- Op mkOp(Kind kind, Kind k)
- Op mkOp(Kind kind, const string& arg)
- Op mkOp(Kind kind, uint32_t arg)
- Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)
- '''
+
+ - ``Op mkOp(Kind kind)``
+ - ``Op mkOp(Kind kind, Kind k)``
+ - ``Op mkOp(Kind kind, const string& arg)``
+ - ``Op mkOp(Kind kind, uint32_t arg)``
+ - ``Op mkOp(Kind kind, uint32_t arg0, uint32_t arg1)``
+ """
cdef Op op = Op(self)
cdef vector[int] v
return op
def mkTrue(self):
+ """Create a Boolean true constant.
+
+ :return: the true constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkTrue()
return term
def mkFalse(self):
+ """Create a Boolean false constant.
+
+ :return: the false constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkFalse()
return term
def mkBoolean(self, bint val):
+ """Create a Boolean constant.
+
+ :return: the Boolean constant
+ :param val: the value of the constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkBoolean(val)
return term
def mkPi(self):
+ """Create a constant representing the number Pi.
+
+ :return: a constant representing Pi
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkPi()
return term
def mkInteger(self, val):
+ """Create an integer constant.
+
+ :param val: representation of the constant: either a string or integer
+ :return: a constant of sort Integer
+ """
cdef Term term = Term(self)
if isinstance(val, str):
term.cterm = self.csolver.mkInteger(<const string &> str(val).encode())
return term
def mkReal(self, val, den=None):
- '''
- Make a real number term.
-
- Really, makes a rational term.
-
- Can be used in various forms.
- * Given a string "N/D" constructs the corresponding rational.
- * Given a string "W.D" constructs the reduction of (W * P + D)/P, where
- P is the appropriate power of 10.
- * 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.
- * Given a string "W" or an integer, constructs that integer.
- * Given two strings and/or integers N and D, constructs N/D.
- '''
+ """Create a real constant.
+
+ :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.
+ :param: `den` if not None, the value is `val`/`den`
+ :return: a real term with literal value
+
+ Can be used in various forms:
+
+ - Given a string ``"N/D"`` constructs the corresponding rational.
+ - Given a string ``"W.D"`` constructs the reduction of ``(W * P + D)/P``, where ``P`` is the appropriate power of 10.
+ - 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``.
+ - Given a string ``"W"`` or an integer, constructs that integer.
+ - Given two strings and/or integers ``N`` and ``D``, constructs ``N/D``.
+ """
cdef Term term = Term(self)
if den is None:
term.cterm = self.csolver.mkReal(str(val).encode())
return term
def mkRegexpEmpty(self):
+ """Create a regular expression empty term.
+
+ :return: the empty term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkRegexpEmpty()
return term
def mkRegexpSigma(self):
+ """Create a regular expression sigma term.
+
+ :return: the sigma term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkRegexpSigma()
return term
def mkEmptySet(self, Sort s):
+ """Create a constant representing an empty set of the given sort.
+
+ :param sort: the sort of the set elements.
+ :return: the empty set constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkEmptySet(s.csort)
return term
def mkEmptyBag(self, Sort s):
+ """Create a constant representing an empty bag of the given sort.
+
+ :param sort: the sort of the bag elements.
+ :return: the empty bag constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkEmptyBag(s.csort)
return term
def mkSepNil(self, Sort sort):
+ """Create a separation logic nil term.
+
+ :param sort: the sort of the nil term
+ :return: the separation logic nil term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkSepNil(sort.csort)
return term
def mkString(self, str s, useEscSequences = None):
+ """Create a String constant from a `str` which may contain SMT-LIB
+ compatible escape sequences like ``\\u1234`` to encode unicode characters.
+
+ :param s: the string this constant represents
+ :param useEscSequences: determines whether escape sequences in `s` should be converted to the corresponding unicode character
+ :return: the String constant
+ """
cdef Term term = Term(self)
cdef Py_ssize_t size
cdef wchar_t* tmp = PyUnicode_AsWideCharString(s, &size)
return term
def mkEmptySequence(self, Sort sort):
+ """Create an empty sequence of the given element sort.
+
+ :param sort: The element sort of the sequence.
+ :return: the empty sequence with given element sort.
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkEmptySequence(sort.csort)
return term
def mkUniverseSet(self, Sort sort):
+ """Create a universe set of the given sort.
+
+ :param sort: the sort of the set elements
+ :return: the universe set constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkUniverseSet(sort.csort)
return term
@expand_list_arg(num_req_args=0)
def mkBitVector(self, *args):
- '''
- Supports the following arguments:
- Term mkBitVector(int size, int val=0)
- Term mkBitVector(int size, string val, int base)
- '''
+ """
+ Supports the following arguments:
+
+ - ``Term mkBitVector(int size, int val=0)``
+ - ``Term mkBitVector(int size, string val, int base)``
+
+ :return: a bit-vector literal term
+ :param: `size` an integer size.
+ :param: `val` an integer representating the value, in the first form. In the second form, a string representing the value.
+ :param: `base` the base of the string representation (second form only)
+ """
cdef Term term = Term(self)
if len(args) == 0:
raise ValueError("Missing arguments to mkBitVector")
return term
def mkConstArray(self, Sort sort, Term val):
+ """ Create a constant array with the provided constant value stored at every
+ index
+
+ :param sort: the sort of the constant array (must be an array sort)
+ :param val: the constant value to store (must match the sort's element sort)
+ :return: the constant array term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkConstArray(sort.csort, val.cterm)
return term
def mkPosInf(self, int exp, int sig):
+ """Create a positive infinity floating-point constant.
+
+ :param exp: Number of bits in the exponent
+ :param sig: Number of bits in the significand
+ :return: the floating-point constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkPosInf(exp, sig)
return term
def mkNegInf(self, int exp, int sig):
+ """Create a negative infinity floating-point constant.
+
+ :param exp: Number of bits in the exponent
+ :param sig: Number of bits in the significand
+ :return: the floating-point constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkNegInf(exp, sig)
return term
def mkNaN(self, int exp, int sig):
+ """Create a not-a-number (NaN) floating-point constant.
+
+ :param exp: Number of bits in the exponent
+ :param sig: Number of bits in the significand
+ :return: the floating-point constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkNaN(exp, sig)
return term
def mkPosZero(self, int exp, int sig):
+ """Create a positive zero (+0.0) floating-point constant.
+
+ :param exp: Number of bits in the exponent
+ :param sig: Number of bits in the significand
+ :return: the floating-point constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkPosZero(exp, sig)
return term
def mkNegZero(self, int exp, int sig):
+ """Create a negative zero (+0.0) floating-point constant.
+
+ :param exp: Number of bits in the exponent
+ :param sig: Number of bits in the significand
+ :return: the floating-point constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkNegZero(exp, sig)
return term
def mkRoundingMode(self, RoundingMode rm):
+ """Create a roundingmode constant.
+
+ :param rm: the floating point rounding mode this constant represents
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkRoundingMode(<c_RoundingMode> rm.crm)
return term
def mkUninterpretedConst(self, Sort sort, int index):
+ """Create uninterpreted constant.
+
+ :param sort: Sort of the constant
+ :param index: Index of the constant
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkUninterpretedConst(sort.csort, index)
return term
def mkAbstractValue(self, index):
+ """Create an abstract value constant.
+ The given index needs to be positive.
+
+ :param index: Index of the abstract value
+ """
cdef Term term = Term(self)
try:
term.cterm = self.csolver.mkAbstractValue(str(index).encode())
return term
def mkFloatingPoint(self, int exp, int sig, Term val):
+ """Create a floating-point constant.
+
+ :param exp: Size of the exponent
+ :param sig: Size of the significand
+ :param val: Value of the floating-point constant as a bit-vector term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkFloatingPoint(exp, sig, val.cterm)
return term
def mkConst(self, Sort sort, symbol=None):
+ """
+ Create (first-order) constant (0-arity function symbol).
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( declare-const <symbol> <sort> )
+ ( declare-fun <symbol> ( ) <sort> )
+
+ :param sort: the sort of the constant
+ :param symbol: the name of the constant. If None, a default symbol is used.
+ :return: the first-order constant
+ """
cdef Term term = Term(self)
if symbol is None:
term.cterm = self.csolver.mkConst(sort.csort)
return term
def mkVar(self, Sort sort, symbol=None):
+ """Create a bound variable to be used in a binder (i.e. a quantifier, a
+ lambda, or a witness binder).
+
+ :param sort: the sort of the variable
+ :param symbol: the name of the variable
+ :return: the variable
+ """
cdef Term term = Term(self)
if symbol is None:
term.cterm = self.csolver.mkVar(sort.csort)
return term
def mkDatatypeConstructorDecl(self, str name):
+ """ :return: a datatype constructor declaration
+ :param: `name` the constructor's name
+ """
cdef DatatypeConstructorDecl ddc = DatatypeConstructorDecl(self)
ddc.cddc = self.csolver.mkDatatypeConstructorDecl(name.encode())
return ddc
def mkDatatypeDecl(self, str name, sorts_or_bool=None, isCoDatatype=None):
+ """Create a datatype declaration.
+
+ :param name: the name of the datatype
+ :param isCoDatatype: true if a codatatype is to be constructed
+ :return: the DatatypeDecl
+ """
cdef DatatypeDecl dd = DatatypeDecl(self)
cdef vector[c_Sort] v
return dd
def simplify(self, Term t):
+ """Simplify a formula without doing "much" work. Does not involve the
+ SAT Engine in the simplification, but uses the current definitions,
+ assertions, and the current partial model, if one has been constructed.
+ It also involves theory normalization.
+
+ :param t: the formula to simplify
+ :return: the simplified formula
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.simplify(t.cterm)
return term
def assertFormula(self, Term term):
+ """ Assert a formula
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( assert <term> )
+
+ :param term: the formula to assert
+ """
self.csolver.assertFormula(term.cterm)
def checkSat(self):
+ """
+ Check satisfiability.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( check-sat )
+
+ :return: the result of the satisfiability check.
+ """
cdef Result r = Result()
r.cr = self.csolver.checkSat()
return r
def mkSygusGrammar(self, boundVars, ntSymbols):
+ """Create a SyGuS grammar. The first non-terminal is treated as the
+ starting non-terminal, so the order of non-terminals matters.
+
+ :param boundVars: the parameters to corresponding synth-fun/synth-inv
+ :param ntSymbols: the pre-declaration of the non-terminal symbols
+ :return: the grammar
+ """
cdef Grammar grammar = Grammar(self)
cdef vector[c_Term] bvc
cdef vector[c_Term] ntc
return grammar
def mkSygusVar(self, Sort sort, str symbol=""):
+ """Append symbol to the current list of universal variables.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( declare-var <symbol> <sort> )
+
+ :param sort: the sort of the universal variable
+ :param symbol: the name of the universal variable
+ :return: the universal variable
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.mkSygusVar(sort.csort, symbol.encode())
return term
def addSygusConstraint(self, Term t):
+ """
+ Add a formula to the set of SyGuS constraints.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( constraint <term> )
+
+ :param term: the formula to add as a constraint
+ """
self.csolver.addSygusConstraint(t.cterm)
def addSygusInvConstraint(self, Term inv_f, Term pre_f, Term trans_f, Term post_f):
+ """Add a set of SyGuS constraints to the current state that correspond to an
+ invariant synthesis problem.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( inv-constraint <inv> <pre> <trans> <post> )
+
+ :param inv: the function-to-synthesize
+ :param pre: the pre-condition
+ :param trans: the transition relation
+ :param post: the post-condition
+ """
self.csolver.addSygusInvConstraint(inv_f.cterm, pre_f.cterm, trans_f.cterm, post_f.cterm)
def synthFun(self, str symbol, bound_vars, Sort sort, Grammar grammar=None):
+ """
+ Synthesize n-ary function following specified syntactic constraints.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( synth-fun <symbol> ( <boundVars>* ) <sort> <g> )
+
+ :param symbol: the name of the function
+ :param boundVars: the parameters to this function
+ :param sort: the sort of the return value of this function
+ :param grammar: the syntactic constraints
+ :return: the function
+ """
cdef Term term = Term(self)
cdef vector[c_Term] v
for bv in bound_vars:
return term
def checkSynth(self):
+ """
+ Try to find a solution for the synthesis conjecture corresponding to the
+ current list of functions-to-synthesize, universal variables and
+ constraints.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( check-synth )
+
+ :return: the result of the synthesis conjecture.
+ """
cdef Result r = Result()
r.cr = self.csolver.checkSynth()
return r
def getSynthSolution(self, Term term):
+ """Get the synthesis solution of the given term. This method should be
+ called immediately after the solver answers unsat for sygus input.
+
+ :param term: the term for which the synthesis solution is queried
+ :return: the synthesis solution of the given term
+ """
cdef Term t = Term(self)
t.cterm = self.csolver.getSynthSolution(term.cterm)
return t
def getSynthSolutions(self, list terms):
+ """Get the synthesis solutions of the given terms. This method should be
+ called immediately after the solver answers unsat for sygus input.
+
+ :param terms: the terms for which the synthesis solutions is queried
+ :return: the synthesis solutions of the given terms
+ """
result = []
cdef vector[c_Term] vec
for t in terms:
def synthInv(self, symbol, bound_vars, Grammar grammar=None):
+ """
+ Synthesize invariant.
+
+ SyGuS v2:
+
+ .. code-block:: smtlib
+
+ ( synth-inv <symbol> ( <boundVars>* ) <grammar> )
+
+ :param symbol: the name of the invariant
+ :param boundVars: the parameters to this invariant
+ :param grammar: the syntactic constraints
+ :return: the invariant
+ """
cdef Term term = Term(self)
cdef vector[c_Term] v
for bv in bound_vars:
@expand_list_arg(num_req_args=0)
def checkSatAssuming(self, *assumptions):
- '''
- Supports the following arguments:
- Result checkSatAssuming(List[Term] assumptions)
+ """ Check satisfiability assuming the given formula.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( check-sat-assuming ( <prop_literal> ) )
- where assumptions can also be comma-separated arguments of
- type (boolean) Term
- '''
+ :param assumptions: the formulas to assume, as a list or as distinct arguments
+ :return: the result of the satisfiability check.
+ """
cdef Result r = Result()
# used if assumptions is a list of terms
cdef vector[c_Term] v
@expand_list_arg(num_req_args=0)
def checkEntailed(self, *assumptions):
- '''
- Supports the following arguments:
- Result checkEntailed(List[Term] assumptions)
+ """Check entailment of the given formula w.r.t. the current set of assertions.
- where assumptions can also be comma-separated arguments of
- type (boolean) Term
- '''
+ :param terms: the formulas to check entailment for, as a list or as distinct arguments
+ :return: the result of the entailment check.
+ """
cdef Result r = Result()
# used if assumptions is a list of terms
cdef vector[c_Term] v
@expand_list_arg(num_req_args=1)
def declareDatatype(self, str symbol, *ctors):
- '''
- Supports the following arguments:
- Sort declareDatatype(str symbol, List[Term] ctors)
+ """
+ Create datatype sort.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
- where ctors can also be comma-separated arguments of
- type DatatypeConstructorDecl
- '''
+ ( declare-datatype <symbol> <datatype_decl> )
+
+ :param symbol: the name of the datatype sort
+ :param ctors: the constructor declarations of the datatype sort, as a list or as distinct arguments
+ :return: the datatype sort
+ """
cdef Sort sort = Sort(self)
cdef vector[c_DatatypeConstructorDecl] v
return sort
def declareFun(self, str symbol, list sorts, Sort sort):
+ """Declare n-ary function symbol.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( declare-fun <symbol> ( <sort>* ) <sort> )
+
+ :param symbol: the name of the function
+ :param sorts: the sorts of the parameters to this function
+ :param sort: the sort of the return value of this function
+ :return: the function
+ """
cdef Term term = Term(self)
cdef vector[c_Sort] v
for s in sorts:
return term
def declareSort(self, str symbol, int arity):
+ """Declare uninterpreted sort.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( declare-sort <symbol> <numeral> )
+
+ :param symbol: the name of the sort
+ :param arity: the arity of the sort
+ :return: the sort
+ """
cdef Sort sort = Sort(self)
sort.csort = self.csolver.declareSort(symbol.encode(), arity)
return sort
def defineFun(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
- '''
+ """
+ Define n-ary function.
Supports two uses:
- Term defineFun(str symbol, List[Term] bound_vars,
- Sort sort, Term term, bool glbl)
- Term defineFun(Term fun, List[Term] bound_vars,
- Term term, bool glbl)
- '''
+
+ - ``Term defineFun(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
+ - ``Term defineFun(Term fun, List[Term] bound_vars, Term term, bool glbl)``
+
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( define-fun <function_def> )
+
+ :param symbol: the name of the function
+ :param bound_vars: the parameters to this function
+ :param sort: the sort of the return value of this function
+ :param term: the function body
+ :param global: determines whether this definition is global (i.e. persists when popping the context)
+ :return: the function
+ """
cdef Term term = Term(self)
cdef vector[c_Term] v
for bv in bound_vars:
return term
def defineFunRec(self, sym_or_fun, bound_vars, sort_or_term, t=None, glbl=False):
- '''
+ """Define recursive functions.
+
Supports two uses:
- Term defineFunRec(str symbol, List[Term] bound_vars,
- Sort sort, Term term, bool glbl)
- Term defineFunRec(Term fun, List[Term] bound_vars,
- Term term, bool glbl)
- '''
+
+ - ``Term defineFunRec(str symbol, List[Term] bound_vars, Sort sort, Term term, bool glbl)``
+ - ``Term defineFunRec(Term fun, List[Term] bound_vars, Term term, bool glbl)``
+
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
+
+ Create elements of parameter ``funs`` with mkConst().
+
+ :param funs: the sorted functions
+ :param bound_vars: the list of parameters to the functions
+ :param terms: the list of function bodies of the functions
+ :param global: determines whether this definition is global (i.e. persists when popping the context)
+ :return: the function
+ """
cdef Term term = Term(self)
cdef vector[c_Term] v
for bv in bound_vars:
return term
def defineFunsRec(self, funs, bound_vars, terms):
+ """Define recursive functions.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( define-funs-rec ( <function_decl>^n ) ( <term>^n ) )
+
+ Create elements of parameter ``funs`` with mkConst().
+
+ :param funs: the sorted functions
+ :param bound_vars: the list of parameters to the functions
+ :param terms: the list of function bodies of the functions
+ :param global: determines whether this definition is global (i.e. persists when popping the context)
+ :return: the function
+ """
cdef vector[c_Term] vf
cdef vector[vector[c_Term]] vbv
cdef vector[c_Term] vt
vf.push_back((<Term?> t).cterm)
def getAssertions(self):
+ """Get the list of asserted formulas.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-assertions )
+
+ :return: the list of asserted formulas
+ """
assertions = []
for a in self.csolver.getAssertions():
term = Term(self)
return assertions
def getInfo(self, str flag):
+ """Get info from the solver.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-info <info_flag> )
+
+ :param flag: the info flag
+ :return: the info
+ """
return self.csolver.getInfo(flag.encode())
def getOption(self, str option):
+ """Get the value of a given option.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-option <keyword> )
+
+ :param option: the option for which the value is queried
+ :return: a string representation of the option value
+ """
return self.csolver.getOption(option.encode())
def getUnsatAssumptions(self):
+ """
+ Get the set of unsat ("failed") assumptions.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-unsat-assumptions )
+
+ Requires to enable option :ref:`produce-unsat-assumptions <lbl-option-produce-unsat-assumptions>`.
+
+ :return: the set of unsat assumptions.
+ """
assumptions = []
for a in self.csolver.getUnsatAssumptions():
term = Term(self)
return assumptions
def getUnsatCore(self):
+ """Get the unsatisfiable core.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-unsat-core )
+
+ Requires to enable option :ref:`produce-unsat-cores <lbl-produce-unsat-cores>`.
+
+ :return: a set of terms representing the unsatisfiable core
+ """
core = []
for a in self.csolver.getUnsatCore():
term = Term(self)
return core
def getValue(self, Term t):
+ """Get the value of the given term in the current model.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( get-value ( <term> ) )
+
+ :param term: the term for which the value is queried
+ :return: the value of the given term
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.getValue(t.cterm)
return term
def getModelDomainElements(self, Sort s):
+ """
+ Get the domain elements of uninterpreted sort s in the current model. The
+ current model interprets s as the finite sort whose domain elements are
+ given in the return value of this method.
+
+ :param s: The uninterpreted sort in question
+ :return: the domain elements of s in the current model
+ """
result = []
cresult = self.csolver.getModelDomainElements(s.csort)
for e in cresult:
return result
def isModelCoreSymbol(self, Term v):
+ """This returns false if the model value of free constant v was not
+ essential for showing the satisfiability of the last call to checkSat
+ using the current model. This method will only return false (for any v)
+ if the model-cores option has been set.
+
+ :param v: The term in question
+ :return: true if v is a model core symbol
+ """
return self.csolver.isModelCoreSymbol(v.cterm)
def getSeparationHeap(self):
+ """When using separation logic, obtain the term for the heap.
+
+ :return: The term for the heap
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.getSeparationHeap()
return term
- def declareSeparationHeap(self, Sort locType, Sort dataType):
- self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
-
def getSeparationNilTerm(self):
+ """When using separation logic, obtain the term for nil.
+
+ :return: The term for nil
+ """
cdef Term term = Term(self)
term.cterm = self.csolver.getSeparationNilTerm()
return term
+ def declareSeparationHeap(self, Sort locType, Sort dataType):
+ """
+ When using separation logic, this sets the location sort and the
+ datatype sort to the given ones. This method should be invoked exactly
+ once, before any separation logic constraints are provided.
+
+ :param locSort: The location sort of the heap
+ :param dataSort: The data sort of the heap
+ """
+ self.csolver.declareSeparationHeap(locType.csort, dataType.csort)
+
def declarePool(self, str symbol, Sort sort, initValue):
+ """Declare a symbolic pool of terms with the given initial value.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( declare-pool <symbol> <sort> ( <term>* ) )
+
+ :param symbol: The name of the pool
+ :param sort: The sort of the elements of the pool.
+ :param initValue: The initial value of the pool
+ """
cdef Term term = Term(self)
cdef vector[c_Term] niv
for v in initValue:
return term
def pop(self, nscopes=1):
+ """Pop ``nscopes`` level(s) from the assertion stack.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( pop <numeral> )
+
+ :param nscopes: the number of levels to pop
+ """
self.csolver.pop(nscopes)
def push(self, nscopes=1):
+ """ Push ``nscopes`` level(s) to the assertion stack.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( push <numeral> )
+
+ :param nscopes: the number of levels to push
+ """
self.csolver.push(nscopes)
def resetAssertions(self):
+ """
+ Remove all assertions.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( reset-assertions )
+
+ """
self.csolver.resetAssertions()
def setInfo(self, str keyword, str value):
+ """Set info.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( set-info <attribute> )
+
+ :param keyword: the info flag
+ :param value: the value of the info flag
+ """
self.csolver.setInfo(keyword.encode(), value.encode())
def setLogic(self, str logic):
+ """Set logic.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( set-logic <symbol> )
+
+ :param logic: the logic to set
+ """
self.csolver.setLogic(logic.encode())
def setOption(self, str option, str value):
+ """Set option.
+
+ SMT-LIB:
+
+ .. code-block:: smtlib
+
+ ( set-option <option> )
+
+ :param option: the option name
+ :param value: the option value
+ """
self.csolver.setOption(option.encode(), value.encode())
def isBag(self):
return self.csort.isBag()
-
+
def isSequence(self):
return self.csort.isSequence()
cdef Sort sort = Sort(self.solver)
sort.csort = self.csort.getTesterCodomainSort()
return sort
-
+
def getFunctionArity(self):
return self.csort.getFunctionArity()
# lists for substitutions
cdef vector[c_Term] ces
cdef vector[c_Term] creplacements
-
+
# normalize the input parameters to be lists
if isinstance(term_or_list_1, list):
assert isinstance(term_or_list_2, list)
# add the single elements to the vectors
ces.push_back((<Term?> term_or_list_1).cterm)
creplacements.push_back((<Term?> term_or_list_2).cterm)
-
+
# call the API substitute method with lists
term.cterm = self.cterm.substitute(ces, creplacements)
return term
def isFloatingPointPosZero(self):
return self.cterm.isFloatingPointPosZero()
-
+
def isFloatingPointNegZero(self):
return self.cterm.isFloatingPointNegZero()
-
+
def isFloatingPointPosInf(self):
return self.cterm.isFloatingPointPosInf()
-
+
def isFloatingPointNegInf(self):
return self.cterm.isFloatingPointNegInf()
-
+
def isFloatingPointNaN(self):
return self.cterm.isFloatingPointNaN()
-
+
def isFloatingPointValue(self):
return self.cterm.isFloatingPointValue()
def isUninterpretedValue(self):
return self.cterm.isUninterpretedValue()
-
+
def getUninterpretedValue(self):
cdef pair[c_Sort, int32_t] p = self.cterm.getUninterpretedValue()
cdef Sort sort = Sort(self.solver)
return self.cterm.isRealValue()
def getRealValue(self):
- '''Returns the value of a real term as a Fraction'''
+ """Returns the value of a real term as a Fraction"""
return Fraction(self.cterm.getRealValue().decode())
def isBitVectorValue(self):
return self.cterm.isBitVectorValue()
def getBitVectorValue(self, base = 2):
- '''Returns the value of a bit-vector term as a 0/1 string'''
+ """Returns the value of a bit-vector term as a 0/1 string"""
return self.cterm.getBitVectorValue(base).decode()
def toPythonObj(self):
- '''
+ """
Converts a constant value Term to a Python object.
Currently supports:
String -- returns a Python Unicode string
Array -- returns a Python dict mapping indices to values
-- the constant base is returned as the default value
- '''
+ """
if self.isBooleanValue():
return self.getBooleanValue()