def maximize_distance(bots): o = Optimize() z3_abs = lambda k: If(k >= 0, k, -k) z3_in_ranges = [Int('in_range_of_bot_' + str(i)) for i in xrange(len(bots))] z3_x, z3_y, z3_z = (Int('x'), Int('y'), Int('z')) z3_sum = Int('sum') z3_dist = Int('dist') for i, (x, y, z, r) in enumerate(bots): o.add(z3_in_ranges[i] == If(distance((z3_x, z3_y, z3_z), (x, y, z), z3_abs) <= r, 1, 0)) o.add(z3_sum == sum(z3_in_ranges)) o.add(z3_dist == distance((z3_x, z3_y, z3_z), (0, 0, 0), z3_abs)) h1, h2 = o.maximize(z3_sum), o.minimize(z3_dist) o.check() # o.lower(h1), o.upper(h1) lower, upper = o.lower(h2), o.upper(h2) # o.model()[z3_x], o.model()[z3_y], o.model()[z3_z] if str(lower) != str(upper): raise Exception('lower ({}) != upper ({})'.format(lower, upper)) return (lower, upper)
for (r, c) in board() ]).reshape(H, W) no_scout_threatens_another_scout = [ Implies( is_scout[r][c], And([ Not(is_scout[dr][dc]) for (dr, dc) in scout_moves_from[r, c] ]) ) for (r, c) in board() if (r, c) not in lakes() ] # Clauses s = Optimize() s.add(no_scouts_in_lakes) s.add(at_most_one_scout_per_segment) s.add(no_scout_threatens_another_scout) # Objective num_scouts = Sum([ If(is_scout[r][c], 1, 0) for (r, c) in board() ]) max_scouts = s.maximize(num_scouts) if s.check() == sat: #assert s.upper(max_scouts) == 14 print("The maximum number of scouts satisfying the constraints == %s." % s.upper(max_scouts)) print(diagram(s.model())) else: print("Z3 failed to find a solution.")