Beispiel #1
0
    def __init__(self, value=SMYBOLIC, *, name=AUTOMATIC, prefix=AUTOMATIC):
        if (name is not AUTOMATIC
                or prefix is not AUTOMATIC) and value is not SMYBOLIC:
            raise TypeError('Can only name symbolic variables')
        elif name is not AUTOMATIC and prefix is not AUTOMATIC:
            raise ValueError('Can only set either name or prefix not both')
        elif name is not AUTOMATIC:
            if not isinstance(name, str):
                raise TypeError('Name must be string')
            elif name in _name_table:
                raise ValueError(f'Name {name} already in use')
            elif _name_re.fullmatch(name):
                warnings.warn(
                    'Name looks like an auto generated name, this might break things'
                )
            _name_table[name] = self
        elif prefix is not AUTOMATIC:
            name = _gen_name(prefix)
            _name_table[name] = self
        elif name is AUTOMATIC and value is SMYBOLIC:
            name = _gen_name()
            _name_table[name] = self

        if value is SMYBOLIC:
            self._value = smt.Symbol(name, BOOL)
        elif isinstance(value, pysmt.fnode.FNode):
            if value.get_type().is_bool_type():
                self._value = value
            else:
                raise TypeError(f'Expected bool type not {value.get_type()}')
        elif isinstance(value, SMTBit):
            if name is not AUTOMATIC and name != value.name:
                warnings.warn(
                    'Changing the name of a SMTBit does not cause a new underlying smt variable to be created'
                )
            self._value = value._value
        elif isinstance(value, bool):
            self._value = smt.Bool(value)
        elif isinstance(value, int):
            if value not in {0, 1}:
                raise ValueError(
                    'Bit must have value 0 or 1 not {}'.format(value))
            self._value = smt.Bool(bool(value))
        elif hasattr(value, '__bool__'):
            self._value = smt.Bool(bool(value))
        else:
            raise TypeError("Can't coerce {} to Bit".format(type(value)))

        self._name = name
        self._value = smt.simplify(self._value)
Beispiel #2
0
 def walk_constant(self, value, v_type):
     if v_type == smt.BOOL:
         return smt.Bool(value)
     elif v_type == smt.REAL:
         return smt.Real(value)
     else:
         return ValueError("Unknown type {}".format(v_type))
Beispiel #3
0
def sympy2pysmt(expr, expr_type=None):
    if type(expr
            ) == Poly:  # turn Poly instances into generic sympy expressions
        expr = expr.as_expr()

    op = type(expr)

    if len(expr.free_symbols) == 0:
        if expr.is_Boolean:
            return smt.Bool(bool(expr))
        elif expr.is_number:
            return smt.Real(float(expr))

    elif op == sym.Symbol:
        if expr_type is None:
            raise ValueError(
                "Can't create a pysmt Symbol without type information")

        return smt.Symbol(expr.name, expr_type)

    elif op in SYM2SMT:
        if expr_type is None:
            expr_type = OP_TYPE[op]

        smtargs = [sympy2pysmt(c, expr_type) for c in expr.args]
        return SYM2SMT[op](*smtargs)

    raise NotImplementedError(f"SYMPY -> PYSMT Not implemented for op: {op}")
Beispiel #4
0
    def test_simpleSymbol_false(self):
        symbol_name = "b"

        checker = SmtChecker({symbol_name: False})
        self.assertFalse(checker.walk_smt(smt.Symbol(symbol_name)))

        checker = SmtChecker({symbol_name: smt.Bool(False)})
        self.assertFalse(checker.walk_smt(smt.Symbol(symbol_name)))
Beispiel #5
0
    def test_simpleSymbol_true(self):
        symbol_name = "b"

        checker = SmtChecker({symbol_name: True})
        self.assertTrue(checker.walk_smt(smt.Symbol(symbol_name)))

        checker = SmtChecker({symbol_name: smt.Bool(True)})
        self.assertTrue(checker.walk_smt(smt.Symbol(symbol_name)))
