def graph_to_tree(graph: Graph, constant: float = 1.0, return_map=False, n_bbox=1): edges, nodes = list(graph.edges), list(graph.nodes) n = len(nodes) node_map = {} for label in range(n): symbol = Symbol("x_{}".format(label), REAL) if n_bbox: node_map[label] = TNode(label=label, symbol=symbol, n_bbox=n_bbox) else: node_map[label] = TNode(label=label, symbol=symbol) for u, v in edges: u, v = min(u, v), max(u, v) # u -> v parent = node_map[u] child = node_map[v] formula = Or(parent.symbol + Real(constant) <= child.symbol, parent.symbol + Real(-constant) >= child.symbol) edge = TEdge(parent=parent, child=child, formula=formula) parent.add_edge(edge) if return_map: return node_map[0], node_map return node_map[0]
def test_plus_negatives(self): r0 = Symbol("r0", REAL) r1 = Symbol("r1", REAL) p_1 = Real(1) m_1 = Real(-1) p_2 = Real(2) m_4 = Real(-4) # 4 * r0 + (-1) * r1 + 2 - 4 neg_r1 = Times(m_1, r1) m_4_r0 = Times(Real(4), r0) expr = Plus(m_4_r0, neg_r1, p_2, m_4) res = expr.simplify() self.assertValid(Equals(expr, res)) stack = [res] while stack: curr = stack.pop() if curr.is_plus(): stack.extend(curr.args()) elif curr.is_minus(): stack.extend(curr.args()) elif curr.is_times(): stack.extend(curr.args()) elif curr.is_constant(): self.assertNotEqual(curr, m_1) self.assertNotEqual(curr, p_1) elif not curr.is_symbol(): # unexpected expression type. self.assertTrue(False)
def test_constant(self): b1 = Bool(True) b2 = Bool(False) r1 = Real(5.5) r2 = Real(5) r3 = Real(-5.5) i1 = Int(4) i2 = Int(-4) b1_string = self.print_to_string(b1) b2_string = self.print_to_string(b2) self.assertEqual(b1_string, "true") self.assertEqual(b2_string, "false") r1_string = self.print_to_string(r1) r2_string = self.print_to_string(r2) r3_string = self.print_to_string(r3) self.assertEqual(r1_string, "(/ 11 2)") self.assertEqual(r2_string, "5.0") self.assertEqual(r3_string, "(- (/ 11 2))") i1_string = self.print_to_string(i1) i2_string = self.print_to_string(i2) self.assertEqual(i1_string, "4") self.assertEqual(i2_string, "(- 4)")
def test_get_strict_formula(self): smtlib_single = """ (set-logic UF_LIRA) (declare-fun x () Bool) (declare-fun y () Bool) (declare-fun r () Real) (assert (> r 0.0)) (assert x) (check-sat) """ smtlib_double = smtlib_single + """ (assert (not y)) (check-sat) """ r = Symbol("r", REAL) x, y = Symbol("x"), Symbol("y") target_one = And(GT(r, Real(0)), x) target_two = And(GT(r, Real(0)), x, Not(y)) stream_in = cStringIO(smtlib_single) f = get_formula(stream_in) self.assertEqual(f, target_one) stream_in = cStringIO(smtlib_double) f = get_formula(stream_in) self.assertEqual(f, target_two) stream_in = cStringIO(smtlib_double) with self.assertRaises(PysmtValueError): f = get_formula_strict(stream_in)
def sanity_b1_r0(): domain = Domain.make(["a"]) a, = domain.get_symbols() support = TRUE() weight = Ite(a, Real(0.3), Real(0.7)) queries = [a, ~a] return Density(domain, support, weight, queries)
def create_smt_formula(data, labels, dim, n_weights): weights = [] biases = [] weight_symbols = [Symbol('weight_{}'.format(i), REAL) for i in range(n_weights[0])] weight_symbols2 = Symbol('weight_out', REAL) weights.append(weight_symbols) weights.append([weight_symbols2]) bias_symbol1 = Symbol('bias_{}'.format(1), REAL) bias_symbol2 = Symbol('bias_{}'.format(2), REAL) biases.append([bias_symbol1]) biases.append([bias_symbol2]) layer_domains = [] layer_input = data for i in range(len(layer_input)): # loop over data # \sum <w_ji, x_i> + b_i g = len(weight_symbols)//2 # Layer 1 weight_input1_i = Plus([Times(w_i, Real(int(x_j))) for w_i, x_j in zip(weight_symbols, layer_input[i])]) prod_bias1_i = Plus(weight_input1_i, bias_symbol1) # Layer 2 weight_input2_i = Plus(Times(prod_bias1_i, weight_symbols2)) prod_bias2_i = Plus(weight_input2_i, bias_symbol2) # output weight_output = prod_bias2_i layer_domain = Equals(weight_output, Real(labels[i])) layer_domains.append(layer_domain) network_domain = And(x for x in layer_domains) dnn_problem = network_domain return dnn_problem, weights, biases
def get_coefficients(atom: FNode): """ obtain coefficient of variable x in atom of form a * x + b * y + const note that when there is a * x + b * x, simplify() doesn't do multiplication but still here we return (a + b) :param atom: FNode, formula :param x: FNode, symbol of variable :return: dict with keys as variable symbol and values as coefficient in atom """ variables = list(get_real_variables(atom)) coefficients = defaultdict(int) if len(variables) == 0: return coefficients const = get_constants(atom) atom = simplify(Plus(atom, -const)) sub_dict = dict().fromkeys(variables, Real(0)) for i in range(len(variables)): sub_dict[variables[i]] = Real(1) coefficient = simplify(atom.substitute(sub_dict)) coefficients[variables[i]] = coefficient sub_dict[variables[i]] = Real(0) return coefficients
def operator_to_bound(self, inequality: LinearInequality, var_name: str): result = Real(inequality.b()) for other in inequality.variables: if other != var_name: result += Symbol(other, REAL) * Real(-inequality.coefficient(other)) return simplify(result * Real(1 / inequality.coefficient(var_name)))
def __init__(self, expression, aliases={}): """Default constructor. Takes as input a pysmt formula representing a linear inequality and a dictionary of aliases to be substituted before the parsing. Args: expression (FNode): The pysmt formula representing the inequality. aliases (dict {FNode : FNode}): The dictionary containing the aliases definitions. Raises: WMIParsingException: If the expression is not an inequality or the polynomial has degree more than 1. """ if not (expression.is_le() or expression.is_lt()): raise WMIParsingException(WMIParsingException.NOT_AN_INEQUALITY, expression) left, right = expression.args() if right.is_real_constant(): # Polynomial OP Constant self._parse_expression(left, right, False, aliases) elif left.is_real_constant(): # Constant OP Polynomial self._parse_expression(right, left, True, aliases) else: # Polynomial1 OP Polynomial2 converted into Polynomial1 - Polynomial2 OP 0 self._parse_expression(Plus(left,Times(Real(-1),right)),Real(0), False, aliases)
def simple_checker_problem(): theory = Or( And(LE(Symbol("x", REAL), Real(0.5)), LE(Symbol("y", REAL), Real(0.5))), And(GT(Symbol("x", REAL), Real(0.5)), GT(Symbol("y", REAL), Real(0.5))) ) return xy_domain(), theory, "simple_checker"
def test_reals(self): f = And(LT(Symbol("x", REAL), Real(2)), LE(Symbol("x", REAL), Real(3))) for n in self.all_solvers: with Solver(name=n, logic=QF_UFLRA) as s: s.add_assertion(f) res = s.solve() self.assertTrue(res)
def test_solving_under_assumption_theory(self): x = Symbol("x", REAL) y = Symbol("y", REAL) v1 = GT(x, Real(10)) v2 = LE(y, Real(2)) xor = Or(And(v1, Not(v2)), And(Not(v1), v2)) for name in get_env().factory.all_solvers(logic=QF_LRA): with Solver(name=name) as solver: solver.add_assertion(xor) res1 = solver.solve(assumptions=[v1, Not(v2)]) model1 = solver.get_model() res2 = solver.solve(assumptions=[Not(v1), v2]) model2 = solver.get_model() res3 = solver.solve(assumptions=[v1, v2]) self.assertTrue(res1) self.assertTrue(res2) self.assertFalse(res3) self.assertEqual(model1.get_value(v1), TRUE()) self.assertEqual(model1.get_value(v2), FALSE()) self.assertEqual(model2.get_value(v1), FALSE()) self.assertEqual(model2.get_value(v2), TRUE())
def test_div_by_0(self): varA = Symbol('A', REAL) varB = Symbol('B', REAL) f = And(Equals(varA, varB), Not(Equals(Div(varA, Real(0)), Div(varB, Real(0))))) self.assertUnsat(f)
def to_smt(self): keys = { key: Times(Symbol(n, REAL) for n in key) if key != CONST_KEY else Real(1.0) for key in self.poly_dict.keys() } return Plus(keys[key] * Real(value) if value != 1 else keys[key] for key, value in self.poly_dict.items())
def _real_example(self, qe): # Real Example r, s = Symbol("r", REAL), Symbol("s", REAL) f = ForAll([r], Implies(LT(Real(0), r), LT(s, r))) qf = qe.eliminate_quantifiers(f).simplify() self.assertEqual(qf, LE(s, Real(0)))
def dot(self, num_list, pysmt_list): assert (len(num_list) == len(pysmt_list)) res = Real(0) for n in range(len(num_list)): nreal = Real(float(num_list[n])) prod = Times(pysmt_list[n], nreal) res = Plus(res, prod) return res
def regularize(self, l=0.5): w_reg_list = [] for i, (weight, _) in self.net_formula.items(): # print(i) w_reg_list.append(Plus([Pow(w, Real(2)) for w_r in weight for w in w_r])) # print(w_reg_list[-1]) regularize = And([And(GE(w, Real(-l)), LT(w, Real(l))) for w in w_reg_list]) return regularize
def run_rcwmi(density, n_bins, complits, maxiters, rand_gen, log_path, cache=True, nproc=None): if nproc is None: nproc = 1 #log_path = join(output_folder, "comp_log.json") if not isfile(log_path): print("Running RCWMI") print(f"N. compensating literals: {complits}") print(f"Max. iterations: {maxiters}") print(f"N. processes: {nproc}") # create bin queries debug_queries = [] xvals = {} for xvar in density.domain.get_real_symbols(): x = xvar.symbol_name() low, up = density.domain.var_domains[x] slices = [(i / n_bins) * (up - low) + low for i in range(0, n_bins + 1)] xvals[x] = slices[:-1] for i in range(len(slices) - 1): l, u = slices[i], slices[i + 1] debug_queries.append(LE(Real(l), xvar)) debug_queries.append(LE(xvar, Real(u))) t0 = time.perf_counter() rcwmi = RCWMI(density.support, density.weight, n_comp_lits=complits, rand_gen=rand_gen, max_compensate_iters=maxiters, log_path=log_path, debug_queries=debug_queries, n_processes=nproc) t1 = time.perf_counter() # adding xvals and runtime to the log with open(log_path, 'r') as f: log = json.load(f) log['runtime'] = t1 - t0 log['xvals'] = xvals with open(log_path, 'w') as f: json.dump(log, f) else: print(f"Found {log_path}")
def test_msat_back_not_identical(self): msat = Solver(name="msat", logic=QF_UFLIRA) r, s = FreshSymbol(REAL), FreshSymbol(REAL) # r + 1 > s + 1 f = GT(Plus(r, Real(1)), Plus(s, Real(1))) term = msat.converter.convert(f) res = msat.converter.back(term) self.assertFalse(f == res)
def ex1_b2_r2(): domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)]) a, b, x, y = domain.get_symbols(domain.variables) support = (a | b) & (~a | ~b) & (x >= 0.0) & (x <= y) & (y <= 1.0) weight = Ite(a, Real(0.6), Real(0.4)) * Ite(b, Real(0.8), Real(0.2))\ * (Ite(x >= Real(0.5), Real(0.5) * x + Real(0.1) * y, Real(0.1) * x + Real(0.7) * y)) return Density(domain, support, weight, [x <= y / 2])
def test_constant(self): b1 = Bool(True) b2 = Bool(False) r1 = Real(5.5) r2 = Real(5) r3 = Real(-5.5) i1 = Int(4) i2 = Int(-4) self.assertEqual(b1.to_smtlib(daggify=True), "true") self.assertEqual(b2.to_smtlib(daggify=True), "false") self.assertEqual(r1.to_smtlib(daggify=True), "(/ 11 2)") self.assertEqual(r2.to_smtlib(daggify=True), "5.0") self.assertEqual(r3.to_smtlib(daggify=True), "(- (/ 11 2))") self.assertEqual(i1.to_smtlib(daggify=True), "4") self.assertEqual(i2.to_smtlib(daggify=True), "(- 4)") self.assertEqual(b1.to_smtlib(daggify=False), "true") self.assertEqual(b2.to_smtlib(daggify=False), "false") self.assertEqual(r1.to_smtlib(daggify=False), "(/ 11 2)") self.assertEqual(r2.to_smtlib(daggify=False), "5.0") self.assertEqual(r3.to_smtlib(daggify=False), "(- (/ 11 2))") self.assertEqual(i1.to_smtlib(daggify=False), "4") self.assertEqual(i2.to_smtlib(daggify=False), "(- 4)")
def test_substitution_term(self): x, y = FreshSymbol(REAL), FreshSymbol(REAL) # y = 0 /\ Forall x. x > 3 f = And(Equals(y, Real(0)), ForAll([x], GT(x, Real(3)))) subs = {GT(x, Real(3)): TRUE()} f_subs = substitute(f, subs) # Since 'x' is quantified, we cannot replace the term # therefore the substitution does not yield any result. self.assertEqual(f_subs, f)
def to_weight_function(self): if self.is_leaf(): return Real(self.weight) else: if self.split_variable.symbol_type() == BOOL: condition = self.split_variable else: condition = LE(self.split_variable, Real(self.split_value)) return Ite(condition, self.pos.to_weight_function(), self.neg.to_weight_function())
def constructRewardMatrix(intents, tuples, matches): rewardMatrix = dict() for intent in intents: rewardMatrix[intent] = dict() for tup in tuples: if (intent, tup) in matches: rewardMatrix[intent][tup] = Real(1) else: rewardMatrix[intent][tup] = Real(0) return rewardMatrix
def test_plot_xor(): domain = Domain.make(["a", "b"], ["x", "y"], [(0, 1), (0, 1)]) a, b, x, y = domain.get_symbols() formula = ((x * -2.539851974031258e-15 + y * 3.539312736703863e-15 <= Real(0.0)) | ~a | ~b) \ & (a | b) \ & (Real(0.0) < x * -2.539851974031258e-15 + y * 3.539312736703863e-15) with TemporaryFile(suffix=".png") as filename: plot_formula(filename, domain, formula) image = Image.open(filename) assert image.getpixel((900, 900)) == image.getpixel((300, 300))
def test_sum_all_negatives(self): r0 = Symbol("r0", REAL) r1 = Symbol("r1", REAL) m_1 = Real(-1) # -4 * r0 + (-1) * r1 neg_r1 = Times(m_1, r1) m_4_r0 = Times(Real(-4), r0) expr = Plus(m_4_r0, neg_r1) res = expr.simplify() self.assertValid(Equals(expr, res))
def ex_jonathan(): domain = Domain.make(["f0", "d0"], ["r0"], [(10, 45)]) f0, d0 = domain.get_bool_symbols() r0, = domain.get_real_symbols() support = ((f0 & (((d0 | ~d0) & ~(r0 <= 35)) | ((r0 <= 35) & (~d0)))) | (~f0 & (d0 & (r0 <= 35)))) & domain.get_bounds() weight_function = Ite(f0, Real(0.0001), Real(0.00001)) * \ Ite(d0, (r0/10)-1, 8-(r0/10)) * \ Ite(r0 <= 35, -0.001*(r0-27)*(r0-27)+0.3, -0.001*(r0-27)*(r0-27)+0.3) return Density(domain, support, weight_function, queries=[d0])
def bounds_to_SMT(self): formula = [] for var in self.bounds: if var.symbol_type() == REAL: lower, upper = self.bounds[var] formula.append(And(LE(Real(lower), var), LE(var, Real(upper)))) elif self.bounds[var] is not None: bool_bound = var if self.bounds[var] else Not(var) formula.append(bool_bound) return And(formula)
def hist_to_piecewise_constant(var, breaks, ys): assert (len(breaks) == len(ys)), "dimensions mismatch" assert(all(breaks[i-1] < breaks[i] for i in range(1,len(breaks)))),\ "bin bounds should be sorted" else_branch = Real(0) for i in range(1, len(breaks)): assert (breaks[i - 1] < breaks[i]) interval = And(LE(Real(breaks[i - 1]), var), LE(var, Real(breaks[i]))) else_branch = Ite(interval, Real(ys[i], else_branch)) return else_branch
def test_clear_pop_smtlibsolver(self): for n in self.all_solvers: with Solver(name=n, logic=QF_LRA) as s: x1, x2 = [Symbol(var, REAL) for var in ["x1", "x2"]] init = LT(Plus(x1, Real(-1), x2), Real(Fraction(1, 4))) invar = TRUE() safe = LT(Plus(x1, x2), Real(8)) invar_init = And(invar, init) iv_imp = Implies(invar, safe) self.assertFalse(s.is_unsat(invar_init)) self.assertFalse(s.is_valid(iv_imp))
def setUp(self) -> None: parent_symbol = Symbol("x", REAL) child_symbol = Symbol("y", REAL) # y < 2x+1 or y > x - 1 or x > 2 or y > 0.1 atom0 = LE(child_symbol, Real(2) * parent_symbol + Real(1)) atom1 = LE(parent_symbol - 1, child_symbol) atom2 = LE(Real(2), parent_symbol) atom3 = LE(Real(0.1), child_symbol) atom4 = LE(child_symbol, Real(0.4)) self.parent_symbol = parent_symbol self.child_symbol = child_symbol self.atoms = [atom0, atom1, atom2, atom3, atom4] self.formula = Or(self.atoms[:4])