def SBV(self, value, width=None): """Returns a constant of type BitVector interpreting the sign. If the specified value is an integer, it is converted in the 2-complement representation of the given number, otherwise the behavior is the same as BV(). """ if is_python_integer(value): if width is None: raise PyomtValueError( "Need to specify a width for the constant") min_val = -(2**(width - 1)) max_val = (2**(width - 1)) - 1 if value < min_val: raise PyomtValueError("Cannot represent a value (%d) lower " \ "than %d in %d bits" % (value, min_val, width)) if value > max_val: raise PyomtValueError("Cannot represent a value (%d) greater " \ "than %d in %d bits" % (value, max_val, width)) if value >= 0: return self.BV(value, width) else: comp_value = (2**width) + value # value is negative! return self.BV(comp_value, width) else: return self.BV(value, width=width)
def _set_option(z3solver, name, value): try: z3solver.set(name, value) except z3.Z3Exception: raise PyomtValueError("Error setting the option '%s=%s'" \ % (name, value)) except z3.z3types.Z3Exception: raise PyomtValueError("Error setting the option '%s=%s'" \ % (name, value))
def _create_symbol(self, name, typename=types.BOOL): if len(name) == 0: raise PyomtValueError("Empty string is not a valid name") if not isinstance(typename, types.PySMTType): raise PyomtValueError("typename must be a PySMTType.") 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.unsat_cores_mode is not None: raise PyomtValueError("'unsat_cores_mode' option not supported.") # Set Defaults self.preprocessing = True self.propagation_limit = None self.more_important_lit = None self.less_important_lit = None self.global_default_phase = None self.enable_trace_generation = False self.output = None self.verbosity = 0 for k, v in self.solver_options.items(): if k == "enable_trace_generation": if v not in (True, False): raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k == "output": if v is not None and not hasattr(v, "fileno"): raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k == "global_default_phase": if v is not None and v not in PicosatOptions.ALL_GLOBAL_DEFAULT_PHASE: raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k == "preprocessing": if v not in (True, False): raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k == "verbosity": if not is_python_integer(v): raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k == "propagation_limit": if not is_python_integer(v): raise PyomtValueError("Invalid value for %s: %s" % \ (str(k),str(v))) elif k in ("more_important_lit", "less_important_lit"): if v is not None: try: valid = all(x.is_symbol(types.BOOL) for x in v) except: valid = False if not valid: raise PyomtValueError("'more_important_lit' and " "'less_important_lit' require a " "list of Boolean variables") else: raise PyomtValueError("Unrecognized option '%s'." % k) # Store option setattr(self, k, v) # Consistency if self.output is not None and self.verbosity == 0: self.verbosity = 1
def __call__(self, *args): if self.is_symbol() and self.symbol_type().is_function_type(): types = self.symbol_type().param_types if (len(types) != len(args)): raise PyomtValueError("Wrong number of parameters passed in " "infix 'call' operator") args = [self._infix_prepare_arg(x, t) for x, t in zip(args, types)] return _mgr().Function(self, args) else: raise PyomtValueError("Call operator can be applied to symbol " "types having function type only")
def get_strict_formula(self, mgr=None): if self.contains_command(smtcmd.PUSH) or \ self.contains_command(smtcmd.POP): raise PyomtValueError("Was not expecting push-pop commands") if self.count_command_occurrences(smtcmd.CHECK_SAT) != 1: raise PyomtValueError( "Was expecting exactly one check-sat command") _And = mgr.And if mgr else get_env().formula_manager.And assertions = [ cmd.args[0] for cmd in self.filter_by_command_name([smtcmd.ASSERT]) ] return _And(assertions)
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 PyomtValueError("Error setting the option '%s=%s'" % (k,v)) except z3.z3types.Z3Exception: raise PyomtValueError("Error setting the option '%s=%s'" % (k,v))
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 __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 PyomtValueError("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 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 PyomtValueError("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_string_type() and self.node_type() != STR_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 _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 PyomtValueError("Logic not supported by Z3 interpolation." "(detected logic is: %s)" % str(logic))
def eliminate_quantifiers(self, formula): logic = get_logic(formula, self.environment) if not logic <= LRA and not logic <= LIA: raise PyomtValueError("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(f).as_expr() pyomt_res = None try: pyomt_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 pyomt_res
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 __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.unsat_cores_mode is not None: raise PyomtValueError("'unsat_cores_mode' option not supported.") self.debug_interaction = False if 'debug_interaction' in self.solver_options: self.debug_interaction = self.solver_options del self.solver_options['debug_interaction']
def _set_option(self, btor, name, value): available_options = { boolector.BoolectorOpt(btor, io).lng: io for io in self.internal_options } try: btor.Set_opt(available_options[name], value) except TypeError: raise PyomtValueError("Error setting the option '%s=%s'" \ % (name,value)) except boolector.BoolectorException: raise PyomtValueError("Error setting the option '%s=%s'" \ % (name,value)) except KeyError: raise PyomtValueError("Unable to set non-existing option '%s'. " "The accepted options options are: %s" \ % (name, ", ".join(boolector.BoolectorOpt(btor, io).lng for io in self.internal_options)))
def __init__(self, environment, logic, **options): if logic is None: raise PyomtValueError("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 _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 PyomtValueError("Error setting the option " "'%s=%s'" % (name, value))
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 PyomtValueError("The exponent of POW must be a constant.", exponent) if base.is_constant(): val = base.constant_value()**exponent.constant_value() if base.is_constant(types.REAL): return self.Real(val) else: assert base.is_constant(types.INT) return self.Int(val) return self.create_node(node_type=op.POW, args=(base, exponent))
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 PyomtValueError("Cannot override %s." % k) solver.set_option(k, str(v))
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 PyomtValueError("Unsupported value '%s' in infix operator" % str(arg))
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.random_seed is not None: raise PyomtValueError("'random_seed' option not supported.") if self.unsat_cores_mode is not None: raise PyomtValueError("'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 PyomtValueError("The BDD static ordering must be" \ " a list of Boolean variables") elif k == "dynamic_reordering": if v not in (True, False): raise PyomtValueError("Invalid value %s for '%s'" % \ (str(k),str(v))) elif k == "reordering_algorithm": if v not in BddOptions.CUDD_ALL_REORDERING_ALGORITHMS: raise PyomtValueError("Invalid value %s for '%s'" % \ (str(k),str(v))) else: raise PyomtValueError("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 PyomtValueError("reordering_algorithm requires " "dynamic_reordering.")
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 PyomtValueError("Error setting the option '%s=%s'" % (k, v)) solver.yices_params = params
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 PyomtValueError("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 PyomtValueError("Type %s previously declared with arity "\ " %d." % (name, td.arity)) except KeyError: td = _TypeDecl(name, arity) td.set_custom_type_flag() self._custom_types_decl[name] = td if td.arity == 0: # Automatically instantiate 0-arity types return self.get_type_instance(td) return td
def _set_option(cvc4, name, value): try: cvc4.setOption(name, CVC4.SExpr(value)) except: raise PyomtValueError("Error setting the option '%s=%s'" % (name, value))
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) # TODO: CVC4 Supports UnsatCore extraction # but we did not wrapped it yet. (See #349) if self.unsat_cores_mode is not None: raise PyomtValueError("'unsat_cores_mode' option not supported.")
def __init__(self, **base_options): SolverOptions.__init__(self, **base_options) if self.random_seed is not None: raise PyomtValueError("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 assert_is_type(target, func_name): if not isinstance(target, PySMTType): raise PyomtValueError("Invalid type '%s' in %s." % (target, func_name))