Beispiel #6
0
    def ast_to_smt(self, node):
        """
        :type node: Node
        """
        def convert_children(number=None):
            if number is not None and len(node.children) != number:
                raise Exception(
                    "The number of children ({}) differed from {}".format(
                        len(node.children), number))
            return [self.ast_to_smt(child) for child in node.children]

        if node.name == "ite":
            return smt.Ite(*convert_children(3))
        elif node.name == "~":
            return smt.Not(*convert_children(1))
        elif node.name == "^":
            return smt.Pow(*convert_children(2))
        elif node.name == "&":
            return smt.And(*convert_children())
        elif node.name == "|":
            return smt.Or(*convert_children())
        elif node.name == "*":
            return smt.Times(*convert_children())
        elif node.name == "+":
            return smt.Plus(*convert_children())
        elif node.name == "-":
            return smt.Minus(*convert_children(2))
        elif node.name == "<=":
            return smt.LE(*convert_children(2))
        elif node.name == ">=":
            return smt.GE(*convert_children(2))
        elif node.name == "<":
            return smt.LT(*convert_children(2))
        elif node.name == ">":
            return smt.GT(*convert_children(2))
        elif node.name == "=":
            return smt.Equals(*convert_children(2))
        elif node.name == "const":
            c_type, c_value = [child.name for child in node.children]
            if c_type == "bool":
                return smt.Bool(bool(c_value))
            elif c_type == "real":
                return smt.Real(float(c_value))
            else:
                raise Exception("Unknown constant type {}".format(c_type))
        elif node.name == "var":
            v_type, v_name = [child.name for child in node.children]
            if v_type == "bool":
                v_smt_type = smt.BOOL
            elif v_type == "real":
                v_smt_type = smt.REAL
            else:
                raise Exception("Unknown variable type {}".format(v_type))
            return smt.Symbol(v_name, v_smt_type)
        else:
            raise RuntimeError("Unrecognized node type '{}'".format(node.name))
Beispiel #7
0
    def test_pysmt_operations(self, width, x, y):
        try:
            from pysmt import shortcuts as sc
        except ImportError:
            return

        modulus = 2 ** width
        x = x % modulus
        y = y % modulus
        bvx = Constant(x, width)
        bvy = Constant(y, width)
        psx = sc.BV(x, width)
        psy = sc.BV(y, width)

        def eval_pysmt(pysmt_var):
            return pysmt_var.simplify().constant_value()

        self.assertEqual(~bvx, eval_pysmt(sc.BVNot(psx)))
        self.assertEqual(bvx & bvy, eval_pysmt(sc.BVAnd(psx, psy)))
        self.assertEqual(bvx | bvy, eval_pysmt(sc.BVOr(psx, psy)))
        self.assertEqual(bvx ^ bvy, eval_pysmt(sc.BVXor(psx, psy)))

        self.assertEqual(BvComp(bvx, bvy), eval_pysmt(sc.BVComp(psx, psy)))
        self.assertEqual((bvx < bvy), eval_pysmt(sc.BVULT(psx, psy)))
        self.assertEqual((bvx <= bvy), eval_pysmt(sc.BVULE(psx, psy)))
        self.assertEqual((bvx > bvy), eval_pysmt(sc.BVUGT(psx, psy)))
        self.assertEqual((bvx >= bvy), eval_pysmt(sc.BVUGE(psx, psy)))

        r = y % bvx.width
        self.assertEqual(bvx << bvy, eval_pysmt(sc.BVLShl(psx, psy)))
        self.assertEqual(bvx >> bvy, eval_pysmt(sc.BVLShr(psx, psy)))
        self.assertEqual(RotateLeft(bvx, r), eval_pysmt(sc.BVRol(psx, r)))
        self.assertEqual(RotateRight(bvx, r), eval_pysmt(sc.BVRor(psx, r)))

        bvb = Constant(y % 2, 1)
        psb = sc.Bool(bool(bvb))
        self.assertEqual(Ite(bvb, bvx, bvy), eval_pysmt(sc.Ite(psb, psx, psy)))
        j = y % bvx.width
        self.assertEqual(bvx[:j], eval_pysmt(sc.BVExtract(psx, start=j)))
        self.assertEqual(bvx[j:], eval_pysmt(sc.BVExtract(psx, end=j)))
        self.assertEqual(Concat(bvx, bvy), eval_pysmt(sc.BVConcat(psx, psy)))
        self.assertEqual(ZeroExtend(bvx, j), eval_pysmt(sc.BVZExt(psx, j)))
        self.assertEqual(Repeat(bvx, 1 + j), eval_pysmt(psx.BVRepeat(1 + j)))

        self.assertEqual(-bvx, eval_pysmt(sc.BVNeg(psx)))
        self.assertEqual(bvx + bvy, eval_pysmt(sc.BVAdd(psx, psy)))
        self.assertEqual(bvx - bvy, eval_pysmt(sc.BVSub(psx, psy)))
        self.assertEqual(bvx * bvy, eval_pysmt(sc.BVMul(psx, psy)))
        if bvy > 0:
            self.assertEqual(bvx / bvy, eval_pysmt(sc.BVUDiv(psx, psy)))
            self.assertEqual(bvx % bvy, eval_pysmt(sc.BVURem(psx, psy)))
