def generate_strict_cnf(domain, and_count, or_count, half_space_count): half_spaces = [generate_half_space_sample(domain, len(domain.real_vars)) for _ in range(half_space_count)] candidates = [domain.get_symbol(v) for v in domain.bool_vars] + half_spaces candidates += [smt.Not(c) for c in candidates] formulas = [] iteration = 0 max_iterations = 100 * and_count while len(formulas) < and_count: if iteration >= max_iterations: return generate_strict_cnf(domain, and_count, or_count, half_space_count) iteration += 1 formula_candidates = [c for c in candidates] random.shuffle(formula_candidates) formula = [] try: while len(formula) < or_count: next_term = formula_candidates.pop(0) if len(formula) == 0 or smt.is_sat(~smt.Or(*formula) & next_term): formula.append(next_term) except IndexError: continue if len(formulas) == 0 or smt.is_sat(~smt.And(*[smt.Or(*f) for f in formulas]) & smt.Or(*formula)): formulas.append(formula) return smt.And(*[smt.Or(*f) for f in formulas])
def reduce_branch(true): solver.push() solver.add_assertion( smt_test_true if true else smt.Not(smt_test_false)) child_node = self.pool.get_node( node.child_true if true else node.child_false) reduced_node = self._reduce(child_node, solver) solver.pop() return reduced_node
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))
def resolve(self): """We're getting read to try out another policy (because the last one failed, or because we're on our first iteration). Apply any new constraints we've learned, then find a new solution. """ if self.dirty_variables: nogood = sc.And(*self.dirty_variables) self.solver.add_assertion(sc.Not(nogood)) self.dirty_variables = set() self.dirty_buffer = set() sat = self.solver.solve() if not sat: raise UnsatException()
def check(self, sys): styp = type(sys) if styp is BD.VarIntro: smtsym = SMT.Symbol(repr(sys.name), SMT.INT) self._ctxt.set(sys.name, smtsym) self.check(sys.cont) elif styp is BD.RelIntro: Rtyp = SMT.FunctionType(SMT.BOOL, [SMT.INT for i in range(0, sys.n_args)]) smtsym = SMT.Symbol(repr(sys.name), Rtyp) self._ctxt.set(sys.name, smtsym) self.check(sys.cont) elif styp is BD.Guard: pred = self.formula(sys.pred) self._slv.add_assertion(pred) self.check(sys.cont) elif styp is BD.Both: # make sure we can backtrack from the first branch self._slv.push() self._ctxt.push() self.check(sys.lhs) self._ctxt.pop() self._slv.pop() # now the second branch we can just proceed self.check(sys.rhs) elif styp is BD.Check: pred = SMT.Not(self.formula(sys.pred)) failure = self._slv.is_sat(pred) if failure: mapping = self._get_solution(pred) self._err(sys, f"Out of Bounds Access:\n{mapping}") # continue regardless self.check(sys.cont) elif styp is BD.NullSys: pass
def generate_formula(self): for i in range(self.max_tries): print("Generating formula...") samples = self.get_samples() half_spaces = self.get_half_spaces(self.get_samples()) bool_literals = [(self.symbol(v), samples[:, self.domain.variables.index(v)]) for v in self.domain.bool_vars] literal_pool = half_spaces + bool_literals literal_pool += [(smt.Not(l), np.logical_not(bits)) for l, bits in literal_pool] print([(v, len(l)) for v, l in literal_pool]) try: formula = self.get_formula(self.get_name(), literal_pool) return formula except GeneratorError: continue raise RuntimeError( "Could not generate a formula within {} tries".format( self.max_tries))
def _lookup(self, rules, obs, state, buff=True): thing = rules[(state, obs)] if isinstance(thing, list): for (i, formula) in enumerate(thing): if self.solver.get_py_value(formula): ret = i form = formula break else: assert False, "Shouldn't have exhausted loop" else: val = self.solver.get_py_value(thing) # Bool -> 0/1 ret = int(val) # If X=0 led us astray, then put ~X in our big 'nogood' conjunction, rather than X form = thing if val else sc.Not(thing) if buff: self.dirty_buffer.add(form) else: self.dirty_variables.add(form) return ret
def test_bv2pysmt(self): bvx, bvy = Variable("x", 8), Variable("y", 8) psx, psy = bv2pysmt(bvx), bv2pysmt(bvy) self.assertEqual(bv2pysmt(Constant(0, 8)), sc.BV(0, 8)) self.assertEqual(psx, sc.Symbol("x", typing.BVType(8))) self.assertEqual(bv2pysmt(~bvx), sc.BVNot(psx)) self.assertEqual(bv2pysmt(bvx & bvy), sc.BVAnd(psx, psy)) self.assertEqual(bv2pysmt(bvx | bvy), sc.BVOr(psx, psy)) self.assertEqual(bv2pysmt(bvx ^ bvy), sc.BVXor(psx, psy)) self.assertEqual(bv2pysmt(BvComp(bvx, bvy)), sc.Equals(psx, psy)) self.assertEqual(bv2pysmt(BvNot(BvComp(bvx, bvy))), sc.Not(sc.Equals(psx, psy))) self.assertEqual(bv2pysmt(bvx < bvy), sc.BVULT(psx, psy)) self.assertEqual(bv2pysmt(bvx <= bvy), sc.BVULE(psx, psy)) self.assertEqual(bv2pysmt(bvx > bvy), sc.BVUGT(psx, psy)) self.assertEqual(bv2pysmt(bvx >= bvy), sc.BVUGE(psx, psy)) self.assertEqual(bv2pysmt(bvx << bvy), sc.BVLShl(psx, psy)) self.assertEqual(bv2pysmt(bvx >> bvy), sc.BVLShr(psx, psy)) self.assertEqual(bv2pysmt(RotateLeft(bvx, 1)), sc.BVRol(psx, 1)) self.assertEqual(bv2pysmt(RotateRight(bvx, 1)), sc.BVRor(psx, 1)) self.assertEqual(bv2pysmt(bvx[4:2]), sc.BVExtract(psx, 2, 4)) self.assertEqual(bv2pysmt(Concat(bvx, bvy)), sc.BVConcat(psx, psy)) # zeroextend reduces to Concat # self.assertEqual(bv2pysmt(ZeroExtend(bvx, 2)), sc.BVZExt(psx, 2)) self.assertEqual(bv2pysmt(Repeat(bvx, 2)), psx.BVRepeat(2)) self.assertEqual(bv2pysmt(-bvx), sc.BVNeg(psx)) self.assertEqual(bv2pysmt(bvx + bvy), sc.BVAdd(psx, psy)) # bvsum reduces to add # self.assertEqual(bv2pysmt(bvx - bvy), sc.BVSub(psx, psy)) self.assertEqual(bv2pysmt(bvx * bvy), sc.BVMul(psx, psy)) self.assertEqual(bv2pysmt(bvx / bvy), sc.BVUDiv(psx, psy)) self.assertEqual(bv2pysmt(bvx % bvy), sc.BVURem(psx, psy))
def generate(self, n): from bitarray import bitarray count = 0 i = 0 while count < n and i < self.max_tries: print("Generate data set {}".format(count)) i += 1 samples = self.get_samples() half_spaces = self.get_half_spaces(self.get_samples()) bool_literals = [(self.symbol(v), bitarray([sample[v] for sample in samples])) for v in self.domain.bool_vars] literal_pool = half_spaces + bool_literals literal_pool += [(smt.Not(l), ~bits) for l, bits in literal_pool] try: data_set = self.get_formula(self.get_name(i), literal_pool) count += 1 yield data_set except GeneratorError: continue if i == self.max_tries: print("Failed to generate enough data sets after {} tries".format(self.max_tries))
def initialize(self, mdp, colors, hole_options, reward_name, okay_states, target_states, threshold, relation): logger.warning("This approach has been tested sparsely.") prob0E, prob1A = stormpy.compute_prob01min_states( mdp, okay_states, target_states) sink_states = ~okay_states assert len(mdp.initial_states) == 1 self.state_vars = [ smt.Symbol("p_{}".format(i), smt.REAL) for i in range(mdp.nr_states) ] self.state_prob1_vars = [ smt.Symbol("asure_{}".format(i)) for i in range(mdp.nr_states) ] self.state_probpos_vars = [ smt.Symbol("x_{}".format(i)) for i in range(mdp.nr_states) ] self.state_order_vars = [ smt.Symbol("r_{}".format(i), smt.REAL) for i in range(mdp.nr_states) ] self.option_vars = dict() for h, opts in hole_options.items(): self.option_vars[h] = { index: smt.Symbol("h_{}_{}".format(h, opt)) for index, opt in enumerate(opts) } self.transition_system = [] logger.debug("Obtain rewards if necessary") rewards = mdp.reward_models[reward_name] if reward_name else None if rewards: assert not rewards.has_transition_rewards state_rewards = rewards.has_state_rewards action_rewards = rewards.has_state_action_rewards logger.debug( "Model has state rewards: {}, has state/action rewards {}". format(state_rewards, action_rewards)) self.transition_system.append( self.state_prob1_vars[mdp.initial_states[0]]) threshold_inequality, action_constraint_inequality = self._to_smt_relation( relation) # TODO or GE self.transition_system.append( threshold_inequality(self.state_vars[mdp.initial_states[0]], smt.Real(float(threshold)))) state_order_domain_constraint = smt.And([ smt.And(smt.GE(var, smt.Real(0)), smt.LE(var, smt.Real(1))) for var in self.state_order_vars ]) self.transition_system.append(state_order_domain_constraint) #TODO how to ensure that prob is zero if there is no path. select_parameter_value_constraints = [] for h, opts in self.option_vars.items(): select_parameter_value_constraints.append( smt.Or(ov for ov in opts.values())) for i, opt1 in enumerate(opts.values()): for opt2 in list(opts.values())[i + 1:]: select_parameter_value_constraints.append( smt.Not(smt.And(opt1, opt2))) #logger.debug("Consistency: {}".format(smt.And(select_parameter_value_constraints))) self.transition_system.append( smt.And(select_parameter_value_constraints)) for state in mdp.states: if sink_states.get(state.id): assert rewards is None self.transition_system.append( smt.Equals(self.state_vars[state.id], smt.REAL(0))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append( smt.Not(self.state_prob1_vars[state.id])) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append( smt.Equals(self.state_order_vars[state.id], smt.Real(0))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) elif target_states.get(state.id): self.transition_system.append( smt.Equals(self.state_order_vars[state.id], smt.Real(1))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append(self.state_prob1_vars[state.id]) #logger.debug("Constraint: {}".format(self.transition_system[-1])) if rewards is None: self.transition_system.append( smt.Equals(self.state_vars[state.id], smt.Real(1))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) else: self.transition_system.append( self.state_probpos_vars[state.id]) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append( smt.Equals(self.state_vars[state.id], smt.Real(0))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) else: state_in_prob1A = False state_in_prob0E = False if prob0E.get(state.id): state_in_prob0E = True else: self.transition_system.append( smt.Equals(self.state_order_vars[state.id], smt.Real(1))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append( self.state_probpos_vars[state.id]) #logger.debug("Constraint: {}".format(self.transition_system[-1])) if rewards and not state_in_prob0E: if prob1A.get(state.id): self.transition_system.append( self.state_prob1_vars[state.id]) logger.debug("Constraint: {}".format( self.transition_system[-1])) state_in_prob1A = True for action in state.actions: action_index = mdp.nondeterministic_choice_indices[ state.id] + action.id #logger.debug("Action index: {}".format(action_index)) precondition = smt.And([ self.option_vars[hole][list(option)[0]] for hole, option in colors.get(action_index, dict()).items() ]) reward_value = None if rewards: reward_const = (rewards.get_state_reward( state.id) if state_rewards else 0.0) + ( rewards.get_state_action_reward(action_index) if action_rewards else 0.0) reward_value = smt.Real(reward_const) act_constraint = action_constraint_inequality( self.state_vars[state.id], smt.Plus([ smt.Times(smt.Real(t.value()), self. state_vars[t.column]) for t in action.transitions ] + [reward_value] if reward_value else [])) full_act_constraint = act_constraint if state_in_prob0E: if not rewards: full_act_constraint = smt.And( smt.Implies(self.state_probpos_vars[state.id], act_constraint), smt.Implies( smt.Not(self.state_probpos_vars), smt.Equals(self.state_vars[state.id], smt.Real(0)))) self.transition_system.append( smt.Implies( precondition, smt.Iff( self.state_probpos_vars[state.id], smt.Or([ smt.And( self.state_probpos_vars[t.column], smt.LT( self.state_order_vars[ state.id], self.state_order_vars[ t.column])) for t in action.transitions ])))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) if rewards and not state_in_prob1A: # prob_one(state) <-> probpos AND for all succ prob_one(succ) self.transition_system.append( smt.Implies( precondition, smt.Iff( self.state_prob1_vars[state.id], smt.And([ self.state_prob1_vars[t.column] for t in action.transitions ] + [self.state_probpos_vars[state.id]])))) #logger.debug("Constraint: {}".format(self.transition_system[-1])) self.transition_system.append( smt.Implies(precondition, full_act_constraint)) #logger.debug("Constraint: {}".format(self.transition_system[-1])) if rewards: self.transition_system.append( smt.And([smt.GE(sv, smt.Real(0)) for sv in self.state_vars])) else: self.transition_system.append( smt.And([ smt.And(smt.GE(sv, smt.Real(0)), smt.LE(sv, smt.Real(1))) for sv in self.state_vars ])) #print(self.transition_system) formula = smt.And(self.transition_system) logger.info("Start SMT solver") model = smt.get_model(formula) if model: logger.info("SAT: Found {}".format(model)) else: logger.info("UNSAT.")
def walk_not(self, argument): return smt.Not(self.walk_smt(argument))
def walk_implies(self, left, right): return self.walk_smt(smt.Or(smt.Not(left), right))
def bv2pysmt(bv): """Convert a bit-vector type to a pySMT type. >>> from arxpy.bitvector.core import Constant, Variable >>> from arxpy.diffcrypt.smt import bv2pysmt >>> bv2pysmt(Constant(0b00000001, 8)) 1_8 >>> x, y = Variable("x", 8), Variable("y", 8) >>> bv2pysmt(x) x >>> bv2pysmt(x + y) (x + y) >>> bv2pysmt(x <= y) (x u<= y) >>> bv2pysmt(x[4: 2]) x[2:4] """ msg = "unknown conversion of {} to a pySMT type".format(type(bv).__name__) if isinstance(bv, int): return bv if isinstance(bv, core.Variable): return sc.Symbol(bv.name, typing.BVType(bv.width)) if isinstance(bv, core.Constant): return sc.BV(bv.val, bv.width) if isinstance(bv, operation.Operation): args = [bv2pysmt(a) for a in bv.args] if type(bv) == operation.BvNot: if args[0].is_equals(): return sc.Not(*args) else: return sc.BVNot(*args) if type(bv) == operation.BvAnd: return sc.BVAnd(*args) if type(bv) == operation.BvOr: return sc.BVOr(*args) if type(bv) == operation.BvXor: return sc.BVXor(*args) if type(bv) == operation.BvComp: # return sc.BVComp(*args) return sc.Equals(*args) if type(bv) == operation.BvUlt: return sc.BVULT(*args) if type(bv) == operation.BvUle: return sc.BVULE(*args) if type(bv) == operation.BvUgt: return sc.BVUGT(*args) if type(bv) == operation.BvUge: return sc.BVUGE(*args) if type(bv) == operation.BvShl: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVLShl(*args) else: x, r = bv.args offset = 0 while (x.width & (x.width - 1)) != 0: x = operation.ZeroExtend(x, 1) r = operation.ZeroExtend(r, 1) offset += 1 shift = bv2pysmt(x << r) return sc.BVExtract(shift, end=shift.bv_width() - offset - 1) # width = args[0].bv_width() # assert (width & (width - 1)) == 0 # power of 2 # return sc.BVLShl(*args) if type(bv) == operation.BvLshr: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVLShr(*args) else: x, r = bv.args offset = 0 while (x.width & (x.width - 1)) != 0: x = operation.ZeroExtend(x, 1) r = operation.ZeroExtend(r, 1) offset += 1 shift = bv2pysmt(x >> r) return sc.BVExtract(shift, end=shift.bv_width() - offset - 1) # width = args[1].bv_width() # assert (width & (width - 1)) == 0 # power of 2 # return sc.BVLShr(*args) if type(bv) == operation.RotateLeft: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVRol(*args) else: x, r = bv.args n = x.width return bv2pysmt(operation.Concat(x[n - r - 1:], x[n - 1:n - r])) if type(bv) == operation.RotateRight: # Left hand side width must be a power of 2 if (args[0].bv_width() & (args[0].bv_width() - 1)) == 0: return sc.BVRor(*args) else: x, r = bv.args n = x.width return bv2pysmt(operation.Concat(x[r - 1:], x[n - 1:r])) if type(bv) == operation.Ite: if args[0].is_equals(): a0 = args[0] else: a0 = sc.Equals(args[0], bv2pysmt(core.Constant(1, 1))) return sc.Ite(a0, *args[1:]) if type(bv) == operation.Extract: return sc.BVExtract(args[0], args[2], args[1]) if type(bv) == operation.Concat: return sc.BVConcat(*args) if type(bv) == operation.ZeroExtend: return sc.BVZExt(*args) if type(bv) == operation.Repeat: return args[0].BVRepeat(args[1]) if type(bv) == operation.BvNeg: return sc.BVNeg(*args) if type(bv) == operation.BvAdd: return sc.BVAdd(*args) if type(bv) == operation.BvSub: return sc.BVSub(*args) if type(bv) == operation.BvMul: return sc.BVMul(*args) if type(bv) == operation.BvMul: return sc.BVMul(*args) if type(bv) == operation.BvUdiv: return sc.BVUDiv(*args) if type(bv) == operation.BvUrem: return sc.BVURem(*args) raise NotImplementedError(msg)
def prove_properties(junctions): width = max(max(y1 for _, y1, _ in junctions), max(y2 for _, _, y2 in junctions)) + 1 length = max(x for x, _, _ in junctions) formula, belts = balancer_flow_formula(junctions, width, length) supply = s.Plus(beltway[0].rho for beltway in belts) demand = s.Plus(beltway[-1].v for beltway in belts) max_theoretical_throughput = s.Min(supply, demand) actual_throughput = s.Plus(beltway[-1].flux for beltway in belts) fully_balanced_output = [] max_flux = s.Max(b[-1].flux for b in belts) for i, b1 in enumerate(belts): fully_balanced_output.append( s.Or(s.Equals(b1[-1].flux, max_flux), s.Equals(b1[-1].flux, b1[-1].v))) fully_balanced_output = s.And(fully_balanced_output) fully_balanced_input = [] max_flux = s.Max(b[0].flux for b in belts) for i, b1 in enumerate(belts): fully_balanced_input.append( s.Or(s.Equals(b1[0].flux, max_flux), s.Equals(b1[0].flux, b1[0].rho))) fully_balanced_input = s.And(fully_balanced_input) with s.Solver() as solver: solver.add_assertion(s.And(formula)) solver.push() solver.add_assertion( s.Not(s.Equals(max_theoretical_throughput, actual_throughput))) if not solver.solve(): print("It's throughput-unlimited!") else: print("It's throughput-limited; here's an example:") m = solver.get_model() inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts) outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts) print(f'Input lane densities: ({", ".join(map(str, inputs))})') print(f'Output lane velocities: ({", ".join(map(str, outputs))})') check_balancer_flow(junctions, inputs, outputs) solver.pop() solver.push() solver.add_assertion(s.Not(fully_balanced_input)) if not solver.solve(): print("It's input-balanced!") else: print("It's input-imbalanced; here's an example:") m = solver.get_model() inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts) outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts) print(f'Input lane densities: ({", ".join(map(str, inputs))})') print(f'Output lane velocities: ({", ".join(map(str, outputs))})') check_balancer_flow(junctions, inputs, outputs) solver.pop() solver.push() solver.add_assertion(s.Not(fully_balanced_output)) if solver.solve: print("It's output-balanced!") else: print("It's output-imbalanced; here's an example:") m = solver.get_model() inputs = tuple(m.get_py_value(beltway[0].rho) for beltway in belts) outputs = tuple(m.get_py_value(beltway[-1].v) for beltway in belts) print(f'Input lane densities: ({", ".join(map(str, inputs))})') print(f'Output lane velocities: ({", ".join(map(str, outputs))})') check_balancer_flow(junctions, inputs, outputs)
def generate_synthetic_data_sampling(data_sets_per_setting, bool_count, real_count, cnf_or_dnf, k, l_per_term, h, sample_count, max_ratio, seed, prefix="synthetics"): def test_ratio(_indices): return (1 - max_ratio) * sample_count <= len(_indices) <= max_ratio * sample_count data_set_count = 0 domain = generate_domain(bool_count, real_count) while data_set_count < data_sets_per_setting: name = get_synthetic_problem_name(prefix, bool_count, real_count, cnf_or_dnf, k, l_per_term, h, sample_count, seed, max_ratio * 100, data_set_count) samples = [get_sample(domain) for _ in range(sample_count)] half_spaces = [] print("Generating half spaces: ", end="") if real_count > 0: while len(half_spaces) < h: half_space = generate_half_space_sample(domain, real_count) indices = {i for i in range(sample_count) if smt_test(half_space, samples[i])} if True or test_ratio(indices): half_spaces.append((half_space, indices)) print("y", end="") else: print("x", end="") print() bool_literals = [(domain.get_symbol(v), {i for i in range(sample_count) if samples[i][v]}) for v in domain.bool_vars] literal_pool = half_spaces + bool_literals literal_pool += [(smt.Not(l), {i for i in range(sample_count)} - indices) for l, indices in literal_pool] random.shuffle(literal_pool) term_pool = [] print("Generating terms: ", end="") for literals in itertools.combinations(literal_pool, l_per_term): term = smt.Or(*[t[0] for t in literals]) covered = set() all_matter = True for _, indices in literals: prev_size = len(covered) covered |= indices if (len(covered) - prev_size) / sample_count < 0.05: all_matter = False if all_matter: # & test_ratio(covered): term_pool.append((term, covered)) print("y", end="") else: print("x", end="") print() print("Generating formulas: ", end="") random.shuffle(term_pool) counter = 0 max_tries = 10000 for terms in itertools.combinations(term_pool, k): if counter >= max_tries: print("Restart") break formula = smt.And(*[t[0] for t in terms]) covered = {i for i in range(sample_count)} all_matter = True for _, indices in terms: prev_size = len(covered) covered &= indices if prev_size == len(covered): all_matter = False if all_matter & test_ratio(covered): print("y({:.2f})".format(len(covered) / sample_count), end="") synthetic_problem = SyntheticProblem(problem.Problem(domain, formula, name), "cnf", k, l_per_term, h) data_set = synthetic_problem.get_data(sample_count, 1) new_sample_positives = [sample for sample in data_set.samples if sample[1]] if test_ratio(new_sample_positives): print("c({:.2f})".format(len(new_sample_positives) / sample_count)) data_set_count += 1 yield data_set break else: print("r({:.2f})".format(len(new_sample_positives) / sample_count), end="") else: print("x", end="") print(" ", end="") counter += 1 print()
def __getExpressionTree(symbolicExpression): # TODO LATER: take into account bitwise shift operations args = [] castType = None if len(symbolicExpression.args) > 0: for symbolicArg in symbolicExpression.args: arg, type = Solver.__getExpressionTree(symbolicArg) args.append(arg) if castType is None: castType = type else: if castType.literal == 'Integer': if type.literal == 'Real': castType = type # TODO LATER: consider other possible castings if castType.literal == 'Real': for i in range(len(args)): args[i] = pysmt.ToReal(args[i]) if isinstance(symbolicExpression, sympy.Not): if castType.literal == 'Integer': return pysmt.Equals(args[0], pysmt.Int(0)), Type('Bool') elif castType.literal == 'Real': return pysmt.Equals(args[0], pysmt.Real(0)), Type('Bool') elif castType.literal == 'Bool': return pysmt.Not(args[0]), Type('Bool') else: # castType.literal == 'BitVector' return pysmt.BVNot(args[0]), Type('BitVector') elif isinstance(symbolicExpression, sympy.Lt): return pysmt.LT(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.Gt): return pysmt.GT(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.Ge): return pysmt.GE(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.Le): return pysmt.LE(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.Eq): return pysmt.Equals(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.Ne): return pysmt.NotEquals(args[0], args[1]), Type('Bool') elif isinstance(symbolicExpression, sympy.And): if castType.literal == 'Bool': return pysmt.And(args[0], args[1]), Type('Bool') else: # type.literal == 'BitVector' return pysmt.BVAnd(args[0], args[1]), castType elif isinstance(symbolicExpression, sympy.Or): if castType.literal == 'Bool': return pysmt.Or(args[0], args[1]), Type('Bool') else: # type.literal == 'BitVector' return pysmt.BVOr(args[0], args[1]), castType elif isinstance(symbolicExpression, sympy.Xor): return pysmt.BVXor(args[0], args[1]), castType elif isinstance(symbolicExpression, sympy.Add): return pysmt.Plus(args), castType elif isinstance(symbolicExpression, sympy.Mul): return pysmt.Times(args), castType elif isinstance(symbolicExpression, sympy.Pow): return pysmt.Pow(args[0], args[1]), castType # TODO LATER: deal with missing modulo operator from pysmt else: if isinstance(symbolicExpression, sympy.Symbol): symbolType = Variable.symbolTypes[symbolicExpression.name] literal = symbolType.getTypeForSolver() designator = symbolType.designatorExpr1 type = Type(literal, designator) return Solver.__encodeTerminal(symbolicExpression, type), type elif isinstance(symbolicExpression, sympy.Integer): type = Type('Integer') return Solver.__encodeTerminal(symbolicExpression, type), type elif isinstance(symbolicExpression, sympy.Rational): type = Type('Real') return Solver.__encodeTerminal(symbolicExpression, type), type elif isinstance(symbolicExpression, sympy.Float): type = Type('Real') return Solver.__encodeTerminal(symbolicExpression, type), type else: type = Type('Real') return Solver.__encodeTerminal(symbolicExpression, type), type
def __ne__(self, other: 'SMTBit') -> 'SMTBit': return type(self)(smt.Not(smt.Iff(self.value, other.value)))
def smt_to_nested(expression): # type: (FNode) -> str """ Converts an smt expression to a nested formula :param expression: An SMT expression (FNode) :return: A string representation (lisp-style) Functional operators can be: &, |, *, +, <=, <, ^ Variables are represented as (var type name) Constants are represented as (const type name) Types can be: real, int, bool """ def convert_children(op): return "({} {})".format( op, " ".join(smt_to_nested(arg) for arg in expression.args())) def format_type(smt_type): if smt_type == smt.REAL: return "real" if smt_type == smt.INT: return "int" if smt_type == smt.BOOL: return "bool" raise RuntimeError("No type corresponding to {}".format(smt_type)) if expression.is_and(): return convert_children("&") if expression.is_or(): return convert_children("|") if expression.node_type() == IMPLIES: return smt_to_nested( smt.Or(smt.Not(expression.args()[0]), expression.args()[1])) if expression.is_iff(): return smt_to_nested( smt.And(smt.Implies(expression.args()[0], expression.args()[1]), smt.Implies(expression.args()[1], expression.args()[0]))) if expression.is_not(): return convert_children("~") if expression.is_times(): return convert_children("*") if expression.is_plus(): return convert_children("+") if expression.is_minus(): return convert_children("-") if expression.is_ite(): return convert_children("ite") if expression.node_type() == POW: exponent = expression.args()[1] if exponent.is_constant() and exponent.constant_value() == 1: return smt_to_nested(expression.args()[0]) else: return convert_children("^") if expression.is_le(): return convert_children("<=") if expression.is_lt(): return convert_children("<") if expression.is_equals(): return convert_children("=") if expression.is_symbol(): return "(var {} {})".format(format_type(expression.symbol_type()), expression.symbol_name()) if expression.is_constant(): value = expression.constant_value() if isinstance(value, fractions.Fraction): value = float(value) return "(const {} {})".format(format_type(expression.constant_type()), value) raise RuntimeError("Cannot convert {} (of type {})".format( expression, expression.node_type()))
def __invert__(self) -> 'SMTBit': return type(self)(smt.Not(self.value))