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 BVExtract(self, formula, start=0, end=None): """Returns the slice of formula from start to end (inclusive).""" if end is None: end = formula.bv_width() - 1 assert is_python_integer(start) and is_python_integer(end) assert end >= start and start >= 0, "Start: %d ; End: %d" % (start, end) size = end - start + 1 assert size <= formula.bv_width(), \ "Invalid size: start=%d, end=%d, width=%d" % \ (start, end, formula.bv_width()) return self.create_node(node_type=op.BV_EXTRACT, args=(formula, ), payload=(size, start, end))
def BVLShr(self, left, right): """Returns the logical right shift the BV.""" if is_python_integer(right): right = self.BV(right, left.bv_width()) return self.create_node(node_type=op.BV_LSHR, args=(left, right), payload=(left.bv_width(), ))
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 BVAShr(self, left, right): """Returns the RIGHT arithmetic rotation of the left BV by the number of steps specified by the right BV.""" if is_python_integer(right): right = self.BV(right, left.bv_width()) return self.create_node(node_type=op.BV_ASHR, args=(left, right), payload=(left.bv_width(), ))
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 __rsub__(self, left): # Swap operators to perform right-subtract # For BVs we might need to build the BV constant if self.get_type().is_bv_type(): if is_python_integer(left): left = _mgr().BV(left, width=self.bv_width()) return left._apply_infix(self, _mgr().BVSub) # (x - y) = (-y + x) minus_self = -self return minus_self._apply_infix(left, _mgr().Plus)
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 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