Beispiel #8
0
 def __encodeTerminal(symbolicExpression, type):
     if isinstance(symbolicExpression, sympy.Symbol):
         if type.literal == 'Integer':
             return pysmt.Symbol(symbolicExpression.name, pysmt.INT)
         elif type.literal == 'Real':
             return pysmt.Symbol(symbolicExpression.name, pysmt.REAL)
         elif type.literal == 'Bool':
             return pysmt.Symbol(symbolicExpression.name, pysmt.BOOL)
         else:  # type.literal == 'BitVector'
             return pysmt.Symbol(symbolicExpression.name, pysmt.BVType(type.size))
     else:
         if type.literal == 'Integer':
             return pysmt.Int(symbolicExpression.p)
         elif type.literal == 'Real':
             if isinstance(symbolicExpression, sympy.Rational):
                 return pysmt.Real(symbolicExpression.p / symbolicExpression.q)
             else:  # isinstance(symbolicExpression, sympy.Float)
                 return pysmt.Real(symbolicExpression)
         elif type.literal == 'Bool':
             return pysmt.Bool(symbolicExpression)
         else:  # type.literal == 'BitVector'
             return pysmt.BV(symbolicExpression, type.size)
Beispiel #9
0
def draw_points(feat_x, feat_y, domain, formula, data, learned_labels, name, active_indices, new_active_indices,
                condition=None):

    row_vars = domain.bool_vars[:int(len(domain.bool_vars) / 2)]
    col_vars = domain.bool_vars[int(len(domain.bool_vars) / 2):]
    sf_size = 2

    fig = plt.figure(num=None, figsize=(2 ** len(col_vars) * sf_size, 2 ** len(row_vars) * sf_size), dpi=300)

    for assignment in itertools.product([True, False], repeat=len(domain.bool_vars)):
        row = 0
        for b in assignment[:len(row_vars)]:
            row = row * 2 + (1 if b else 0)

        col = 0
        for b in assignment[len(row_vars):]:
            col = col * 2 + (1 if b else 0)

        index = row * (2 ** len(col_vars)) + col
        ax = fig.add_subplot(2 ** len(row_vars), 2 ** len(col_vars), 1 + index)

        if formula is not None:
            substitution = {domain.get_symbol(v): smt.Bool(a) for v, a in zip(domain.bool_vars, assignment)}
            substituted = formula.substitute(substitution)
            region = RegionBuilder(domain).walk_smt(substituted)
            try:
                if region.dim == 2:
                    region.plot(ax=ax, color="green", alpha=0.2)
            except IndexError:
                pass

        points = []
        for i in range(len(data)):
            instance, label = data[i]
            point = (float(instance[feat_x]), float(instance[feat_y]))
            correct = (learned_labels[i] == label) if learned_labels is not None else True
            status = "active" if i in active_indices else ("new_active" if i in new_active_indices else "excluded")
            match = all(instance[v] == a for v, a in zip(domain.bool_vars, assignment))
            if match and (condition is None or condition(instance, label)):
                points.append((label, correct, status, point))

        def get_color(_l, _c, _s):
            if _s == "active":
                return "black"
            return "green" if _l else "red"

        def get_marker(_l, _c, _s):
            # if _s == "active":
            #     return "v"
            return "+" if _l else "."

        def get_alpha(_l, _c, _s):
            if _s == "active":
                return 0.5
            elif _s == "new_active":
                return 1
            elif _s == "excluded":
                return 0.2

        for label in [True, False]:
            for correct in [True, False]:
                for status in ["active", "new_active", "excluded"]:
                    marker, color, alpha = [f(label, correct, status) for f in (get_marker, get_color, get_alpha)]
                    selection = [p for l, c, s, p in points if l == label and c == correct and s == status]
                    if len(selection) > 0:
                        ax.scatter(*zip(*selection), c=color, marker=marker, alpha=alpha)

        ax.set_xlim([0, 1])
        ax.set_ylim([0, 1])

    plt.savefig("{}.png".format(name))
    plt.close(fig)
def test_constant_boolean():
    formula = smt.Bool(True)
    result = make_coefficients_positive(formula)
    assert formula == result
