def back(self, expr): res = None if expr.isConst(): if expr.getType().isBoolean(): v = expr.getConstBoolean() res = self.mgr.Bool(v) elif expr.getType().isInteger(): v = expr.getConstRational().toString() res = self.mgr.Int(int(v)) elif expr.getType().isReal(): v = expr.getConstRational().toString() res = self.mgr.Real(Fraction(v)) elif expr.getType().isBitVector(): bv = expr.getConstBitVector() v = bv.getValue().toString() width = bv.getSize() res = self.mgr.BV(int(v), width) elif expr.getType().isString(): v = expr.getConstString() res = self.mgr.String(v.toString()) elif expr.getType().isArray(): const_ = expr.getConstArrayStoreAll() array_type = self._cvc4_type_to_type(const_.getType()) base_value = self.back(const_.getExpr()) res = self.mgr.Array(array_type.index_type, base_value) else: raise PyomtTypeError("Unsupported constant type:", expr.getType().toString()) else: raise PyomtTypeError("Unsupported expression:", expr.toString()) return res
def substitute(self, formula, subs): """Replaces any subformula in formula with the definition in subs.""" # Check that formula is a term if not formula.is_term(): raise PyomtTypeError("substitute() can only be used on terms.") for (i, k) in enumerate(subs): v = subs[k] # Check that substitutions are terms if not k.is_term(): raise PyomtTypeError( "Only terms should be provided as substitutions." + " Non-term '%s' found." % k) if not v.is_term(): raise PyomtTypeError( "Only terms should be provided as substitutions." + " Non-term '%s' found." % v) # Check that substitutions belong to the current formula manager if k not in self.manager: raise PyomtTypeError( "Key %d does not belong to the Formula Manager." % i) if v not in self.manager: raise PyomtTypeError( "Value %d does not belong to the Formula Manager." % i) res = self.walk(formula, substitutions=subs) return res
def _assert_is_boolean(self, formula): """Enforces that argument 'formula' is of type Boolean. Raises TypeError. """ if formula.get_type() != BOOL: raise PyomtTypeError("Argument must be boolean.")
def Real(self, value): """ Returns a Real-type constant of the given value. value can be: - A Fraction(n,d) - A tuple (n,d) - A long or int n - A float - (Optionally) a mpq or mpz object """ if value in self.real_constants: return self.real_constants[value] if is_pyomt_fraction(value): val = value elif type(value) == tuple: val = Fraction(value[0], value[1]) elif is_python_rational(value): val = pyomt_fraction_from_rational(value) else: raise PyomtTypeError("Invalid type in constant. The type was:" + \ str(type(value))) n = self.create_node(node_type=op.REAL_CONSTANT, args=tuple(), payload=val) self.real_constants[value] = n return n
def _assert_no_function_type(self, item): """Enforces that argument 'item' cannot be a FunctionType. Raises TypeError. """ if item.is_symbol() and item.symbol_type().is_function_type(): raise PyomtTypeError("Cannot call get_value() on a FunctionType")
def get_type(self, formula): """ Returns the pyomt.types type of the formula """ res = self.walk(formula) if not self.be_nice and res is None: raise PyomtTypeError("The formula '%s' is not well-formed" \ % str(formula)) return res
def Array(self, idx_type, default, assigned_values=None): """Creates a node representing an array having index type equal to idx_type, initialized with default values. If assigned_values is specified, then it must be a map from constants of type idx_type to values of the same type as default and the array is initialized correspondingly. """ if not isinstance(idx_type, types.PySMTType): raise PyomtTypeError("idx_type is not a valid type: '%s'" % idx_type) args = [default] if assigned_values: for k in sorted(assigned_values, key=id): if not k.is_constant(): raise PyomtValueError("Array initialization indexes must " "be constants") # It is useless to represent assignments equal to the default if assigned_values[k] != default: args.append(k) args.append(assigned_values[k]) return self.create_node(node_type=op.ARRAY_VALUE, args=tuple(args), payload=idx_type)
def assert_same_type_args(args): """ Enforces that all elements in args have the same type. """ ref_t = args[0].get_type() for arg in args[1:]: t = arg.get_type() if (t != ref_t): raise PyomtTypeError("Arguments should be of the same type!\n" + str([str((a, a.get_type())) for a in args]))
def BVRor(self, formula, steps): """Returns the RIGHT rotation of the BV by the number of steps.""" if not is_python_integer(steps): raise PyomtTypeError("BVRor: 'steps' should be an integer. Got %s" \ % steps) return self.create_node(node_type=op.BV_ROR, args=(formula, ), payload=(formula.bv_width(), steps))
def declare_variable(self, var): if not var.is_symbol(type_=types.BOOL): raise PyomtTypeError("Trying to declare as a variable something " "that is not a symbol: %s" % var) if var not in self.var2node: node = self.ddmanager.NewVar() self.idx2var[node.NodeReadIndex()] = var self.var2node[var] = node
def assert_args_type_in(args, allowed_types): """ Enforces that the type of the arguments is an allowed type """ for arg in args: t = arg.get_type() if (t not in allowed_types): raise PyomtTypeError( "Argument is of type %s, but one of %s was expected!\n" % (t, str(allowed_types)))
def Bool(self, value): if type(value) != bool: raise PyomtTypeError("Expecting bool, got %s" % type(value)) if value: return self.true_formula else: return self.false_formula
def declare_variable(self, var): if not var.is_symbol(): raise PyomtTypeError("Trying to declare as a variable something " "that is not a symbol: %s" % var) if var.symbol_name() not in self.declared_vars: cvc4_type = self._type_to_cvc4(var.symbol_type()) decl = self.mkVar(var.symbol_name(), cvc4_type) self.declared_vars[var] = decl
def get_or_create_symbol(self, name, typename): s = self.symbols.get(name, None) if s is None: return self._create_symbol(name, typename) if not s.symbol_type() == typename: raise PyomtTypeError( "Trying to redefine symbol '%s' with a new type" ". Previous type was '%s' new type is '%s'" % (name, s.symbol_type(), typename)) return s
def walk_equals(self, formula, args, **kwargs): #pylint: disable=unused-argument if args[0].is_bool_type(): raise PyomtTypeError("The formula '%s' is not well-formed." "Equality operator is not supported for Boolean" " terms. Use Iff instead." \ % str(formula)) elif args[0].is_bv_type(): return self.walk_bv_to_bool(formula, args) return self.walk_type_to_type(formula, args, args[0], BOOL)
def declare_variable(self, var): if not var.is_symbol(): raise PyomtTypeError("Trying to declare as a variable something " "that is not a symbol: %s" % var) if var.symbol_name() not in self.symbol_to_decl: tp = self._type_to_yices(var.symbol_type()) decl = yicespy.yices_new_uninterpreted_term(tp) yicespy.yices_set_term_name(decl, var.symbol_name()) self.symbol_to_decl[var] = decl self.decl_to_symbol[decl] = var
def get_value(self, formula, model_completion=True): if model_completion: syms = formula.get_free_variables() self._complete_model(syms) r = formula.substitute(self.completed_assignment) else: r = formula.substitute(self.assignment) res = r.simplify() if not res.is_constant(): raise PyomtTypeError("Was expecting a constant but got %s" % res) return res
def BVSExt(self, formula, increase): """Returns the signed extension of the BV with 'increase' additional bits New bits are set according to the most-significant-bit. """ if not is_python_integer(increase): raise PyomtTypeError("BVSext: 'increase' should be an integer. " "Got %s" % increase) return self.create_node(node_type=op.BV_SEXT, args=(formula, ), payload=(formula.bv_width() + increase, increase))
def BVZExt(self, formula, increase): """Returns the extension of the BV with 'increase' additional bits New bits are set to zero. """ if not is_python_integer(increase): raise PyomtTypeError("BVZext: 'increase' should be an integer. " "Got %s" % increase) return self.create_node(node_type=op.BV_ZEXT, args=(formula, ), payload=(formula.bv_width() + increase, increase))
def _complete_model(self, symbols): undefined_symbols = (s for s in symbols if s not in self.completed_assignment) mgr = self.environment.formula_manager for s in undefined_symbols: if not s.is_symbol(): raise PyomtTypeError("Was expecting a symbol but got %s" % s) if s.symbol_type().is_bool_type(): value = mgr.Bool(False) elif s.symbol_type().is_real_type(): value = mgr.Real(0) elif s.symbol_type().is_int_type(): value = mgr.Int(0) elif s.symbol_type().is_bv_type(): value = mgr.BVZero(s.bv_width()) else: raise PyomtTypeError("Unhandled type for %s: %s" % (s, s.symbol_type())) self.completed_assignment[s] = value
def ToReal(self, formula): """ Cast a formula to real type. """ t = self.env.stc.get_type(formula) if t == types.REAL: # Ignore casting of a Real return formula elif t == types.INT: if formula.is_int_constant(): return self.Real(formula.constant_value()) return self.create_node(node_type=op.TOREAL, args=(formula, )) else: raise PyomtTypeError("Argument is of type %s, but INT was " "expected!\n" % t)
def BV(self, value, width=None): """Return a constant of type BitVector. value can be either: - a string of 0s and 1s - a string starting with "#b" followed by a sequence of 0s and 1s - an integer number s.t. 0 <= value < 2**width In order to create the BV representation of a signed integer, the SBV() method shall be used. """ if type(value) is str: if value.startswith("#b"): str_width = len(value) - 2 value = int(value[2:], 2) elif all(v in ["0", "1"] for v in value): str_width = len(value) value = int(value, 2) else: raise PyomtValueError("Expecting binary value as string, got " \ "%s instead." % value) if width is not None and width != str_width: raise PyomtValueError("Specified width does not match string " \ "width (%d != %d)" % (width, str_width)) width = str_width if width is None: raise PyomtValueError("Need to specify a width for the constant") if is_pyomt_integer(value): _value = value elif is_python_integer(value): _value = pyomt_integer_from_integer(value) else: raise PyomtTypeError("Invalid type in constant. The type was: %s" \ % str(type(value))) if _value < 0: raise PyomtValueError("Cannot specify a negative value: %d" \ % _value) if _value >= 2**width: raise PyomtValueError("Cannot express %d in %d bits" \ % (_value, width)) return self.create_node(node_type=op.BV_CONSTANT, args=tuple(), payload=(_value, width))
def Int(self, value): """Return a constant of type INT.""" if value in self.int_constants: return self.int_constants[value] if is_pyomt_integer(value): val = value elif is_python_integer(value): val = pyomt_integer_from_integer(value) else: raise PyomtTypeError("Invalid type in constant. The type was:" + \ str(type(value))) n = self.create_node(node_type=op.INT_CONSTANT, args=tuple(), payload=val) self.int_constants[value] = n return n
def Times(self, *args): """ Creates a multiplication of terms This function has polimorphic n-arguments: - Times(a,b,c) - Times([a,b,c]) Restriction: - Arguments must be all of the same type - Arguments must be INT or REAL """ tuple_args = self._polymorph_args_to_tuple(args) if len(tuple_args) == 0: raise PyomtTypeError("Cannot create a Times without arguments.") if len(tuple_args) == 1: return tuple_args[0] else: return self.create_node(node_type=op.TIMES, args=tuple_args)
def Plus(self, *args): """ Returns an sum of terms. This function has polimorphic n-arguments: - Plus(a,b,c) - Plus([a,b,c]) Restriction: - Arguments must be all of the same type - Arguments must be INT or REAL """ tuple_args = self._polymorph_args_to_tuple(args) if len(tuple_args) == 0: raise PyomtTypeError("Cannot create a Plus without arguments.") if len(tuple_args) == 1: return tuple_args[0] else: return self.create_node(node_type=op.PLUS, args=tuple_args)
def assert_boolean_args(args): """ Enforces that the elements in args are of BOOL type. """ for arg in args: t = arg.get_type() if (t != BOOL): raise PyomtTypeError("%s is not allowed in arguments" % t)
def assert_no_boolean_in_args(args): """ Enforces that the elements in args are not of BOOL type.""" for arg in args: if (arg.get_type() == BOOL): raise PyomtTypeError("Boolean Expressions are not allowed " "in arguments")