def cosine_law_crit_angle(self): """Use cosine law to find cos^2(theta) between three points node1---node2---node3 to assert that it is less than cos^2(thetaC) where thetaC is the critical crossing angle :param node1: Outside node :param node2: Middle connecting node :param node3: Outside node :returns: cos^2 as calculated using cosine law (a_dot_b^2/a^2*b^2) """ node1 = self.get_input_nodes().values()[0] node2 = self.get_input_nodes().values()[1] node3 = self.get_output_node() # Lengths of channels aX = Minus(node1.get_x(), node2.get_x()) aY = Minus(node1.get_y(), node2.get_y()) bX = Minus(node3.get_x(), node2.get_x()) bY = Minus(node3.get_y(), node2.get_y()) # Dot products between each channel a_dot_b_squared = Pow(Plus(Times(aX, bX), Times(aY, bY)), Real(2)) a_squared_b_squared = Times( Plus(Times(aX, aX), Times(aY, aY)), Plus(Times(bX, bX), Times(bY, bY)), ) return Div(a_dot_b_squared, a_squared_b_squared)
def test_real(self): f = Plus([ Real(1), Symbol("x", REAL), Symbol("y", REAL)]) self.assertEqual(f.to_smtlib(daggify=False), "(+ 1.0 x y)") self.assertEqual(f.to_smtlib(daggify=True), "(let ((.def_0 (+ 1.0 x y))) .def_0)")
def process(): varA = Symbol("A") varB = Symbol("B") f = And(varA, Not(varB)) print(f) print(is_sat(f)) hello = [Symbol(s, INT) for s in "hello"] world = [Symbol(s, INT) for s in "world"] letters = set(hello + world) domains = And(And(LE(Int(1), l), GE(Int(10), l)) for l in letters) print(domains,'domain') sum_hello = Plus(hello) sum_world = Plus(world) problem = And(Equals(sum_hello, sum_world), Equals(sum_hello, Int(36))) formula = And(domains, problem) print("Serialization of the formula:") print(formula) print(formula.serialize()) print(is_sat(formula)) print(get_model(formula))
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 vertex_cover_solver(graph, k): vertexes, edges = graph # vertex in vertex cover 1 otherwise 0 vertex_vars = [Symbol(v, INT) for v in vertexes] vertex_range = And( [And(GE(v, Int(0)), LE(v, Int(1))) for v in vertex_vars]) # size of vertex cover <= k sum_vertex = Plus(vertex_vars) vertex_constraint = LE(sum_vertex, Int(k)) # edge constraints # Plus(vi, vj) >= 1 for edge = (vi, vj) # cannot use Or(vi, vj), because variables are integers not boolean type edge_constraint = And([ GE(Plus([vertex_vars[lv], vertex_vars[rv]]), Int(1)) for (lv, rv) in edges ]) # combined formula formula = And(vertex_range, vertex_constraint, edge_constraint) model = get_model(formula) size = get_formula_size(formula) cover = set() if model: for i, node in enumerate(vertexes): if model.get_py_value(vertex_vars[i]): cover.add(node) return cover, formula, size else: return None, formula, size
def main(): # Example Transition System (SMV-like syntax) # # VAR x: integer; # y: integer; # # INIT: x = 1 & y = 2; # # TRANS: next(x) = x + 1; # TRANS: next(y) = y + 2; x, y = [Symbol(s, INT) for s in "xy"] nx, ny = [next_var(Symbol(s, INT)) for s in "xy"] example = TransitionSystem(variables=[x, y], init=And(Equals(x, Int(1)), Equals(y, Int(2))), trans=And(Equals(nx, Plus(x, Int(1))), Equals(ny, Plus(y, Int(2))))) # A true invariant property: y = x * 2 true_prop = Equals(y, Times(x, Int(2))) # A false invariant property: x <= 10 false_prop = LE(x, Int(10)) for prop in [true_prop, false_prop]: check_property(example, prop) print("")
def construct_spread_formula_from_graph(spread_graph, limit, target): initial_infection_ints = [ Symbol('init_int_' + str(i), INT) for i in spread_graph.nodes ] final_infection_ints = [ Symbol('final_int_' + str(i), INT) for i in spread_graph.nodes ] spreading_clauses = [] origin_clauses = [] all_bounds = [] # Here, we ensure that, if node i is selected as an initial infector, all of its neighbors are also infected: for starting_node in spread_graph.nodes: initial_infection_bounds = And( LE(initial_infection_ints[int(starting_node)], Int(1)), GE(initial_infection_ints[int(starting_node)], Int(0))) infected_neighbors = And([ Equals(final_infection_ints[int(i)], Int(1)) for i in spread_graph.successors(starting_node) ]) infected_nodes = And( infected_neighbors, Equals(final_infection_ints[int(starting_node)], Int(1))) spreading_forumla = Implies( Equals(initial_infection_ints[int(starting_node)], Int(1)), infected_nodes) spreading_clauses.append(spreading_forumla) all_bounds.append(initial_infection_bounds) # Here, we ensure that, if node i becomes infected, either it was infected by an initial infectors with an edge to node i # of node i itself was an initial infector. for infected_node in spread_graph.nodes: final_infection_bounds = And( LE(final_infection_ints[int(infected_node)], Int(1)), GE(final_infection_ints[int(infected_node)], Int(0))) origin_neighbors = Or([ Equals(initial_infection_ints[int(i)], Int(1)) for i in spread_graph.predecessors(infected_node) ]) origin_nodes = Or( origin_neighbors, Equals(initial_infection_ints[int(infected_node)], Int(1))) origin_formula = Implies( Equals(final_infection_ints[int(infected_node)], Int(1)), origin_nodes) origin_clauses.append(origin_formula) all_bounds.append(final_infection_bounds) initial_infection_limit = LE(Plus(initial_infection_ints), Int(limit)) final_infection_target = GE(Plus(final_infection_ints), Int(target)) return And( And(spreading_clauses), And(origin_clauses), And(all_bounds), initial_infection_limit, final_infection_target), initial_infection_ints, final_infection_ints
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 message(self, tree, spins, subtheta, auxvars): """Determine the energy of the elimination tree. Args: tree (dict): The current elimination tree spins (dict): The current fixed spins subtheta (dict): Theta with spins fixed. auxvars (dict): The auxiliary variables for the given spins. Returns: The formula for the energy of the tree. """ energy_sources = set() for v, children in iteritems(tree): aux = auxvars[v] assert all(u in spins for u in self._ancestors[v]) # build an iterable over all of the energies contributions # that we can exactly determine given v and our known spins # in these contributions we assume that v is positive def energy_contributions(): yield subtheta.linear[v] for u, bias in iteritems(subtheta.adj[v]): if u in spins: yield SpinTimes(spins[u], bias) plus_energy = Plus(energy_contributions()) minus_energy = SpinTimes(-1, plus_energy) # if the variable has children, we need to recursively determine their energies if children: # set v to be positive spins[v] = 1 plus_energy = Plus(plus_energy, self.message(children, spins, subtheta, auxvars)) spins[v] = -1 minus_energy = Plus(minus_energy, self.message(children, spins, subtheta, auxvars)) del spins[v] # we now need a real-valued smt variable to be our message m = FreshSymbol(REAL) ancestor_aux = {auxvars[u] if spins[u] > 0 else Not(auxvars[u]) for u in self._ancestors[v]} plus_aux = And({aux}.union(ancestor_aux)) minus_aux = And({Not(aux)}.union(ancestor_aux)) self.assertions.update({LE(m, plus_energy), LE(m, minus_energy), Implies(plus_aux, GE(m, plus_energy)), Implies(minus_aux, GE(m, minus_energy)) }) energy_sources.add(m) return Plus(energy_sources)
def test_simplifying_int_plus_changes_type_of_expression(self): varA = Symbol("At", INT) varB = Symbol("Bt", INT) get_type = get_env().stc.get_type f = Plus(varB, Int(1)) old_type = get_type(f) f = f.simplify() new_type = get_type(f) self.assertEqual(new_type, old_type)
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 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 k_sequence_WH_worst_case(m, K, K_seq_len=100, count=100): k_seq = [Symbol('x_%i' % i, INT) for i in range(K_seq_len)] domain = And([Or(Equals(x, Int(0)), Equals(x, Int(1))) for x in k_seq]) K_window = And([ LE(Plus(k_seq[t:min(K_seq_len, t + K)]), Int(m)) for t in range(max(1, K_seq_len - K + 1)) ]) violate_up = And([ GT(Plus(k_seq[t:min(K_seq_len, t + K)]), Int(m - 1)) for t in range(max(1, K_seq_len - K + 1)) ]) def violate_right_generator(n): return And([ GT(Plus(k_seq[t:min(K_seq_len, t + K + n)]), Int(m)) for t in range(max(1, K_seq_len - (K + n) + 1)) ]) right_shift = 1 formula = And(domain, K_window, violate_up, violate_right_generator(right_shift)) solver = Solver(name='z3', incremental=True, random_seed=randint(2 << 30)) solver.add_assertion(formula) solver.z3.set('timeout', 5 * 60 * 1000) solutions = And() for _ in range(count): while right_shift + K < K_seq_len: try: result = solver.solve() except BaseException: result = None if not result: solver = Solver(name='z3', incremental=True, random_seed=randint(2 << 30)) right_shift += 1 solver.z3.set('timeout', 5 * 60 * 1000) solver.add_assertion( And(solutions, domain, K_window, violate_up, violate_right_generator(right_shift))) else: break try: model = solver.get_model() except BaseException: break model = array(list(map(lambda x: model.get_py_value(x), k_seq)), dtype=bool) yield model solution = Or( [NotEquals(k_seq[i], Int(model[i])) for i in range(K_seq_len)]) solutions = And(solutions, solution) solver.add_assertion(solution)
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 get_x_coefficient(atom: FNode): """ obtain coefficient of variable in univariate LRA :param atom: FNode atom :return: coeffcient of variable, type FNode """ variable = list(get_real_variables(atom)) assert len(variable) == 1 var = variable[0] const = get_constants(atom) new_atom = Plus(atom, -const) new_atom = new_atom.substitute({var: Real(1)}) return simplify(new_atom)
def message_upperbound(self, tree, spins, subtheta): """Determine an upper bound on the energy of the elimination tree. Args: tree (dict): The current elimination tree spins (dict): The current fixed spins subtheta (dict): Theta with spins fixed. Returns: The formula for the energy of the tree. """ energy_sources = set() for v, subtree in tree.items(): assert all(u in spins for u in self._ancestors[v]) # build an iterable over all of the energies contributions # that we can exactly determine given v and our known spins # in these contributions we assume that v is positive def energy_contributions(): yield subtheta.linear[v] for u, bias in subtheta.adj[v].items(): if u in spins: yield Times(limitReal(spins[u]), bias) energy = Plus(energy_contributions()) # if there are no more variables in the order, we can stop # otherwise we need the next message variable if subtree: spins[v] = 1. plus = self.message_upperbound(subtree, spins, subtheta) spins[v] = -1. minus = self.message_upperbound(subtree, spins, subtheta) del spins[v] else: plus = minus = limitReal(0.0) # we now need a real-valued smt variable to be our message m = FreshSymbol(REAL) self.assertions.update({ LE(m, Plus(energy, plus)), LE(m, Plus(Times(energy, limitReal(-1.)), minus)) }) energy_sources.add(m) return Plus(energy_sources)
def feed_data(self, X, Y): formula = [] for x, y in zip(X, Y): x_formula = [] for i, (weight, bias) in self.net_formula.items(): if i == 0: x_hidden = [] for r, w_r in enumerate(weight): tmp = Plus([Plus(Times(w, Real(float(x[c]))), bias[r]) for c, w in enumerate(w_r)]) if self.activation == 'relu': x_hidden.append(Max(tmp, Real(0))) else: x_hidden.append(tmp) """node_output = [] for c, w in enumerate(w_r): var = Plus(Times(w, Real(float(x[c]))), bias[r]) exp_3 = Pow(var, Real(3)) #exp_5 = Pow(var, Real(5)) sen_2 = Times(Real(0.25), var) sen_3 = Times(Real(0.02), exp_3) #sen_4 = Times(Real(0.002), exp_5) node_output.append(Plus(Real(0.5), sen_2, sen_3))#, sen_4)) matrix_addition = Plus(node_output[i] for i in range(len(node_output))) x_hidden.append(matrix_addition)""" x = x_hidden else: x_hidden = [] for r, w_r in enumerate(weight): tmp = Plus([Plus(Times(w, x[c]), bias[r]) for c, w in enumerate(w_r)]) if self.activation == 'relu' and i < len(self.net_formula) - 1: x_hidden.append(Max(tmp, Real(0))) else: x_hidden.append(tmp) """node_output = [] for c, w in enumerate(w_r): var = Plus(Times(w, x[c]), bias[r]) exp_3 = Pow(var, Real(3)) #exp_5 = Pow(var, Real(5)) sen_2 = Times(Real(0.25), var) sen_3 = Times(Real(0.02), exp_3) #sen_4 = Times(Real(0.002), exp_5) node_output.append(Plus(Real(0.5), sen_2, sen_3)) #, sen_4)) matrix_addition = Plus(node_output[i] for i in range(len(node_output))) x_hidden.append(matrix_addition)""" x = x_hidden ## Add activation function if np.argmax(y) == 0: x_formula.append(GE(x[0], x[1])) else: x_formula.append(GE(x[1], x[0])) return And(x_formula)
def convert(self, abstract=False): for i in range(self.nnet.inputSize): x = Symbol("x%d" % i, REAL) self.input_vars.append(x) for i in range(self.nnet.outputSize): y = Symbol("y%d" % i, REAL) self.output_vars.append(y) # for i,v in enumerate(self.input_vars): # # normalized # m = self.nnet.mins[i] # l = GE(self.input_vars[i], # Real((m - self.nnet.means[i])/self.nnet.ranges[i])) # self.formulae.append(l) # # normalized # m = self.nnet.maxes[i] # l = LE(self.input_vars[i], # Real((m - self.nnet.means[i])/self.nnet.ranges[i])) # self.formulae.append(l) prev_layer_result = self.input_vars.copy() layer_result = [] zero = Real(0) self.relus_level.append(set()) for l in range(self.nnet.numLayers - 1): self.relus_level.append(set()) for ls in range(self.nnet.layerSizes[l + 1]): r = self.dot(self.nnet.weights[l][ls], prev_layer_result) r = Plus(r, Real(float(self.nnet.biases[l][ls]))) relu_in = FreshSymbol(REAL) self.formulae.append(Equals(relu_in, r)) if abstract: relu_out = FreshSymbol(REAL) r = relu_out self.relus.append((relu_out, relu_in)) self.relus_level[l + 1].add((relu_out, relu_in)) else: r = Max(relu_in, zero) layer_result.append(r) prev_layer_result = layer_result.copy() layer_result.clear() for i, y in enumerate(self.output_vars): o = self.dot(self.nnet.weights[-1][i], prev_layer_result) o = Plus(o, Real(float(self.nnet.biases[-1][i]))) # # undo normalization # o = Times(o, Real(self.nnet.ranges[-1])) # o = Plus(o, Real(self.nnet.means[-1])) self.formulae.append(Equals(y, o)) self.parse_violation(self.violation_path)
def test_msat_back_not_identical(self): from pysmt.solvers.msat import MathSAT5Solver, MSatConverter env = get_env() msat = MathSAT5Solver(environment=env, logic=QF_UFLIRA) new_converter = MSatConverter(env, msat.msat_env) r, s = FreshSymbol(REAL), FreshSymbol(REAL) # r + 1 > s + 1 f = GT(Plus(r, Real(1)), Plus(s, Real(1))) term = new_converter.convert(f) res = new_converter.back(term) self.assertFalse(f == res)
def test_plus_algebraic(self): from pysmt.constants import Numeral env = get_env() mgr = env.formula_manager r0 = Symbol("r0", REAL) p_2 = Real(2) m_5 = mgr._Algebraic(Numeral(-5)) m_3 = mgr._Algebraic(Numeral(-3)) # r0 + 2 - 5 expr = Plus(r0, p_2, m_5) res = expr.simplify() self.assertValid(Equals(expr, res)) self.assertIn(m_3, res.args())
def triangle(nvars, rand_gen): # alpha = rand_gen.uniform(0.05, 0.25) alpha = rand_gen.uniform(0.2, 0.25) remain = nvars % 3 n_tris = int(nvars / 3) variables = [Symbol(f"x{i}", REAL) for i in range(1, nvars + 1)] lbounds = [LE(Real(0), x) for x in variables] ubounds = [LE(x, Real(1)) for x in variables] clauses = [] potentials = [] for i in range(n_tris): x, y, z = variables[3 * i], variables[3 * i + 1], variables[3 * i + 2] xc = None if 3 * i + 3 >= nvars else variables[3 * i + 3] # x_i clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) # x_i -- y_i clauses.append( Or(LE(y, Plus(x, Real(-alpha))), LE(Plus(x, Real(alpha)), y))) # x_i -- z_i clauses.append(Or(LE(Real(1 - alpha), x), LE(Real(1 - alpha), z))) clauses.append(Or(LE(x, Real(alpha)), LE(z, Real(alpha)))) # z_i -- y_i clauses.append(LE(z, y)) # x_i -- x_i+1 if xc: clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), xc))) clauses.append(Or(LE(Real(1 - alpha), x), LE(xc, Real(alpha)))) pot_yz = Ite(LE(z, y), Times([z, y, Real(100)]), Real(1)) pot_xy = Ite(LE(y, Plus(x, Real(-alpha))), Times(Real(100), Plus(x, y)), Real(1)) potentials.append(pot_xy) potentials.append(pot_yz) if remain == 1: x = variables[3 * n_tris] clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) if remain == 2: x, y = variables[3 * n_tris], variables[nvars - 1] # x_n clauses.append(Or(LE(x, Real(alpha)), LE(Real(1 - alpha), x))) # x -- y clauses.append( Or(LE(y, Plus(x, Real(-alpha))), LE(Plus(x, Real(alpha)), y))) potentials.append( Ite(LE(y, Plus(x, Real(-alpha))), Times(Real(100), Plus(x, y)), Real(1))) domain = Domain.make( [], # no booleans [x.symbol_name() for x in variables], [(0, 1) for _ in range(len(variables))]) support = And(lbounds + ubounds + clauses) weight = Times(potentials) if len(potentials) > 1 else potentials[0] return Density(domain, support, weight, []), alpha
def test_substitution_on_functions(self): i, r = FreshSymbol(INT), FreshSymbol(REAL) f = Symbol("f", FunctionType(BOOL, [INT, REAL])) phi = Function(f, [Plus(i, Int(1)), Minus(r, Real(2))]) phi_sub = substitute(phi, {i: Int(0)}).simplify() self.assertEqual(phi_sub, Function(f, [Int(1), Minus(r, Real(2))])) phi_sub = substitute(phi, {r: Real(0)}).simplify() self.assertEqual(phi_sub, Function(f, [Plus(i, Int(1)), Real(-2)])) phi_sub = substitute(phi, {r: Real(0), i: Int(0)}).simplify() self.assertEqual(phi_sub, Function(f, [Int(1), Real(-2)]))
def link_constraints(constraints, frameSetSortedByLink): ''' 已验证 ''' # print ('###### 测试link constraints生成 ######') for link in frameSetSortedByLink: subFrameDict = frameSetSortedByLink[link] frameSameLink = [] for vlid in subFrameDict: frameList = subFrameDict[vlid] for frame in frameList: frameSameLink.append(frame) # 对于同一个物理链路的任意两个帧成立: for i in range(len(frameSameLink)): for j in range(i + 1, len(frameSameLink)): frame_i = frameSameLink[i] frame_j = frameSameLink[j] # 挑选不同虚链路的Frame if frame_i.vlid == frame_j.vlid: continue # print('frame_i: {}_{}_{}, T={}, L={}, frame_j: {}_{}_{}, T={}, L={}'.format( # frame_i.vlid, frame_i.lname, frame_i.fid, frame_i.T, frame_i.L, # frame_j.vlid, frame_j.lname, frame_j.fid, frame_j.T, frame_j.L)) hp = lcm(frame_i.T, frame_j.T) # 对于任意的阿尔法和贝塔属于....都满足: for alpha in range(int(hp / frame_i.T)): for beta in range(int(hp / frame_j.T)): # single_link_constraint = Or( # (frame_i.offset + alpha * frame_i.T >= # frame_j.offset + beta * frame_j.T + frame_j.L), # (frame_j.offset + beta * frame_j.T >= frame_i.offset + alpha * frame_i.T + frame_i.L)) single_link_constraint = Or( GE( Plus(frame_i.offset, Int(alpha * frame_i.T)), Plus(frame_j.offset, Int(beta * frame_j.T + frame_j.L))), GE( Plus(frame_j.offset, Int(beta * frame_j.T)), Plus(frame_i.offset, Int(alpha * frame_i.T + frame_i.L)))) #print('alpha={},beta={}:\nconstraint={}'.format( # alpha, beta, single_link_constraint)) constraints.append(single_link_constraint) # print(solver) # print(solver.check()) # print(solver.model()) # pdb.set_trace() # FIXME:提高效率? return True
def test_lira(self): varA = Symbol("A", REAL) varB = Symbol("B", INT) with self.assertRaises(PysmtTypeError): f = And(LT(varA, Plus(varA, Real(1))), GT(varA, Minus(varB, Int(1)))) f = And(LT(varA, Plus(varA, Real(1))), GT(varA, ToReal(Minus(varB, Int(1))))) g = Equals(varA, ToReal(varB)) self.assertUnsat(And(f, g, Equals(varA, Real(1.2))), "Formula was expected to be unsat", logic=QF_UFLIRA)
def _random_polynomial(self, nonnegative=False): if nonnegative: # the sum of squared rational functions is a non-negative polynomial sq_sum = [] for _ in range(randint(1, self.MAX_SRF)): poly = self._random_polynomial() sq_sum.append(Times(poly, poly)) return Plus(sq_sum) else: monomials = [] for i in range(randint(1, self.MAX_MONOMIALS)): monomials.append(self._random_monomial()) return Plus(monomials)
def learn(self, domain, data, border_indices): positive_indices = [i for i in range(len(data)) if data[i][1]] real_vars = [ v for v in domain.variables if domain.var_types[v] == REAL ] bool_vars = [ v for v in domain.variables if domain.var_types[v] == BOOL ] d = len(real_vars) hyperplanes = [] for indices in itertools.combinations(positive_indices, d): print(indices) hyperplanes.append( Learner.fit_hyperplane(domain, [data[i][0] for i in indices])) boolean_data = [] for i in range(len(data)): row = [] for v in bool_vars: row.append(data[i][0][v].constant_value()) boolean_data.append(row) hyperplanes_smt = [] for a, c in hyperplanes: lhs_smt = Plus( Times(Real(float(a[j])), domain.get_symbol(real_vars[j])) for j in range(d)) hyperplanes_smt.append(LE(lhs_smt, Real(c))) lhs_smt = Plus( Times(Real(-float(a[j])), domain.get_symbol(real_vars[j])) for j in range(d)) hyperplanes_smt.append(LE(lhs_smt, Real(-c))) for i in range(len(data)): lhs = 0 for j in range(d): lhs += float(a[j]) * float( data[i][0][real_vars[j]].constant_value()) boolean_data[i].append(lhs <= c) boolean_data[i].append(lhs >= c) print(boolean_data) # logical_dnf_indices = [[i] for i in range(len(boolean_data[0]))] logical_dnf_indices = self.learn_logical(boolean_data, [row[1] for row in data]) logical_dnf = [[ domain.get_symbol(bool_vars[i]) if i < len(bool_vars) else hyperplanes_smt[i - len(bool_vars)] for i in conj_indices ] for conj_indices in logical_dnf_indices] print(logical_dnf) return logical_dnf
def calculate_droplet_volume(self, h, w, wIn, epsilon, qD, qC): """From paper DOI:10.1039/c002625e. Calculating the droplet volume created in a T-junction Unit is volume in m^3 :param Symbol h: Height of channel :param Symbol w: Width of continuous/output channel :param Symbol wIn: Width of dispersed_channel :param Symbol epsilon: Equals 0.414*radius of rounded edge where channels join :param Symbol qD: Flow rate in dispersed_channel :param Symbol qC: Flow rate in continuous_channel """ q_gutter = Real(0.1) # normalizedVFill = 3pi/8 - (pi/2)(1 - pi/4)(h/w) v_fill_simple = Minus( Times(Real((3, 8)), Real(math.pi)), Times( Times(Div(Real(math.pi), Real(2)), Minus(Real(1), Div(Real(math.pi), Real(4)))), Div(h, w))) hw_parallel = Div(Times(h, w), Plus(h, w)) # r_pinch = w+((wIn-(hw_parallel - eps))+sqrt(2*((wIn-hw_parallel)*(w-hw_parallel)))) r_pinch = Plus( w, Plus( Minus(wIn, Minus(hw_parallel, epsilon)), Pow( Times( Real(2), Times(Minus(wIn, hw_parallel), Minus(w, hw_parallel))), Real(0.5)))) r_fill = w alpha = Times( Minus(Real(1), Div(Real(math.pi), Real(4))), Times( Pow(Minus(Real(1), q_gutter), Real(-1)), Plus( Minus(Pow(Div(r_pinch, w), Real(2)), Pow(Div(r_fill, w), Real(2))), Times( Div(Real(math.pi), Real(4)), Times(Minus(Div(r_pinch, w), Div(r_fill, w)), Div(h, w)))))) return Times(Times(h, Times(w, w)), Plus(v_fill_simple, Times(alpha, Div(qD, qC))))
def test_misc(self): bool_list = [ And(self.x, self.y), Or(self.x, self.y), Not(self.x), self.x, Equals(self.p, self.q), GE(self.p, self.q), LE(self.p, self.q), GT(self.p, self.q), LT(self.p, self.q), Bool(True), Ite(self.x, self.y, self.x) ] # TODO: FORALL EXISTS real_list = [ self.r, Real(4), Plus(self.r, self.s), Plus(self.r, Real(2)), Minus(self.s, self.r), Times(self.r, Real(1)), Div(self.r, Real(1)), Ite(self.x, self.r, self.s), ] int_list = [ self.p, Int(4), Plus(self.p, self.q), Plus(self.p, Int(2)), Minus(self.p, self.q), Times(self.p, Int(1)), Ite(self.x, self.p, self.q), ] for f in bool_list: t = self.tc.walk(f) self.assertEqual(t, BOOL, f) for f in real_list: t = self.tc.walk(f) self.assertEqual(t, REAL, f) for f in int_list: t = self.tc.walk(f) self.assertEqual(t, INT, f)
def test_msat_converter_on_msat_error(self): import mathsat import _mathsat from pysmt.solvers.msat import MathSAT5Solver, MSatConverter env = get_env() msat = MathSAT5Solver(env, logic=QF_UFLIRA) new_converter = MSatConverter(env, msat.msat_env) def walk_plus(formula, args): res = mathsat.MSAT_MAKE_ERROR_TERM() return res # Replace the function used to compute the Plus() # with one that returns a msat_error new_converter.set_function(walk_plus, op.PLUS) r, s = FreshSymbol(REAL), FreshSymbol(REAL) f1 = GT(r, s) f2 = Plus(r, s) t1 = new_converter.convert(f1) self.assertFalse(mathsat.MSAT_ERROR_TERM(t1)) with self.assertRaises(InternalSolverError): new_converter.convert(f2)
def energy(self, spins, break_aux_symmetry=True): """A formula for the exact energy of Theta with spins fixed. Args: spins (dict): Spin values for a subset of the variables in Theta. break_aux_symmetry (bool, optional): Default True. If True, break the aux variable symmetry by setting all aux variable to 1 for one of the feasible configurations. If the energy ranges are not symmetric then this can make finding models impossible. Returns: Formula for the exact energy of Theta with spins fixed. """ subtheta = self.theta.fix_variables(spins) # we need aux variables av = next(self._auxvar_counter) auxvars = {v: Symbol('aux{}_{}'.format(av, v), BOOL) for v in subtheta.linear} if break_aux_symmetry and av == 0: # without loss of generality, we can assume that the aux variables are all # spin-up for one configuration self.assertions.update(set(itervalues(auxvars))) trees = self._trees if not trees: # if there are no variables to eliminate, then the offset of # subtheta is the exact value and we can just return it assert not subtheta.linear and not subtheta.quadratic return subtheta.offset energy = Plus(self.message(trees, {}, subtheta, auxvars), subtheta.offset) return energy
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