Beispiel #11
0
def plot_combined(feat_x: Union[str, int],
                  feat_y: Union[str, int],
                  domain: Domain,
                  formula: Optional[FNode],
                  data: Union[Tuple[np.ndarray, np.ndarray],
                              List[Tuple[Dict, bool]]],
                  learned_labels: Optional[List[bool]],
                  name: str,
                  active_indices: Set[int],
                  new_active_indices: Set[int],
                  condition: Optional[callable] = None):

    row_vars = domain.bool_vars[:int(len(domain.bool_vars) / 2)]
    col_vars = domain.bool_vars[int(len(domain.bool_vars) / 2):]
    sf_size = 2

    fig = plt.figure(num=None,
                     figsize=(2**len(col_vars) * sf_size,
                              2**len(row_vars) * sf_size),
                     dpi=300)

    for assignment in itertools.product([True, False],
                                        repeat=len(domain.bool_vars)):
        row = 0
        for b in assignment[:len(row_vars)]:
            row = row * 2 + (1 if b else 0)

        col = 0
        for b in assignment[len(row_vars):]:
            col = col * 2 + (1 if b else 0)

        index = row * (2**len(col_vars)) + col
        ax = fig.add_subplot(2**len(row_vars), 2**len(col_vars), 1 + index)

        if formula is not None:
            substitution = {
                domain.get_symbol(v): smt.Bool(a)
                for v, a in zip(domain.bool_vars, assignment)
            }
            substituted = smt.simplify(formula.substitute(substitution))
            try:
                region = RegionBuilder(domain).walk_smt(substituted)
                try:
                    if region.dim == 2:
                        region.linestyle = None
                        region.plot(ax=ax, color="green", alpha=0.2)
                except IndexError:
                    pass
            except ValueError:
                pass

        points = []

        def status(_i):
            return "active" if _i in active_indices else (
                "new_active" if _i in new_active_indices else "excluded")

        if isinstance(data, tuple):
            values, labels = data  # type: Tuple[np.ndarray, np.ndarray]
            var_index_map = domain.var_index_map()
            fx, fy = (f if isinstance(f, int) else var_index_map[f]
                      for f in (feat_x, feat_y))
            # noinspection PyUnresolvedReferences
            for i in range(values.shape[0]):
                row = values[i, :]
                point = row[fx], row[fy]
                label = labels[i] == 1
                correct = (learned_labels[i]
                           == label) if learned_labels is not None else True
                match = all(row[var_index_map[v]] == a
                            for v, a in zip(domain.bool_vars, assignment))
                if match and (condition is None or condition(row, label)):
                    points.append((label, correct, status(i), point))
        else:
            for i in range(len(data)):
                instance, label = data[i]
                point = (float(instance[feat_x]), float(instance[feat_y]))
                correct = (learned_labels[i]
                           == label) if learned_labels is not None else True
                match = all(instance[v] == a
                            for v, a in zip(domain.bool_vars, assignment))
                if match and (condition is None or condition(instance, label)):
                    points.append((label, correct, status(i), point))

        def get_color(_l, _c, _s):
            if _s == "active":
                return "black"
            return "green" if _l else "red"

        def get_marker(_l, _c, _s):
            # if _s == "active":
            #     return "v"
            return "+" if _l else "."

        def get_alpha(_l, _c, _s):
            if _s == "active":
                return 0.5
            elif _s == "new_active":
                return 1
            elif _s == "excluded":
                return 0.2

        for label in [True, False]:
            for correct in [True, False]:
                for status in ["active", "new_active", "excluded"]:
                    marker, color, alpha = [
                        f(label, correct, status)
                        for f in (get_marker, get_color, get_alpha)
                    ]
                    selection = [
                        p for l, c, s, p in points
                        if l == label and c == correct and s == status
                    ]
                    if len(selection) > 0:
                        ax.scatter(*zip(*selection),
                                   c=color,
                                   marker=marker,
                                   alpha=alpha)

        ax.set_xlim(domain.var_domains[feat_x])
        ax.set_ylim(domain.var_domains[feat_y])

    if name is not None:
        plt.savefig(name if name.endswith(".png") else "{}.png".format(name))
    else:
        plt.show()
    plt.close(fig)
Beispiel #12
0
 def test_constant_true(self):
     checker = SmtChecker({})
     self.assertTrue(checker.walk_smt(smt.Bool(True)))
Beispiel #13
0
 def test_constant_false(self):
     checker = SmtChecker({})
     self.assertFalse(checker.walk_smt(smt.Bool(False)))