def solve_23_part_2(nanobots: List[Nanobot]): print('Starting up') origin = (0, 0, 0) x, y, z, in_range = z3.Ints('x y z in_range') in_range = in_range * 0 print('Vars declared') for bot in nanobots: in_range += z3.If(z3distance(bot.loc_tuple(), (x, y, z)) <= bot.radius, 1, 0) print('In range calc prep done') optimizer = z3.Optimize() print('Created optimizer, setting max/min functions') optimizer.maximize(in_range) optimizer.minimize(z3distance(origin, (x, y, z))) print('Checking optimizer') optimizer.check() print('Getting model') model = optimizer.model() print('Returning values') origin_loc = Point3d(0, 0, 0) found_loc = Point3d(model[x].as_long(), model[y].as_long(), model[z].as_long()) distance_to_found_loc = manhattan_distance_3d(origin_loc, found_loc) bots_at_loc = search_point(found_loc, nanobots) print('Distance from {} to {}: {}. Bots in range: {}'.format(origin_loc, found_loc, distance_to_found_loc, len(bots_at_loc))) return distance_to_found_loc
def __init__(self, xes_log, threshold): self.xes_log = xes_log self.xes_tree = ET.parse(xes_log) self.sample_confidence = 1.0 self.threshold = threshold self.rules = 3 self.rocknum = -1 self.size = -1 self.rocks = [] self.beliefs = [] self.actions = [] self.positions = [] self.runs = [] self.steps = [] self.collected = [] self.build_from_xes() self.solver = z3.Optimize() self.thresholds = [[] for i in range(self.rules)] self.soft_constr = [[] for i in range(self.rules)]
def __init__(self, hypergraph, wprecision=20, timeout=0, stream=StringIO(), checker_epsilon=None, ghtd=False, solver_bin=None, debug=False): self.debug = debug if not checker_epsilon: checker_epsilon = Decimal(0.001) self.__checker_epsilon = checker_epsilon self.hypergraph = hypergraph self.num_vars = 1 self.num_cls = 0 self.timeout = timeout self.ord = None self.arc = None self.weight = None # self.__solver = z3.Solver() self.__solver = z3.Optimize() self.__clauses = [] self._vartab = {} self.stream = stream self.cards = [] self.wprecision = wprecision self.stream.write( '(set-option :print-success true)\n(set-option :produce-models true)\n' ) self.ghtd = ghtd
def create_solver(cls, maximize=None): if maximize is None: solver = z3.Solver() else: solver = z3.Optimize() solver.set(timeout=settings.SOLVER_TIMEOUT) return solver
def optimal_point(self): # https://www.reddit.com/r/adventofcode/comments/a8s17l/2018_day_23_solutions/ecdcbin p = tuple(z3.Int(c) for c in "xyz") # optimal (x, y, z) # the number of bots that can reach position p reachable_bot_count = sum( z3.If(z3_man_dist(p, b.p.to_tuple()) <= b.r, 1, 0) for b in self.nanobots) # man distance between p and origin origin_distance = z3_man_dist(p, ORIGIN.to_tuple()) # create optimization problem opt = z3.Optimize() # add constraints opt.maximize(reachable_bot_count) opt.minimize(origin_distance) # solve the problem opt.check() model = opt.model() # get the values we care about from the model return Point(*(model[c].as_long() for c in p))
def solve(self) -> Optional[SchedulingSolution]: s = z3.Optimize() # soft constraint to guide the solver towards the suggested model sumweight = 0 if self._suggested_solution: for i in range(self._suggested_solution.number_of_steps()): lhs = FTerm(self._steps_dt.get_constructor("step" + str(i))).z3_expr() for bhv in self._suggested_solution.step(i): assert bhv in self._sequences[bhv.component_instance()] bhv_idx = self._sequences[bhv.component_instance()].index( bhv) bhv_fun = self._bhv_dt.get_constructor( bhv.component_instance().id() + "_" + bhv.behavior().name() + "_" + str(bhv_idx)) rhs = FTerm(self._schedule_fun, FTerm(bhv_fun)).z3_expr() s.add_soft(lhs == rhs) sumweight += 1 # soft constraint to minimize the number of steps in the schedule for bhv_fun in self._bhv_dt.constructors(): lhs = FTerm(self._schedule_fun, FTerm(bhv_fun)).z3_expr() for step in range(1, self._n_steps): rhs = FTerm( self._steps_dt.get_constructor("step" + str(step))).z3_expr() # heavier weight for later steps # the weight is heavier than the sum of weight for suggested model s.add_soft(lhs != rhs, weight=sumweight + step) # hard constraints s.add([c.z3_expr() for c in self._constraints]) r: z3.CheckSatResult = SchedulingStatistics.check_with_stats(s) return self._solution_from_model(s.model()) if r == z3.sat else None
def part2(nanobots): # New library! Let's learn z3! optimiser = z3.Optimize() def z3_abs(x): return z3.If(x >= 0, x, -x) def z3_mdist(pos1, pos2): return z3_abs(pos1[0] - pos2[0]) + z3_abs(pos1[1] - pos2[1]) + z3_abs(pos1[2] - pos2[2]) cand = tuple(map(z3.Int, "xyz")) near_bots = sum( z3.If(z3_mdist(cand, pos) <= rad, 1, 0) for pos, rad in nanobots) optimiser.maximize(near_bots) # Get the one closest to 0, 0, 0. optimiser.minimize(z3_mdist(cand, (0, 0, 0))) optimiser.check() model = optimiser.model() return m_dist((0, 0, 0), map(lambda c: model[c].as_long(), cand))
def __init__(self, regex_str, num_captures: int, valid: List[List[str]], condition_invalid: List[List[str]]): self.solver = z3.Optimize() self.num_captures = num_captures self.condition_operators = utils.condition_operators self.conditions = list(self.condition_operators.keys()) valid = list(map(lambda x: x[0], valid)) assert isinstance(valid, List) and isinstance(valid[0], str) condition_invalid = list(map(lambda x: x[0], condition_invalid)) assert isinstance(condition_invalid, List) and isinstance( condition_invalid[0], str) self.compiled_re = re.compile(regex_str) self.model = None self._init_z3_variables(valid, condition_invalid) self.solver.add(self._make_a_constraints(valid, valid=True)) self.solver.add( self._make_a_constraints(condition_invalid, valid=False)) # Soft clauses to minimize the number of used conditions: for u in self.us.values(): self.solver.add_soft(z3.Not(u))
def iterative(basename, maximize=False): capacity, sizes, requests, caches = io.read_file(basename + '.in') result = 0 #25234071 print('preparing...') constraints = generate_constraints(capacity, sizes, requests, caches) s = z3.Optimize() if maximize else z3.Solver() for c in constraints: s.add(c) if maximize: s.maximize(SERVE) while True: target = int(result) print('solving round for', target) s.add(SERVE > target) s.check() try: m = s.model() except z3.Z3Exception: print('UNSAT') break result = int(str(m.evaluate(SERVE))) print('found', result) d = { c: [v for v in videos if m.evaluate(has_video(v, c))] for c, videos in caches.items() } io.write_file("{}/{}.txt".format(basename, result), d) if maximize: break
def distance_to_point_in_range_of_most_nanobots( nanobots: Iterable[Nanobot]) -> int: x_coord = z3.Int("x") y_coord = z3.Int("y") z_coord = z3.Int("z") bots_in_range = { z3.Int(f"in_range_{botno}"): bot.z3_in_range_of(x_coord, y_coord, z_coord) for botno, bot in enumerate(nanobots) } opt = z3.Optimize() for variable, constraint in bots_in_range.items(): opt.add(variable == constraint) bot_count = z3.Int("bot_count") opt.add(bot_count == sum(bots_in_range.keys())) dist = z3.Int("dist") opt.add(dist == zabs(x_coord) + zabs(y_coord) + zabs(z_coord)) opt.maximize(bot_count) nearest_point = opt.minimize(dist) opt.check() return opt.lower(nearest_point)
def part2(input_list): # Use z3 to find x,y,z that maximizes number_of_nearby_bots(x,y,z). # Based on https://github.com/msullivan's solution. nanobots = parse_input(input_list) z3_x_val = z3.Int('x') z3_y_val = z3.Int('y') z3_z_val = z3.Int('z') best_location = (z3_x_val, z3_y_val, z3_z_val) z3_number_of_bots = z3.Int('number_of_bots') z3_number_of_nearby_bots = z3_x_val * 0 for nanobot in nanobots: z3_number_of_nearby_bots += z3.If(z3_dist(best_location, nanobot[0]) <= nanobot[1], 1, 0) optimize = z3.Optimize() optimize.add(z3_number_of_bots == z3_number_of_nearby_bots) optimize.maximize(z3_number_of_bots) optimize.minimize(z3_dist((0,0,0), (z3_x_val, z3_y_val, z3_z_val))) optimize.check() model = optimize.model() position = (model[z3_x_val].as_long(), model[z3_y_val].as_long(), model[z3_z_val].as_long()) distance = abs(position[0]) + abs(position[1]) + abs(position[2]) return distance
def getMostOverlap(): maxCount = 0 for this in bots: common = [] count = 0 for other in bots: dist = this.dist(other) #if there exists a common point in both ranges if dist < other.range + this.range: common.append(other) count += 1 if count >= 907: # From print outs, I know theres a subsection thats at least 907 print(count) x = z3.Int('x') y = z3.Int('y') z = z3.Int('z') s = z3.Optimize() for c in common: s.add( z3.If(c.x >= x, c.x - x, x - c.x) + z3.If(c.y >= y, c.y - y, y - c.y) + z3.If(c.z >= z, c.z - z, z - c.z) <= c.range) minDist = s.minimize( z3.If(x >= 0, x, -x) + z3.If(y >= 0, y, -y) + z3.If(z >= 0, z, -z)) if (s.check()): print(s.lower(minDist), s.upper(minDist)) return count
def largest_clique(self, timeout=120): if z3 is None: raise ImportError() solver = z3.Optimize() solver.set("timeout", timeout) vars = {} #rev = {} start = time.clock() m = z3.Int(name="cliquesize") for v in self.nodes_iter(): vars[v] = z3.Int(name="node{0}".format(v)) #rev[vars[v]] = v solver.add(vars[v] <= 1) solver.add(vars[v] >= 0) solver.add(z3.Sum([vars[v] for v in self.nodes_iter()]) >= m) #solver.add(z3.Or([vars[v] == 1 for v in self.nodes_iter()])) adj = self.adj for u in self.nodes_iter(): for v in self.nodes_iter(): if u < v and u not in adj[v]: solver.add(z3.Or(vars[u] == 0, vars[v] == 0)) if timeout != 0 and time.clock() - start >= timeout: return None r = None try: r = solver.maximize(m) solver.check() except z3.Z3Exception, e: logging.error(e.message)
def main(nanobots): solver = z3.Optimize() bx = z3.Int("x") by = z3.Int("y") bz = z3.Int("z") d = z3.Int("d") bots = [] for i, bot in enumerate(nanobots): print("adding bot {} to z3".format(i)) b = z3.Int("b{:04}".format(i)) solver.add(b == z3.If(manhattan_distance((bx, by, bz), (bot.x, bot.y, bot.z)) <= bot.radius, 1, 0)) bots.append(b) print("adding constraints") solver.add(d == manhattan_distance((bx, by, bz), (0, 0, 0))) solver.maximize(z3.Sum(*bots)) solver.minimize(d) print("solving...") print(solver.check()) model = solver.model() print("answer:") print(model[d])
def find_max(self, loc, term): ss = self.symstates.ss[loc] ss = z3.And([ss[depth].myexpr for depth in ss]) term = helpers.miscs.Z3.parse(str(term.poly), use_reals=False) opt = z3.Optimize() opt.add(ss) opt.maximize(term) stat = opt.check() v = None if stat == z3.sat: model = opt.model() #term = -(x+y) # create a dict from model, e.g., d = {x: 5, y = 10} # v will then be term.subs(d) for s in model: if str(s) == str(term): v = model[s] break if v is not None: v = int(str(v)) print(term, v) else: print('???', term, model) assert False else: raise NotImplementedError("deal with this: {}".format(stat)) return v
def part2(nanobots): o = z3.Optimize() x, y, z = z3.Int('x'), z3.Int('y'), z3.Int('z') def zabs(v): return z3.If(v > 0, v, -v) def in_distance(n): d = zabs(x - n.x) + zabs(y - n.y) + zabs(z - n.z) return z3.If(d <= n.r, 1, 0) all_in_distance = z3.Int('all_in_distance') distance_to_origin = z3.Int('distance_to_origin') o.add(all_in_distance == z3.Sum(*[in_distance(n) for n in nanobots])) o.add(distance_to_origin == zabs(x) + zabs(y) + zabs(z)) a = o.maximize(all_in_distance) b = o.minimize(distance_to_origin) assert o.check() # print('x:', o.model()[x], 'y:', o.model()[y], 'z:', o.model()[z]) return b.lower().as_long()
def __init__(self, r2api: R2API, **kwargs): self.kwargs = kwargs self.r2api = r2api self.pure_symbolic = kwargs.get("sym", False) self.pcode = kwargs.get("pcode", False) self.check_perms = kwargs.get("check", False) if kwargs.get("optimize", False): self.solver = z3.Optimize() elif kwargs.get("simple", True): self.solver = z3.SimpleSolver() else: self.solver = z3.Solver() #self.solver.set("cache_all", True) timeout = kwargs.get("timeout", None) if timeout != None: self.solver.set("timeout", timeout) #self.solver.set("threads", 4) # without this push z3 does not use an "incremental" solver # which causes it to try tactics which are wildly slow self.solver.push() #self.constraints = [] self.model = None self.current_instruction = None self.esil = {"cur": 0, "old": 0, "stack": [], "size": 64, "type": 1} self.stack = self.esil["stack"] self.info = self.r2api.get_info() self.debug = kwargs.get("debug", False) self.trace = kwargs.get("trace", False) self.memory: ESILMemory = None self.registers: ESILRegisters = None self.proc: ESILProcess = None self.aliases = {} self.condition = None # steps executed and distance from goal self.steps = 0 self.distance = 0xffffffff self.target = None if "info" in self.info: self.bits = self.info["info"]["bits"] self.endian = self.info["info"]["endian"] else: self.bits = 64 self.endian = "little" if kwargs.get("init", True): self.proc = ESILProcess(r2api, **kwargs) self.init_state()
def __init__(self, state): self.state = state self.assertions = [] self._solver = z3.Optimize() if USE_OPT_SOLVER else z3.Solver() self._min_cache = OrderedDict() self._max_cache = OrderedDict() self._eval_cache = OrderedDict() self._symb_check_cache = OrderedDict()
def run_test(adj, fab_dims, wire_lengths={}, debug_prints=True, constraints_gen=place_constraints, model_checker=None, model_printer=print_model): comps = build_graph(adj) if wire_lengths: #use provided wire lengths print('Finding satisfying model with given wire lenths') constraints = constraints_gen(comps, fab_dims, wire_lengths) s = z3.Solver() s.add(constraints) if s.check() != z3.sat: if debug_prints: print('test is unsat') return s if debug_prints: print('test is sat') if debug_prints and all( model_checker(s.model(), comps, fab_dims, wire_lengths)): model_printer(s.model(), comps, fab_dims, wire_lengths) return (True, s) elif debug_prints: return (False, s) elif all( model_checker(s.model(), comps, fab_dims, wire_lengths, printer=lambda *x: None)): return (True, s) else: return (False, s) else: #no provided wire lengths, optimize the manhattan distance print('No provided wire lengths. Minimizing total L1 norm') constraints, manhattan_dist = place_constraints_opt(comps, fab_dims) s = z3.Optimize() s.add(constraints) h = s.minimize(manhattan_dist) if s.check() != z3.sat: if debug_prints: print('test is unsat') return s if debug_prints: print('test is sat') print('Total L1 Norm = ', s.lower(h)) #print(s.model()) print_model_opt(s.model(), comps, fab_dims) return s
def _min_z3_optimize(self, val: BV): opt = z3.Optimize() for c in self.assertions: opt.add(c.z3obj) h = opt.minimize(val.z3obj) assert opt.check().r == 1 res = opt.lower(h).as_long() return res
def get_condition_change_enablers(self, influence_update, all_dts, cache): """ Calculates if an if/else condition within the function can change its value """ logger.debug( f"Calculating condition change time in '{influence_update._name}' in entity '{influence_update._parent._name}' ({influence_update._parent.__class__.__name__})" ) solver = z3.Optimize(cache.ctx) # build a mapping that shows the propagation of information to the influence/update source (what influences the guard) if isinstance(influence_update, model.Influence): modifier_map = self.get_modifier_map( [influence_update.source, influence_update.target], cache=False) else: read_ports = SH.get_accessed_ports(influence_update.function, influence_update, cache=False) read_ports.append(influence_update.target) modifier_map = self.get_modifier_map(read_ports, cache=False) z3_vars = cache.z3_vars # add the initial values for the sources of the dataflow for port, modifiers in modifier_map.items(): # set default port value to the current value pre_value = port.value #get_z3_value(port, port._name + "_0").translate(cache.ctx) solver.add(z3_vars[port][port._name + "_0"] == pre_value) if len(modifiers) == 0: solver.add( z3_vars[port][port._name] == z3_vars[port][port._name + "_0"]) # create the constraints for updates and influences for port, modifiers in modifier_map.items(): for modifier in modifiers: if modifier != influence_update: # skip the one we're actually analysing, this should be already done in the modifier-map creation... constraints = cache.z3_modifier_constraints[modifier] solver.add( constraints ) #[const.translate(ctx) for const in constraints]) conditionchanged_constraintset, additionals = cache.z3_conditionchanged_constraintsets[ influence_update] solver.add(additionals) #[a.translate(ctx) for a in additionals]) min_dt, label = get_behaviour_change_dt_from_constraintset( solver, conditionchanged_constraintset, z3_vars['dt'], ctx=cache.ctx) if min_dt is not None: logger.info( f"Minimum condition change times in '{influence_update._name}' in entity '{influence_update._parent._name}' ({influence_update._parent.__class__.__name__}) is {min_dt} (at label {label})" ) ret = (to_python(min_dt), influence_update, label) all_dts.append(ret)
def __init__(self, env, optimize=False): if optimize: self._solver = z3.Optimize() else: self._solver = z3.Solver() self._do_optimize = False self._z3vars = {} self._smtvars = {} self._smtenv = env self._sat = None self._model = None
def __init__(self, state): self.state = state self.assertions = [] self._added_mem_constraints = set() self._solver = z3.Optimize() if USE_OPT_SOLVER else z3.Solver() self._min_cache = OrderedDict() self._max_cache = OrderedDict() self._eval_cache = OrderedDict() self._symb_check_cache = OrderedDict() if DBG: self.dbg_idx = 0
def multi_distinguish(self, regexes): start = time.time() # Problem: cannot distinguish more than 4 regexes at once: it takes forever. # Solution: use only 4 randomly selected regexes for the SMT maximization, # and then add the others to the solution. if len(regexes) <= 4: selected_regexes = regexes others = [] else: random.seed('regex') random.shuffle(regexes) selected_regexes = regexes[:4] others = regexes[4:] solver = z3.Optimize() z3_regexes = [] for regex in selected_regexes: z3_regex = self._toz3.eval(regex) z3_regexes.append(z3_regex) dist = z3.String("distinguishing") # solver.add(z3.Length(dist) <= 6) ro_z3 = [] for i, z3_regex in enumerate(z3_regexes): ro = z3.Bool(f"ro_{i}") ro_z3.append(ro) solver.add(ro == z3.InRe(dist, z3_regex)) # ro_z3[i] == true if dist matches regex[i]. big_or = [] for ro_i, ro_j in combinations(ro_z3, 2): big_or.append(z3.Xor(ro_i, ro_j)) solver.add_soft(z3.Xor(ro_i, ro_j)) solver.add(z3.Or(big_or)) # at least one regex is distinguished if solver.check() == z3.sat: # print(solver.model()) print("took", round(time.time() - start, 2), "seconds") keep_if_valid = [] keep_if_invalid = [] dist_input = str(solver.model()[dist]).strip('"') for i, ro in enumerate(ro_z3): if solver.model()[ro]: keep_if_valid.append(selected_regexes[i]) else: keep_if_invalid.append(selected_regexes[i]) smallest_regex = min(selected_regexes, key=lambda r: len(self._printer.eval(r))) return dist_input, keep_if_valid, keep_if_invalid, others else: return None, None, None, None
def hard(): o = z3.Optimize() x, y, z = z3.Ints("x y z") for p, d in t: o.add_soft( z3.If(x > p[0], x - p[0], p[0] - x) + z3.If(y > p[1], y - p[1], p[1] - y) + z3.If(z > p[2], z - p[2], p[2] - z) <= d) o.check() m = o.model() print(m.eval(x + y + z))
def generate_optimizer(self): self.log.info("Generating optimizer") solver = z3.Optimize() for name, condition in self.terminal_conditions.items(): solver.assert_and_track(condition, name) for strategy, expression in self.optimizations: if strategy == Optimizations.MAXIMIZE: solver.maximize(expression) elif strategy == Optimizations.MINIMIZE: solver.minimize(expression) self._solver = solver return solver
def largest_clique(self, timeout=120): if z3 is None: raise ImportError() solver = z3.Optimize() solver.set("timeout", timeout) vars = {} # rev = {} start = time.clock() m = z3.Int(name="cliquesize") for v in self.nodes_iter(): vars[v] = z3.Int(name="node{0}".format(v)) # rev[vars[v]] = v solver.add(vars[v] <= 1) solver.add(vars[v] >= 0) solver.add(z3.Sum([vars[v] for v in self.nodes_iter()]) >= m) # solver.add(z3.Or([vars[v] == 1 for v in self.nodes_iter()])) adj = self.adj for u in self.nodes_iter(): for v in self.nodes_iter(): if u < v and u not in adj[v]: solver.add(z3.Or(vars[u] == 0, vars[v] == 0)) if timeout != 0 and time.clock() - start >= timeout: return None r = None try: r = solver.maximize(m) solver.check() except z3.Z3Exception as e: logging.error(e.message) if r is None: return None res = solver.lower(r) # assert(str(res) != 'epsilon' and str(res) != 'unsat' and isinstance(res, z3.IntNumRef) and res.as_long() >= 1) if str(res) == 'epsilon' or str(res) == 'unsat': logging.error(res) elif not isinstance(res, z3.IntNumRef): logging.error("not an int") elif res.as_long() < 1: logging.error("clique result < 1") else: cl = [ k for (k, v) in vars.items() if solver.model()[v].as_long() == 1 ] if len(cl) != res.as_long(): logging.error("{0} vs. {1}".format(len(cl), res.as_long())) # assert(len(cl) == res.as_long()) return None # print cl return cl return None
def __init__(self, z3_mask): """Initializer. Args: z3_mask: list, contains mask bits as z3 vars. """ self.z3_mask = z3_mask self.mask_sum = 0 self.solver = z3.Optimize() for mask in self.z3_mask: self.solver.add(z3.Or(mask == 1, mask == 0)) self.mask_sum += mask self.minimal_mask_sum = self.solver.minimize(self.mask_sum)
def best_point(nanos): x, y, z, cost = z3.Ints("x y z cost") cost = cost * 0 for c, r in nanos: cost += z3.If(z3dist((x, y, z), c) <= r, 1, 0) o = z3.Optimize() o.maximize(cost) o.minimize(z3dist((0, 0, 0), (x, y, z))) o.check() model = o.model() return distance( (0, 0, 0), (model[x].as_long(), model[y].as_long(), model[z].as_long()))
def solve(inp, maximize=True): s = z3.Optimize() value = add_constraints(s, inp) if maximize: s.maximize(value) else: s.minimize(value) assert s.check() == z3.sat m = s.model() return m.eval(value)