def __init__(self, decl=None, basename=None, args=None): if decl: self.decl = decl self.basename = decl.name self.arity = decl.arity if (args and self.arity != len(args)) or \ (not args and self.arity != 0): raise PysmtValueError("Invalid number of arguments. " + "Expected %d, got %d." % (self.arity, len(args))) self.custom_type = decl.custom_type else: self.basename = basename self.arity = len(args) if args else 0 self.custom_type = False self.args = args if self.args: args_str = "{%s}" % ", ".join(str(a) for a in self.args) else: args_str = "" if self.basename: self.name = self.basename + args_str else: self.name = None
def _next_var(self, symbol): if symbol.is_symbol(): name = symbol.symbol_name() ty = symbol.symbol_type() return self.env.formula_manager.Symbol("next_" + name, ty) else: raise PysmtValueError("'next' operator can be applied only to symbols")
def is_constant(self, _type=None, value=None): """Test whether the formula is a constant. Optionally, check that the constant is of the given type and value. """ if self.node_type() not in CONSTANTS: if self.node_type() == ARRAY_VALUE: # An array value can be a constant if all its children # are constants for c in self.args(): if not c.is_constant(): return False if _type is not None or value is not None: raise PysmtValueError("constant type and value checking " \ "is not available for array values") return True return False if _type is not None: if _type.is_int_type() and self.node_type() != INT_CONSTANT: return False if _type.is_real_type() and self.node_type() != REAL_CONSTANT: return False if _type.is_bool_type() and self.node_type() != BOOL_CONSTANT: return False if _type.is_bv_type(): if self.node_type() != BV_CONSTANT: return False if self._content.payload[1] != _type.width: return False if value is not None: return value == self.constant_value() return True
def __call__(self, solver): self._set_option(solver.z3, 'model', self.generate_models) if self.unsat_cores_mode is not None: self._set_option(solver.z3, 'unsat_core', True) if self.random_seed is not None: self._set_option(solver.z3, 'random_seed', self.random_seed) for k, v in self.solver_options.items(): try: self._set_option(solver.z3, str(k), v) except z3.Z3Exception: raise PysmtValueError("Error setting the option '%s=%s'" % (k, v)) except z3.z3types.Z3Exception: raise PysmtValueError("Error setting the option '%s=%s'" % (k, v))
def _set_option(self, btor, name, value): available_options = {pyboolector.BoolectorOpt(btor, io).lng : io for io in self.internal_options} try: btor.Set_opt(available_options[name], value) except TypeError: raise PysmtValueError("Error setting the option '%s=%s'" \ % (name,value)) except pyboolector.BoolectorException: raise PysmtValueError("Error setting the option '%s=%s'" \ % (name,value)) except KeyError: raise PysmtValueError("Unable to set non-existing option '%s'. " "The accepted options options are: %s" \ % (name, ", ".join(pyboolector.BoolectorOpt(btor, io).lng for io in self.internal_options)))
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 PysmtTypeError("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 PysmtValueError("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 eliminate_quantifiers(self, formula): logic = get_logic(formula, self.environment) if not logic <= LRA and not logic <= LIA: raise PysmtValueError("Z3 quantifier elimination only "\ "supports LRA or LIA without combination."\ "(detected logic is: %s)" % str(logic)) simplifier = z3.Tactic('simplify') eliminator = z3.Tactic('qe') f = self.converter.convert(formula) s = simplifier(f, elim_and=True, pull_cheap_ite=True, ite_extra_rules=True).as_expr() res = eliminator(s, eliminate_variables_as_block=True).as_expr() pysmt_res = None try: pysmt_res = self.converter.back(res) except ConvertExpressionError: if logic <= LRA: raise raise ConvertExpressionError(message=("Unable to represent" \ "expression %s in pySMT: the quantifier elimination for " \ "LIA is incomplete as it requires the modulus. You can " \ "find the Z3 expression representing the quantifier " \ "elimination as the attribute 'expression' of this " \ "exception object" % str(res)), expression=res) return pysmt_res
def validate_simplifications(self, value): possible_solvers = [sname for sname in self.env.factory.all_solvers()\ if sname!="bdd"] if len(possible_solvers) == 0: raise PysmtValueError("To validate at least another solver must " "be available!") self._validation_sname = possible_solvers[0] self._validate_simplifications = value
def _check_logic(self, formulas): for f in formulas: logic = get_logic(f, self.environment) ok = any(logic <= l for l in self.LOGICS) if not ok: raise PysmtValueError( "Logic not supported by Z3 interpolation." "(detected logic is: %s)" % str(logic))
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 PysmtValueError("Expecting binary value as string, got " \ "%s instead." % value) if width is not None and width != str_width: raise PysmtValueError("Specified width does not match string " \ "width (%d != %d)" % (width, str_width)) width = str_width if width is None: raise PysmtValueError("Need to specify a width for the constant") if is_python_integer(value): if value < 0: raise PysmtValueError("Cannot specify a negative value: %d" \ % value) if value >= 2**width: raise PysmtValueError("Cannot express %d in %d bits" \ % (value, width)) return self.create_node(node_type=op.BV_CONSTANT, args=tuple(), payload=(value, width)) else: raise PysmtTypeError("Invalid type in constant. The type was:" + \ str(type(value)))
def _create_symbol(self, name, typename=types.BOOL): if len(name) == 0: raise PysmtValueError("Empty string is not a valid name") n = self.create_node(node_type=op.SYMBOL, args=tuple(), payload=(name, typename)) self.symbols[name] = n return n
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.random_seed is not None: raise PysmtValueError("BTOR Does not support Random Seed setting.") # Disabling Incremental usage is not allowed. # This needs to be set to 1 self.incrementality = True
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.unsat_cores_mode is not None: raise PysmtValueError("'unsat_cores_mode' option not supported.") self.debug_interaction = False if 'debug_interaction' in self.solver_options: self.debug_interaction = self.solver_options['debug_interaction'] del self.solver_options['debug_interaction']
def _set_option(cfg, name, value): rv = yicespy.yices_set_config(cfg, name, value) if rv != 0: # This might be a parameter to be set later (see set_params) # We raise the exception only if the parameter exists but the value # provided to the parameter is invalid. err = yicespy.yices_error_code() if err == yicespy.CTX_INVALID_PARAMETER_VALUE: raise PysmtValueError("Error setting the option " "'%s=%s'" % (name, value))
def __init__(self, environment, logic, **options): if logic is None: raise PysmtValueError("Cannot provide 'None' as logic") self.environment = environment self.pending_pop = False self.logic = logic self.options = self.OptionsClass(**options) self._destroyed = False return
def __call__(self, solver): if self.generate_models: solver.solver.set_opt('produce-models', 'true') if self.incremental: solver.solver.set_opt('incremental', 'true') for k, v in self.solver_options.items(): try: solver.solver.set_opt(k, v) except: raise PysmtValueError(f"Error setting the option '{k}={v}'")
def get_type_instance(self, type_decl, *args): if not all(isinstance(t, PySMTType) for t in args): raise PysmtValueError("Trying to instantiate %s with non-type args."\ % str(type_decl)) key = (type_decl, tuple(args)) if args is not None else type_decl try: ty = self._custom_types[key] except KeyError: ty = PySMTType(basename=type_decl.name, args=args) self._custom_types[key] = ty return ty
def get_type_instance(self, type_decl, *args): """Creates an instance of the TypeDecl with the given arguments.""" if not all(isinstance(t, PySMTType) for t in args): raise PysmtValueError("Trying to instantiate %s with non-type args."\ % str(type_decl)) key = (type_decl, tuple(args)) if args is not None else type_decl try: ty = self._custom_types[key] except KeyError: ty = PySMTType(decl=type_decl, args=args) self._custom_types[key] = ty return ty
def __init__(self, formal_params, function_body, allow_free_vars=False): """Constructor, taking in input the list of formal parameters and the function body. The parameter `allow_free_vars` is used to skip the check that the function body has no free variables other than formal parameter and is used in the SmtLib model-validation utility because functions with uninterpreted return value return special symbols (e.g. @val1) in SmtLib. """ if any(not x.is_symbol() or not x.is_term() for x in formal_params): raise PysmtValueError( 'Formal parameters of a function ' 'interpretation must be non-function symbols') if not allow_free_vars and \ not function_body.get_free_variables().issubset(set(formal_params)): raise PysmtValueError( 'the body of a function interpretation cannot' ' contain free variables other than formal ' 'parameters') self.formal_params = list(formal_params) self.function_body = function_body
def BVOr(self, *args): """Returns the Bit-wise OR of bitvectors of the same size. If more than 2 arguments are passed, a left-associative formula is generated.""" args = self._polymorph_args_to_tuple(args) if len(args) == 0: raise PysmtValueError( "BVOr expects at least one argument to be passed") res = args[0] for arg in args[1:]: res = self.create_node(node_type=op.BV_OR, args=(res, arg), payload=(res.bv_width(), )) return res
def Pow(self, base, exponent): """ Creates the n-th power of the base. The exponent must be a constant. """ if not exponent.is_constant(): raise PysmtValueError("The exponent of POW must be a constant.", exponent) if base.is_constant(): val = base.constant_value()**exponent.constant_value() return self.Real(val) return self.create_node(node_type=op.POW, args=(base, exponent))
def BVMul(self, *args): """Returns the product of BV. If more than 2 arguments are passed, a left-associative formula is generated.""" args = self._polymorph_args_to_tuple(args) if len(args) == 0: raise PysmtValueError( "BVMul expects at least one argument to be passed") res = args[0] for arg in args[1:]: res = self.create_node(node_type=op.BV_MUL, args=(res, arg), payload=(res.bv_width(), )) return res
def _infix_prepare_arg(self, arg, expected_type): mgr = _mgr() if isinstance(arg, FNode): return arg # BVs if expected_type.is_bv_type(): return mgr.BV(arg, width=expected_type.width) # Boolean, Integer and Arithmetic elif expected_type.is_bool_type(): return mgr.Bool(arg) elif expected_type.is_int_type(): return mgr.Int(arg) elif expected_type.is_real_type(): return mgr.Real(arg) else: raise PysmtValueError("Unsupported value '%s' in infix operator" % str(arg))
def __call__(self, solver): # These options are needed for the wrapper to work solver.set_option(":print-success", "true") solver.set_option(":diagnostic-output-channel", '"stdout"') if self.generate_models: solver.set_option(":produce-models", "true") else: solver.set_option(":produce-models", "false") if self.random_seed is not None: solver.set_option(":random-seed", str(self.random_seed)) for k, v in self.solver_options.items(): if k in (':print-success', 'diagnostic-output-channel'): raise PysmtValueError("Cannot override %s." % k) solver.set_option(k, str(v))
def set_params(self, solver): """Set Search Parameters. Yices makes a distinction between configuratin and search parameters. The first are fixed for the lifetime of a context, while the latter can be different for every call to check_context. A list of available parameters is available at: http://yices.csl.sri.com/doc/parameters.html """ params = yicespy.yices_new_param_record() yicespy.yices_default_params_for_context(solver.yices, params) for k,v in self.solver_options.items(): rv = yicespy.yices_set_param(params, k, v) if rv != 0: raise PysmtValueError("Error setting the option '%s=%s'" % (k,v)) solver.yices_params = params
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.random_seed is not None: raise PysmtValueError("'random_seed' option not supported.") if self.unsat_cores_mode is not None: raise PysmtValueError("'unsat_cores_mode' option not supported.") for k, v in self.solver_options.items(): if k == "static_ordering": if v is not None: try: valid = all(x.is_symbol(types.BOOL) for x in v) except: valid = False if not valid: raise PysmtValueError("The BDD static ordering must be" \ " a list of Boolean variables") elif k == "dynamic_reordering": if v not in (True, False): raise PysmtValueError("Invalid value %s for '%s'" % \ (str(k),str(v))) elif k == "reordering_algorithm": if v not in BddOptions.CUDD_ALL_REORDERING_ALGORITHMS: raise PysmtValueError("Invalid value %s for '%s'" % \ (str(k),str(v))) else: raise PysmtValueError("Unrecognized option '%s'." % k) # Store option setattr(self, k, v) # Set Defaults if not hasattr(self, "dynamic_reordering"): self.dynamic_reordering = False if not hasattr(self, "reordering_algorithm"): if not self.dynamic_reordering: self.reordering_algorithm = None else: self.reordering_algorithm = BddOptions.CUDD_REORDER_SIFT if not hasattr(self, "static_ordering"): self.static_ordering = None # Consistency check if not self.dynamic_reordering and self.reordering_algorithm is not None: raise PysmtValueError("reordering_algorithm requires " "dynamic_reordering.")
def __call__(self, solver): """Handle Options""" pico = solver.pico if self.random_seed is not None: picosat.picosat_set_seed(pico, self.random_seed) if self.preprocessing is True: picosat.picosat_set_plain(pico, 0) else: picosat.picosat_set_plain(pico, 1) if self.propagation_limit is not None: picosat.picosat_set_propagation_limit(pico, self.propagation_limit) if self.more_important_lit is not None: for x in self.more_important_lit: lit = solver._get_var_id(x) #pylint: disable=protected-access picosat.picosat_set_more_important_lit(pico, lit) if self.less_important_lit is not None: for x in self.less_important_lit: lit = solver._get_var_id(x) #pylint: disable=protected-access picosat.picosat_set_less_important_lit(pico, lit) if self.global_default_phase is not None: picosat.picosat_set_global_default_phase(pico, self.global_default_phase) if self.output is not None: self._log_file_handler = picosat.picosat_set_output( pico, self.output) if self.enable_trace_generation: rv = picosat.picosat_enable_trace_generation(pico) if rv == 0: raise PysmtValueError("Picosat: Cannot enable Trace" " Generation") if self.verbosity > 0: picosat.picosat_set_verbosity(pico, self.verbosity)
def Type(self, name, arity=0): """Creates a new Type Declaration (sort declaration). This is equivalent to the SMT-LIB command "declare-sort". For sorts of arity 0, we return a PySMTType, all other sorts need to be instantiated. See class _Type. """ try: td = self._custom_types_decl[name] if td.arity != arity: raise PysmtValueError("Type %s previously declared with arity "\ " %d." % (name, td.arity)) except KeyError: td = _TypeDecl(self, name, arity) self._custom_types_decl[name] = td if td.arity == 0: # Automatically instantiate 0-arity types return self.get_type_instance(td) return td
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.random_seed is not None: raise PysmtValueError("BTOR Does not support Random Seed setting.") # Disabling Incremental usage is not allowed. # This needs to be set to 1 self.incrementality = True self.internal_options = [ boolector.BTOR_OPT_MODEL_GEN, boolector.BTOR_OPT_INCREMENTAL, boolector.BTOR_OPT_INCREMENTAL_SMT1, boolector.BTOR_OPT_INPUT_FORMAT, boolector.BTOR_OPT_OUTPUT_NUMBER_FORMAT, boolector.BTOR_OPT_OUTPUT_FORMAT, boolector.BTOR_OPT_ENGINE, boolector.BTOR_OPT_SAT_ENGINE, boolector.BTOR_OPT_AUTO_CLEANUP, boolector.BTOR_OPT_PRETTY_PRINT, boolector.BTOR_OPT_EXIT_CODES, boolector.BTOR_OPT_SEED, boolector.BTOR_OPT_VERBOSITY, boolector.BTOR_OPT_LOGLEVEL, boolector.BTOR_OPT_REWRITE_LEVEL, boolector.BTOR_OPT_SKELETON_PREPROC, boolector.BTOR_OPT_ACKERMANN, boolector.BTOR_OPT_BETA_REDUCE_ALL, boolector.BTOR_OPT_ELIMINATE_SLICES, boolector.BTOR_OPT_VAR_SUBST, boolector.BTOR_OPT_UCOPT, boolector.BTOR_OPT_MERGE_LAMBDAS, boolector.BTOR_OPT_EXTRACT_LAMBDAS, boolector.BTOR_OPT_NORMALIZE_ADD, boolector.BTOR_OPT_FUN_PREPROP, boolector.BTOR_OPT_FUN_PRESLS, boolector.BTOR_OPT_FUN_DUAL_PROP, boolector.BTOR_OPT_FUN_DUAL_PROP_QSORT, boolector.BTOR_OPT_FUN_JUST, boolector.BTOR_OPT_FUN_JUST_HEURISTIC, boolector.BTOR_OPT_FUN_LAZY_SYNTHESIZE, boolector.BTOR_OPT_FUN_EAGER_LEMMAS, boolector.BTOR_OPT_SLS_NFLIPS, boolector.BTOR_OPT_SLS_STRATEGY, boolector.BTOR_OPT_SLS_JUST, boolector.BTOR_OPT_SLS_MOVE_GW, boolector.BTOR_OPT_SLS_MOVE_RANGE, boolector.BTOR_OPT_SLS_MOVE_SEGMENT, boolector.BTOR_OPT_SLS_MOVE_RAND_WALK, boolector.BTOR_OPT_SLS_PROB_MOVE_RAND_WALK, boolector.BTOR_OPT_SLS_MOVE_RAND_ALL, boolector.BTOR_OPT_SLS_MOVE_RAND_RANGE, boolector.BTOR_OPT_SLS_MOVE_PROP, boolector.BTOR_OPT_SLS_MOVE_PROP_N_PROP, boolector.BTOR_OPT_SLS_MOVE_PROP_N_SLS, boolector.BTOR_OPT_SLS_MOVE_PROP_FORCE_RW, boolector.BTOR_OPT_SLS_MOVE_INC_MOVE_TEST, boolector.BTOR_OPT_SLS_USE_RESTARTS, boolector.BTOR_OPT_SLS_USE_BANDIT, boolector.BTOR_OPT_PROP_USE_RESTARTS, boolector.BTOR_OPT_PROP_USE_BANDIT, boolector.BTOR_OPT_PROP_PATH_SEL, boolector.BTOR_OPT_PROP_PROB_USE_INV_VALUE, boolector.BTOR_OPT_PROP_PROB_FLIP_COND, boolector.BTOR_OPT_PROP_PROB_FLIP_COND_CONST, boolector.BTOR_OPT_PROP_FLIP_COND_CONST_DELTA, boolector.BTOR_OPT_PROP_FLIP_COND_CONST_NPATHSEL, boolector.BTOR_OPT_PROP_PROB_SLICE_KEEP_DC, boolector.BTOR_OPT_PROP_PROB_CONC_FLIP, boolector.BTOR_OPT_PROP_PROB_SLICE_FLIP, boolector.BTOR_OPT_PROP_PROB_EQ_FLIP, boolector.BTOR_OPT_PROP_PROB_AND_FLIP, boolector.BTOR_OPT_PROP_NO_MOVE_ON_CONFLICT, boolector.BTOR_OPT_AIGPROP_USE_RESTARTS, boolector.BTOR_OPT_AIGPROP_USE_BANDIT, boolector.BTOR_OPT_SORT_EXP, boolector.BTOR_OPT_SORT_AIG, boolector.BTOR_OPT_SORT_AIGVEC, boolector.BTOR_OPT_AUTO_CLEANUP_INTERNAL, boolector.BTOR_OPT_SIMPLIFY_CONSTRAINTS, boolector.BTOR_OPT_CHK_FAILED_ASSUMPTIONS ]
def _set_option(cvc4, name, value): try: cvc4.setOption(name, CVC4.SExpr(value)) except: raise PysmtValueError("Error setting the option '%s=%s'" % (name, value))