def create_z3_vars(self): """ Setup the variables required for Z3 optimization """ for gate in self.dag.gate_nodes(): t_var_name = "t_" + str(self.gate_id[gate]) d_var_name = "d_" + str(self.gate_id[gate]) f_var_name = "f_" + str(self.gate_id[gate]) self.gate_start_time[gate] = Real(t_var_name) self.gate_duration[gate] = Real(d_var_name) self.gate_fidelity[gate] = Real(f_var_name) for gate in self.xtalk_overlap_set: self.overlap_indicator[gate] = {} self.overlap_amounts[gate] = {} for g_1 in self.xtalk_overlap_set: for g_2 in self.xtalk_overlap_set[g_1]: if len(g_2.qargs) == 2 and g_1 in self.overlap_indicator[g_2]: self.overlap_indicator[g_1][g_2] = self.overlap_indicator[g_2][g_1] self.overlap_amounts[g_1][g_2] = self.overlap_amounts[g_2][g_1] else: # Indicator variable for overlap of g_1 and g_2 var_name1 = "olp_ind_" + str(self.gate_id[g_1]) + "_" + str(self.gate_id[g_2]) self.overlap_indicator[g_1][g_2] = Bool(var_name1) var_name2 = "olp_amnt_" + str(self.gate_id[g_1]) + "_" + str(self.gate_id[g_2]) self.overlap_amounts[g_1][g_2] = Real(var_name2) active_qubits_list = [] for gate in self.dag.gate_nodes(): for q in gate.qargs: active_qubits_list.append(self.qubit_indices[q]) for active_qubit in list(set(active_qubits_list)): q_var_name = "l_" + str(active_qubit) self.qubit_lifetime[active_qubit] = Real(q_var_name) meas_q = [] for node in self.dag.op_nodes(): if isinstance(node.op, Measure): meas_q.append(self.qubit_indices[node.qargs[0]]) self.measured_qubits = list(set(self.input_measured_qubits).union(set(meas_q))) self.measure_start = Real("meas_start")
def ReadQuery(synthesisQuery, K): global funcDefsMap global synthFunsMap global declaredVar2PortMap global circuitsCache funcDefsMap = {} synthFunsMap = {} declaredVar2PortMap = {} circuitsCache = [] spec = Bool(True) specInputPorts = [] specConnList = [] circuits = [] specificationConstraints = [] for command in synthesisQuery: commandName = command[0] if commandName == 'define-fun': funcDefsMap[command[1]] = command elif commandName == 'synth-fun': synthFunsMap[command[1]] = command elif commandName == 'declare-var': varName = command[1] varType = command[2] declaredVar2PortMap[ command[1]] = Port( '__DECVAR_%s' % (varName), '__SPEC_%s' % (varName), GetSortFromType(varType)) elif commandName == 'constraint': specificationConstraints.append(command[1]) elif commandName == 'check-synth': specInputPorts = [ port for (_, port) in declaredVar2PortMap.iteritems()] (spec, specConnList, circuits) = GenerateAll( JoinConstraints(specificationConstraints), K, {}) else: pass return (spec, specInputPorts, And(specConnList), circuits)
def GenerateCircuitSimilarityConstraints(circuits): constraints = [Bool(True)] numCircuits = len(circuits) for i in range(numCircuits): for j in range(i + 1, numCircuits): circuitX = circuits[i] circuitY = circuits[j] if circuitX.funcName == circuitY.funcName: numComponentsX = len(circuitX.components) numComponentsY = len(circuitY.components) if numComponentsX != numComponentsY: raise SynthException('circuits for same function must' + 'have same number of components') for comp_no in range(numComponentsX): compX = circuitX.components[comp_no] compY = circuitY.components[comp_no] numInputPortsX = len(compX.inputPorts) numInputPortsY = len(compY.inputPorts) if numInputPortsY != numInputPortsX: raise SynthException('similar components must have' + 'same number of input ports') for port_no in range(numInputPortsX): constraints.append( Int(circuitX.PN2LNMap[ compX.inputPorts[port_no].name]) == Int( circuitY.PN2LNMap[ compY.inputPorts[port_no].name])) constraints.append( Int(circuitX.PN2LNMap[compX.outputPort.name]) == Int( circuitY.PN2LNMap[compY.outputPort.name])) return And(constraints)
def solve(puzzle): nrows = puzzle['nrows'] ncols = puzzle['ncols'] ncolours = puzzle['ncolours'] colours = [[[Bool(f'({row}, {col}, {colour})') for col in range(ncols)] for row in range(nrows)] for colour in range(ncolours)] row_hints = puzzle['rows'] column_hints = puzzle['columns'] constraints = [] for i, hints in enumerate(row_hints): for colour, hint in enumerate(hints): cells = colours[colour][i] constraints.append(constraint(cells, hint)) for i, hints in enumerate(column_hints): for colour, hint in enumerate(hints): cells = column(colours[colour], i) constraints.append(constraint(cells, hint)) s = Solver() s.add(constraints) s.add(exclusive(*colours)) if s.check() == sat: m = s.model() solution = [[0 for j in range(ncols)] for i in range(nrows)] for colour, matrix in enumerate(colours): r = [[m.evaluate(matrix[i][j]) for j in range(ncols)] for i in range(nrows)] for i in range(nrows): for j in range(ncols): if r[i][j]: solution[i][j] = colour + 1 return solution
def __init__(self, lines): self.grid = {} for y, line in enumerate(lines): for x, char in enumerate(line): self.grid[x, y] = char self.height = len(lines) self.width = len(lines[0]) self.solver = Solver() self.model = None # Set up variables self.vars = {} # Head location self["hx"] = Int("hx") self["hy"] = Int("hy") # Tail location self["tx"] = Int("tx") self["ty"] = Int("ty") # Cells with a head or tail marker for y in range(self.height): for x in range(self.width): if self.grid[x, y] == "H": v = "head_{}_{}".format(x, y) self[v] = Int(v) if self.grid[x, y] == "T": v = "tail_{}_{}".format(x, y) self[v] = Int(v) # Cells with a potential snake for y in range(self.height): for x in range(self.width): if self.grid[x, y] == ".": v = "snake_{}_{}".format(x, y) self[v] = Bool(v)
def GenerateLabelRangeConstraints(self): constraints = [Bool(True)] numInputPorts = len(self.inputPorts) numComponents = len(self.components) inputLabelLo = 0 inputLabelHi = numInputPorts + numComponents outputLabelLo = numInputPorts outputLabelHi = numInputPorts + numComponents for comp in self.components: for inputPort in comp.inputPorts: constraints.append( Int(self.PN2LNMap[inputPort.name]) >= inputLabelLo) constraints.append( Int(self.PN2LNMap[inputPort.name]) < inputLabelHi) constraints.append( Int(self.PN2LNMap[comp.outputPort.name]) >= outputLabelLo) constraints.append( Int(self.PN2LNMap[comp.outputPort.name]) < outputLabelHi) return And(constraints)
def sym_xs128p(slvr, sym_state0, sym_state1, generated, browser): s1 = sym_state0 s0 = sym_state1 s1 ^= (s1 << 23) s1 ^= LShR(s1, 17) s1 ^= s0 s1 ^= LShR(s0, 26) sym_state0 = sym_state1 sym_state1 = s1 if browser == "chrome": calc = sym_state0 else: calc = (sym_state0 + sym_state1) condition = Bool("c%d" % int(generated * random.random())) if browser == "chrome": impl = Implies(condition, LShR(calc, 12) == int(generated)) elif browser == "firefox" or browser == "safari": # Firefox and Safari save an extra bit impl = Implies(condition, (calc & 0x1FFFFFFFFFFFFF) == int(generated)) else: raise ValueError(f"invalid browser {browser}") slvr.add(impl) return sym_state0, sym_state1, [condition]
def setup_vars(self): for x, y in self.coords(): self["digit_{}_{}".format(x, y)] = Int("digit_{}_{}".format(x, y)) self["snake_{}_{}".format(x, y)] = Bool("snake_{}_{}".format(x, y))
def main(args): # print(args) seed = int(args[0]) random.seed(seed) GRID_SZ = int(args[1]) HOPS = int(args[2]) print("WORKSPACE SIZE (%s x %s)" % (GRID_SZ, GRID_SZ)) print("HOPS ALLOWED = %s" % (HOPS)) # New primitive primitives = [] # Stay there primitives.append(Primitive(1, [[0,0]], 0, 0)) # Move right primitives.append(Primitive(2, [[0,0], [1,0]], 1, 0)) # Move left primitives.append(Primitive(3, [[0,0], [-1,0]], -1, 0)) # Move up primitives.append(Primitive(4, [[0,0], [0,1]], 0, 1)) # Move down primitives.append(Primitive(5, [[0,0], [0,-1]], 0, -1)) P = [ Int("p_%s" % (k)) for k in range(HOPS+1) ] # X is a three dimensional grid containing (t, x, y) X = [ [ [ Bool("x_%s_%s_%s" % (k, i, j)) for j in range(GRID_SZ) ] for i in range(GRID_SZ) ] for k in range(HOPS+1)] s = Solver() # P should be between 1 and 5 for each time step # s.add([And(1 <= prim , prim <= 5) for prim in P]) for prim in P: s.add(1 <= prim) s.add(prim <= 5) # for d in m.decls(): # print "%s = %s" % (d.name(), m[d]) # Make the swath true for the chosen primitive # for t in range(HOPS): # for i in range(GRID_SZ): # for j in range(GRID_SZ): # for prim_var in P: # for prim_instance in primitives: # for sw in prim_instance.swath: # if ((0 <= i+sw[0] < GRID_SZ) and (0 <= j+sw[1] < GRID_SZ)): # s.add(Implies(prim_var == prim_instance.id, X[t+1][i + sw[0]][j + sw[1]])) # else: # s.add(prim_var != prim_instance.id) # Since a swath cell lies outside the grid point # After the timestep the position of the robot should be curr + (final_x, final_y) for t in range(HOPS): for x in range(GRID_SZ): for y in range(GRID_SZ): for prim_instance in primitives: if ((0 <= x + prim_instance.final_x < GRID_SZ) and (0 <= y + prim_instance.final_y < GRID_SZ)): s.add(Implies(And(P[t] == prim_instance.id, X[t][x][y]), X[t+1][x + prim_instance.final_x][y + prim_instance.final_y])) else: s.add(Implies(X[t][x][y], P[t] != prim_instance.id)) # Initial Constraints s.add(X[0][0][0]) s.add([Not(cell) for row in X[0] for cell in row][1:]) # Final constraints s.add(X[HOPS][GRID_SZ-1][GRID_SZ-1]) s.add([Not(cell) for row in X[HOPS] for cell in row][:-1]) #Sanity Constraints for grid in X: for i in range(len(grid)): for j in range(len(grid)): for p in range(len(grid)): for q in range(len(grid)): if not (i==p and j==q): s.add(Not(And(grid[i][j], grid[p][q]))) ## SIMULATION STARTS HERE ## if s.check() == sat: m = s.model() else: print("No.of hops too low...") exit(1) obs = [Obstacle(0, 3, GRID_SZ), Obstacle(2, 2, GRID_SZ), Obstacle(7, 8. GRID_SZ)] robot_plan = [] hop = 0 while (hop < HOPS): robot_pos = get_robot_pos(m,hop) flag = False for obstacle in obs: obs_pos = (obstacle.x, obstacle.y) # print(obs_pos) obstacle.next_move() if sense_object(robot_pos, obs_pos): flag = True obstacle.add_constraints(s, X, hop, HOPS, GRID_SZ) if flag: if s.check() == sat: m = s.model() else: print("You have run into a ditch.") print("GAME OVER!") exit(1) hop += 1 robot_plan = get_plan(m) print("Robot plan:") print(robot_plan) print("Obstacle path") for obstacle in obs: obs_path = obstacle.path print(obs_path)
def solve(self, output_mode=None, output_file_name=None): objective_name = self.objective_name device = self.device list_gate_qubits = self.list_gate_qubits count_program_qubit = self.count_program_qubit list_gate_name = self.list_gate_name count_physical_qubit = self.count_physical_qubit list_qubit_edge = self.list_qubit_edge swap_duration = self.swap_duration bound_depth = self.bound_depth """ pre-processing """ count_qubit_edge = len(list_qubit_edge) count_gate = len(list_gate_qubits) if self.objective_name == "fidelity": list_logfidelity_single = [ int(1000 * math.log(device.list_fidelity_single[n])) for n in range(count_physical_qubit) ] list_logfidelity_two = [ int(1000 * math.log(device.list_fidelity_two[k])) for k in range(count_qubit_edge) ] list_logfidelity_measure = [ int(1000 * math.log(device.list_fidelity_measure[n])) for n in range(count_physical_qubit) ] list_gate_two = list() list_gate_single = list() for l in range(count_gate): if isinstance(list_gate_qubits[l], int): list_gate_single.append(l) else: list_gate_two.append(l) # list_adjacency_qubit takes in a physical qubit index _p_, and returns the list of indices of # physical qubits adjacent to _p_ list_adjacent_qubit = list() # list_span_edge takes in a physical qubit index _p_, and returns the list of edges spanned from _p_ list_span_edge = list() for n in range(count_physical_qubit): list_adjacent_qubit.append(list()) list_span_edge.append(list()) for k in range(count_qubit_edge): list_adjacent_qubit[list_qubit_edge[k][0]].append( list_qubit_edge[k][1]) list_adjacent_qubit[list_qubit_edge[k][1]].append( list_qubit_edge[k][0]) list_span_edge[list_qubit_edge[k][0]].append(k) list_span_edge[list_qubit_edge[k][1]].append(k) # if_overlap_edge takes in two edge indices _e_ and _e'_, and returns whether or not they overlap if_overlap_edge = [[0] * count_qubit_edge for k in range(count_qubit_edge)] # list_over_lap_edge takes in an edge index _e_, and returns the list of edges that overlap with _e_ list_overlap_edge = list() # list_count_overlap_edge is the list of lengths of overlap edge lists of all the _e_ list_count_overlap_edge = list() for k in range(count_qubit_edge): list_overlap_edge.append(list()) for k in range(count_qubit_edge): for kk in range(k + 1, count_qubit_edge): if (list_qubit_edge[k][0] == list_qubit_edge[kk][0] or list_qubit_edge[k][0] == list_qubit_edge[kk][1]) \ or (list_qubit_edge[k][1] == list_qubit_edge[kk][0] or list_qubit_edge[k][1] == list_qubit_edge[kk][1]): list_overlap_edge[k].append(kk) list_overlap_edge[kk].append(k) if_overlap_edge[kk][k] = 1 if_overlap_edge[k][kk] = 1 for k in range(count_qubit_edge): list_count_overlap_edge.append(len(list_overlap_edge[k])) # list_gate_dependency is the list of dependency, pairs of gate indices (_l_, _l'_), where _l_<_l'_ # _l_ and _ll_ act on a same program qubit list_gate_dependency = collision_extracting(list_gate_qubits) # index function: it takes two physical qubit indices _p_ and _p'_, # and returns the index of the edge between _p_ and _p'_, if there is one map_edge_index = [[0] * count_physical_qubit] * count_physical_qubit for k in range(count_qubit_edge): map_edge_index[list_qubit_edge[k][0]][list_qubit_edge[k][1]] = k map_edge_index[list_qubit_edge[k][1]][list_qubit_edge[k][0]] = k not_solved = True while not_solved: print("Trying maximal depth = {}...".format(bound_depth)) """ variables """ # at cycle t, logical qubit q is mapped to pi[q][t] pi = [[ Int("map_q{}_t{}".format(i, j)) for j in range(bound_depth) ] for i in range(count_program_qubit)] # time coordinate for gate l is time[l] time = IntVector('time', count_gate) # space coordinate for gate l is space[l] space = IntVector('space', count_gate) # if at cycle t, there is a SWAP finishing on edge k, then sigma[k][t]=1 sigma = [[ Bool("ifswap_e{}_t{}".format(i, j)) for j in range(bound_depth) ] for i in range(count_qubit_edge)] # for depth optimization depth = Int('depth') # for swap optimization count_swap = Int('num_swap') # for fidelity optimization if objective_name == "fidelity": u = [ Int("num_1qbg_p{}".format(n)) for n in range(count_physical_qubit) ] v = [ Int("num_2qbg_e{}".format(k)) for k in range(count_qubit_edge) ] vv = [ Int("num_swap_e{}".format(k)) for k in range(count_qubit_edge) ] w = [ Int("num_meas_p{}".format(n)) for n in range(count_physical_qubit) ] fidelity = Int('log_fidelity') lsqc = Optimize() """ Constraints """ for t in range(bound_depth): for m in range(count_program_qubit): lsqc.add(pi[m][t] >= 0, pi[m][t] < count_physical_qubit) for mm in range(m): lsqc.add(pi[m][t] != pi[mm][t]) for l in range(count_gate): lsqc.add(time[l] >= 0, time[l] < bound_depth) if l in list_gate_single: lsqc.add(space[l] >= 0, space[l] < count_physical_qubit) for t in range(bound_depth): lsqc.add( Implies(time[l] == t, pi[list_gate_qubits[l]][t] == space[l])) elif l in list_gate_two: lsqc.add(space[l] >= 0, space[l] < count_qubit_edge) for k in range(count_qubit_edge): for t in range(bound_depth): lsqc.add( Implies( And(time[l] == t, space[l] == k), Or( And( list_qubit_edge[k][0] == pi[ list_gate_qubits[l][0]][t], list_qubit_edge[k][1] == pi[ list_gate_qubits[l][1]][t]), And( list_qubit_edge[k][1] == pi[ list_gate_qubits[l][0]][t], list_qubit_edge[k][0] == pi[ list_gate_qubits[l][1]][t])))) for d in list_gate_dependency: if self.if_transition_based == True: lsqc.add(time[d[0]] <= time[d[1]]) else: lsqc.add(time[d[0]] < time[d[1]]) for t in range(min(swap_duration - 1, bound_depth)): for k in range(count_qubit_edge): lsqc.add(sigma[k][t] == False) for t in range(swap_duration - 1, bound_depth): for k in range(count_qubit_edge): for tt in range(t - swap_duration + 1, t): lsqc.add( Implies(sigma[k][t] == True, sigma[k][tt] == False)) for tt in range(t - swap_duration + 1, t + 1): for kk in list_overlap_edge[k]: lsqc.add( Implies(sigma[k][t] == True, sigma[kk][tt] == False)) if self.if_transition_based == False: for t in range(swap_duration - 1, bound_depth): for k in range(count_qubit_edge): for tt in range(t - swap_duration + 1, t + 1): for l in range(count_gate): if l in list_gate_single: lsqc.add( Implies( And( time[l] == tt, Or( space[l] == list_qubit_edge[k][0], space[l] == list_qubit_edge[k][1])), sigma[k][t] == False)) elif l in list_gate_two: lsqc.add( Implies( And(time[l] == tt, space[l] == k), sigma[k][t] == False)) for kk in list_overlap_edge[k]: lsqc.add( Implies( And(time[l] == tt, space[l] == kk), sigma[k][t] == False)) for t in range(bound_depth - 1): for n in range(count_physical_qubit): for m in range(count_program_qubit): lsqc.add( Implies( And( sum([ If(sigma[k][t], 1, 0) for k in list_span_edge[n] ]) == 0, pi[m][t] == n), pi[m][t + 1] == n)) for t in range(bound_depth - 1): for k in range(count_qubit_edge): for m in range(count_program_qubit): lsqc.add( Implies( And(sigma[k][t] == True, pi[m][t] == list_qubit_edge[k][0]), pi[m][t + 1] == list_qubit_edge[k][1])) lsqc.add( Implies( And(sigma[k][t] == True, pi[m][t] == list_qubit_edge[k][1]), pi[m][t + 1] == list_qubit_edge[k][0])) lsqc.add(count_swap == sum([ If(sigma[k][t], 1, 0) for k in range(count_qubit_edge) for t in range(bound_depth) ])) # for depth optimization for l in range(count_gate): lsqc.add(depth >= time[l] + 1) if objective_name == "swap": lsqc.minimize(count_swap) elif objective_name == "depth": lsqc.minimize(depth) elif objective_name == "fidelity": for n in range(count_physical_qubit): lsqc.add(u[n] == sum( [If(space[l] == n, 1, 0) for l in list_gate_single])) lsqc.add(w[n] == sum([ If(pi[m][bound_depth - 1] == n, 1, 0) for m in range(count_program_qubit) ])) for k in range(count_qubit_edge): lsqc.add(v[k] == sum( [If(space[l] == k, 1, 0) for l in list_gate_two])) lsqc.add(vv[k] == sum( [If(sigma[k][t], 1, 0) for t in range(bound_depth)])) lsqc.add(fidelity == sum([ v[k] * list_logfidelity_two[k] for k in range(count_qubit_edge) ]) + sum([ swap_duration * vv[k] * list_logfidelity_two[k] for k in range(count_qubit_edge) ]) + sum([ w[n] * list_logfidelity_measure[n] for n in range(count_physical_qubit) ]) + sum([ u[n] * list_logfidelity_single[n] for n in range(count_physical_qubit) ])) lsqc.maximize(fidelity) else: raise Exception("Invalid Objective Name") satisfiable = lsqc.check() if satisfiable == sat: not_solved = False else: if self.if_transition_based == True: bound_depth += 1 else: bound_depth = int(1.3 * bound_depth) # print("Compilation time = {}s.".format(sys_time.time() - start_time)) model = lsqc.model() """ post-processing """ result_time = [] result_depth = model[depth].as_long() for l in range(count_gate): result_time.append(model[time[l]].as_long()) list_result_swap = [] for k in range(count_qubit_edge): for t in range(result_depth): if model[sigma[k][t]]: list_result_swap.append((k, t)) # transition based if self.if_transition_based: self.swap_duration = self.device.swap_duration map_to_block = dict() real_time = [0 for i in range(count_gate)] list_depth_on_qubit = [-1 for i in range(self.count_program_qubit)] list_real_swap = [] for block in range(result_depth): for tmp_gate in range(count_gate): if result_time[tmp_gate] == block: qubits = list_gate_qubits[tmp_gate] if isinstance(qubits, int): real_time[ tmp_gate] = list_depth_on_qubit[qubits] + 1 list_depth_on_qubit[qubits] = real_time[tmp_gate] map_to_block[real_time[tmp_gate]] = block else: real_time[tmp_gate] = list_depth_on_qubit[ qubits[0]] + 1 if real_time[tmp_gate] < list_depth_on_qubit[ qubits[1]] + 1: real_time[tmp_gate] = list_depth_on_qubit[ qubits[1]] + 1 list_depth_on_qubit[ qubits[0]] = real_time[tmp_gate] list_depth_on_qubit[ qubits[1]] = real_time[tmp_gate] map_to_block[real_time[tmp_gate]] = block if block < result_depth - 1: for (k, t) in list_result_swap: if t == block: q0 = list_qubit_edge[k][0] q1 = list_qubit_edge[k][1] tmp_time = list_depth_on_qubit[ q0] + self.swap_duration if tmp_time < list_depth_on_qubit[ q1] + self.swap_duration: tmp_time = list_depth_on_qubit[ q1] + self.swap_duration list_depth_on_qubit[q0] = tmp_time list_depth_on_qubit[q1] = tmp_time list_real_swap.append((k, tmp_time)) result_time = real_time real_depth = 0 for tmp_depth in list_depth_on_qubit: if real_depth < tmp_depth + 1: real_depth = tmp_depth + 1 result_depth = real_depth list_result_swap = list_real_swap if objective_name == "fidelity": log_fidelity = model[fidelity].as_long() print("result fidelity = {}".format(math.exp(log_fidelity / 1000.0))) elif objective_name == "swap": print("result additional SWAP count = {}.".format( len(list_result_swap))) else: print("result circuit depth = {}.".format(result_depth)) list_scheduled_gate_qubits = [[] for i in range(result_depth)] list_scheduled_gate_name = [[] for i in range(result_depth)] result_depth = 0 for l in range(count_gate): t = result_time[l] if result_depth < t + 1: result_depth = t + 1 list_scheduled_gate_name[t].append(list_gate_name[l]) if l in list_gate_single: q = model[space[l]].as_long() list_scheduled_gate_qubits[t].append(q) elif l in list_gate_two: [q0, q1] = list_gate_qubits[l] tmp_t = t if self.if_transition_based: tmp_t = map_to_block[t] q0 = model[pi[q0][tmp_t]].as_long() q1 = model[pi[q1][tmp_t]].as_long() list_scheduled_gate_qubits[t].append([q0, q1]) else: raise Exception("Expect single- or two-qubit gate.") final_mapping = [] for m in range(count_program_qubit): tmp_depth = result_depth - 1 if self.if_transition_based: tmp_depth = map_to_block[result_depth - 1] final_mapping.append(model[pi[m][tmp_depth]].as_long()) # print("logical qubit {} is mapped to node {} in the beginning, node {} at the end".format( # m, model[pi[m][0]], model[pi[m][result_depth - 1]])) for (k, t) in list_result_swap: q0 = list_qubit_edge[k][0] q1 = list_qubit_edge[k][1] if self.swap_duration == 1: list_scheduled_gate_qubits[t].append([q0, q1]) list_scheduled_gate_name[t].append("SWAP") elif self.swap_duration == 3: list_scheduled_gate_qubits[t].append([q0, q1]) list_scheduled_gate_name[t].append("cx") list_scheduled_gate_qubits[t - 1].append([q1, q0]) list_scheduled_gate_name[t - 1].append("cx") list_scheduled_gate_qubits[t - 2].append([q0, q1]) list_scheduled_gate_name[t - 2].append("cx") else: raise Exception( "Expect SWAP duration one, or three (decomposed into CX gates)" ) if output_mode == "IR": if output_file_name: output_file = open(output_file_name, 'w') output_file.writelines([ result_depth, list_scheduled_gate_name, list_scheduled_gate_qubits, final_mapping ]) return [ result_depth, list_scheduled_gate_name, list_scheduled_gate_qubits, final_mapping ] else: return output_qasm(self.device, result_depth, list_scheduled_gate_name, list_scheduled_gate_qubits, final_mapping, True, output_file_name)
def solveGrid(self): """ Solve Sudoku grid - Add constraints using Z3 API - Solve using Z3 API - Fill Sudoku grid """ # Declare literals literals = [\ [\ [Bool("{}:{}:{}".format(i, j, value)) for value in range(self.n)]\ for j in range(self.n)]\ for i in range(self.n)] # Add constraints on cases for i in range(self.n): for j in range(self.n): self.solver.add(Or(literals[i][j])) for value in range(self.n): # Add constraints on rows for i in range(self.n): for j in range(self.n): for j_ in range(self.n): if j != j_: self.solver.add( Or(Not(literals[i][j][value]), Not(literals[i][j_][value]))) # Add constraints on columns for j in range(self.n): for i in range(self.n): for i_ in range(self.n): if i != i_: self.solver.add( Or(Not(literals[i][j][value]), Not(literals[i_][j][value]))) # Add constraints on squares for square_i in range(self.s): for square_j in range(self.s): for i in range(self.s): for i_ in range(self.s): for j in range(self.s): for j_ in range(self.s): if i != i_ and j != j_: self.solver.add( Or( Not(literals[ square_i * self.s + i][square_j * self.s + j][value]), Not(literals[ square_i * self.s + i_][square_j * self.s + j_][value]))) # Add constraints on known values from the input grid for i in range(self.n): for j in range(self.n): if self.grid[i][j] != 0: self.solver.add(literals[i][j][self.grid[i][j] - 1]) # Check if grid is solvable, otherwise exit if (self.solver.check() == unsat): solved = False exit("Grid unsolvable!") else: solved = True # Get the model m = self.solver.model() # Fill the grid from the model for i in range(self.n): for j in range(self.n): if self.grid[i][j] == 0: for value, literal in enumerate(literals[i][j]): if m.evaluate(literal): self.grid[i][j] = value + 1 return solved
def solve(data): men_str = data['men_str'] women_str = data['women_str'] men_prefer = data['men'] women_prefer = data['women'] s = Solver() size = len(men_prefer) size_range = range(size) men_choice = [Int(f'men_choice_{i}') for i in size_range] women_choice = [Int(f'women_choice_{i}') for i in size_range] for i in size_range: s.add(And(men_choice[i] >= 0, men_choice[i] <= size - 1)) s.add(And(women_choice[i] >= 0, women_choice[i] <= size - 1)) s.add(Distinct(men_choice)) for i in size_range: s.add(women_choice[i] == _if_x(men_choice, i, 0)) men_own_choice = [Int(f'men_own_choice_{i}') for i in size_range] women_own_choice = [Int(f'women_own_choice_{i}') for i in size_range] for m in size_range: s.add(men_own_choice[m] == _if_xy(men_choice[m], men_prefer[m], 0)) for w in size_range: s.add( women_own_choice[w] == _if_xy(women_choice[w], women_prefer[w], 0)) men_want = [[Bool(f'men_want_{m}_{w}') for w in size_range] for m in size_range] women_want = [[Bool(f'women_want_{w}_{m}') for m in size_range] for w in size_range] for m in size_range: for w in men_prefer[m]: s.add( men_want[m][w] == (men_prefer[m].index(w) < men_own_choice[m])) for w in size_range: for m in women_prefer[w]: s.add(women_want[w][m] == ( women_prefer[w].index(m) < women_own_choice[w])) for m in size_range: for w in size_range: s.add(Not(And(men_want[m][w], women_want[w][m]))) if s.check() != sat: raise Exception('not a valid input') with open('z3_input.txt', 'w') as f: f.write(s.sexpr()) mdl = s.model() with open('z3_model.txt', 'w') as f: f.write(str(mdl)) return { women_str[mdl[men_choice[m]].as_long()]: men_str[m] for m in size_range }
from z3 import Solver, Bool, sat, unsat, print_matrix from solver import column, exclusive, constraint ################## # 15x10 4-colour # ################## nrows = 15 ncols = 10 ncolours = 4 colours = [[[Bool(f'({row}, {col}, {colour})') for col in range(ncols)] for row in range(nrows)] for colour in range(ncolours)] row_hints = [[9, 8, 8, 4, 5, 5, 5, 3, 2, 0, 0, 0, 0, 0, 0], [1, -2, 1, 6, 4, 5, 4, 4, 5, -2, -2, -2, 0, 3, 4], [0, 0, 0, 0, 0, 0, 0, -3, 1, 4, 3, 2, 2, 3, 2], [0, 0, 1, 0, 1, 0, 1, 0, -2, 4, 5, 6, 8, 4, 4]] column_hints = [[-9, -8, -3, -3, -9, -7, 1, 0, 6, -3], [0, 1, -6, 11, 5, 0, -6, 4, 4, 8], [-6, 1, 1, 0, 0, 1, 3, -8, 0, 0], [0, -5, -5, 1, 1, -7, 5, 3, -5, -4]] constraints = [] for colour, row in enumerate(row_hints): for i, hint in enumerate(row): cells = colours[colour][i] constraints.append(constraint(cells, hint))
def visit_MLIL_CONST(self, expr): if expr.size == 0 and expr.constant in (0, 1): return Bool('b') == Bool( 'b') if expr.constant else Bool('b') != Bool('b') return expr.constant
def duplicate_vars(cls, var_vector): new_var_vector = [Bool(cls.new_var_name(var)) for var in var_vector] cls.copies_counter += 1 return new_var_vector
def DeclareVar(sort, name): if sort == "Int": return Int(name) if sort == 'Bool': return Bool(name)
def get_tr_and_initial(self, kripke): aag_lines = self._get_aag_lines() self._prefetch_ap_mapping(aag_lines) self._init_latch_values = _latch_lines_to_init_values( aag_lines[1 + self._I:1 + self._I + self._L], _parse_aag_latch_line) in_lits, next_state_lits, out_lits, prev_state_lits = self._get_literal_lists( aag_lines) formulas = self._get_formulas_hash(aag_lines, in_lits, next_state_lits, out_lits, prev_state_lits) in_vars, next_in_vars, next_output_vars, next_state_vars, prev_output_vars, prev_state_vars = self._get_var_lists( ) ltr_z3_no_sub = simplify( And(*[ next_state_vars[_l] == formulas[next_state_lits[_l]] for _l in xrange(self._L) ])) # in_lits,prev_state_lits->nextstate_vars outputs_z3_no_sub = [ simplify(next_output_vars[_o] == formulas[out_lits[_o]]) for _o in xrange(self._O) ] # in_lits,prev_state_lits->nextoutput_vars current_in_vars = [Bool(str(_i)) for _i in in_lits] curr_prev_latch_vars = [Bool(str(_l)) for _l in prev_state_lits] outputs_z3_next = [ substitute( outputs_z3_no_sub[_o], zip(current_in_vars + curr_prev_latch_vars, next_in_vars + next_state_vars)) for _o in xrange(self._O) ] outputs_z3_prev = [ substitute( outputs_z3_no_sub[_o], zip( current_in_vars + curr_prev_latch_vars + [next_output_vars[_o]], in_vars + prev_state_vars + [prev_output_vars[_o]])) for _o in xrange(self._O) ] ltr_no_prev_output_z3 = substitute( ltr_z3_no_sub, zip(current_in_vars + curr_prev_latch_vars, in_vars + prev_state_vars)) ltr_z3 = And(ltr_no_prev_output_z3, *outputs_z3_prev) output_formulas = [ FormulaWrapper(QBF(outputs_z3_next[_o]), [next_state_vars, [next_output_vars[_o]]], [next_in_vars]) for _o in xrange(self._O) ] prev_var_vector = prev_state_vars + prev_output_vars next_var_vector = next_state_vars + next_output_vars var_vectors = [prev_var_vector, next_var_vector] inner_tr = And(ltr_z3, *outputs_z3_next) qbf_tr = QBF(inner_tr) tr = FormulaWrapper(qbf_tr, var_vectors, [in_vars, next_in_vars]) initial_states = get_initial_states(self._init_latch_values, output_formulas, kripke, tr) qbf_outputs = QBF(And(*outputs_z3_prev)) output_formula_wrapper = FormulaWrapper(qbf_outputs, [prev_var_vector], [in_vars]) return tr, initial_states, output_formula_wrapper
def main(args): # print(args) seed = int(args[0]) random.seed(seed) # X is a three dimensional grid containing (t, x, y) X = [[[Bool("x_%s_%s_%s" % (k, i, j)) for j in range(GRID_SZ)] for i in range(GRID_SZ)] for k in range(HOPS + 1)] s = Optimize() # Initial Constraints s.add(X[0][0][0]) s.add([Not(cell) for row in X[0] for cell in row][1:]) # Final constraints s.add(X[HOPS][GRID_SZ - 1][GRID_SZ - 1]) s.add([Not(cell) for row in X[HOPS] for cell in row][:-1]) #Sanity Constraints for grid in X: for i in range(len(grid)): for j in range(len(grid)): for p in range(len(grid)): for q in range(len(grid)): if not (i == p and j == q): s.add(Not(And(grid[i][j], grid[p][q]))) #Motion primitives for t in range(HOPS): for x in range(GRID_SZ): for y in range(GRID_SZ): temp = Or(X[t][x][y]) if (x + 1 < GRID_SZ): temp = Or(temp, X[t][x + 1][y]) if (y + 1 < GRID_SZ): temp = Or(temp, X[t][x][y + 1]) if (x - 1 >= 0): temp = Or(temp, X[t][x - 1][y]) if (y - 1 >= 0): temp = Or(temp, X[t][x][y - 1]) s.add(simplify(Implies(X[t + 1][x][y], temp))) # Cost constraints for t in range(HOPS): for x in range(GRID_SZ): for y in range(GRID_SZ): s.add_soft(Not(X[t][x][y]), distance(x, y, GRID_SZ - 1, GRID_SZ - 1)) hop = 0 if s.check() == sat: m = s.model() else: print("No.of hops too low...") exit(1) obs1 = Obstacle(0, 3, GRID_SZ) robot_plan = [] obs_plan = [] # for a in s.assertions(): # print(a) while (hop < HOPS): robot_pos = (0, 0) if hop == 0 else get_robot_pos(m, hop) obs_pos = obs1.next_move() s.add(X[hop][robot_pos[0]][robot_pos[1]]) # print("hop is ", hop) # print("robot at ", robot_pos) # print("obs at ", obs_pos) if robot_pos == obs_pos: print("COLLISION!!!") print(robot_plan) print(obs_plan) exit() robot_plan.append(robot_pos) obs_plan.append(obs_pos) #next position of the robot next_robot_pos = get_robot_pos(m, hop + 1) s.push() # print("intersection points") # print(intersection_points(robot_pos, obs_pos)) # count = 0 next_overlap = next_intersection_points(next_robot_pos, obs_pos) for (x, y) in next_overlap: # consider only the intersection with the next step in the plan s.add(Not(X[hop + 1][x][y])) if len(next_overlap) > 0: # we need to find a new path if (s.check() == unsat): print("stay there") else: m = s.model() # print("Plan for hop = " + str(hop+1)) # print(get_plan(m)) hop += 1 else: # we don't need to worry about the path hop += 1 s.pop() robot_pos = get_robot_pos(m, hop) obs_pos = obs1.next_move() # print("hop is ", hop) # print("robot at ", robot_pos) # print("obs at ", obs_pos) robot_plan.append(robot_pos) obs_plan.append(obs_pos) if path_valid(robot_plan, obs_plan): print("PATH IS VALID!!!") else: print("PATH IS INVALID!!!") print("ROBOT MOVEMENT:") print(robot_plan) print("OBSTACLE MOVEMENT:") print(obs_plan)
Expected output (with Python 3): >>> python ranking.py MaryBob = True JimLisa = True BioLisa = True BobJim = True Therefore, the ranking is: Mary, Bob, Jim, Lisa. ''' from __future__ import print_function from z3 import Bool, And, Or, Not, Implies, Sum, If, Solver lb = Bool('LisaBob') bl = Bool('BobLisa') lj = Bool('LisaJim') jl = Bool('JimLisa') lm = Bool('LisaMary') ml = Bool('MaryLisa') bj = Bool('BobJim') jb = Bool('JimBob') bm = Bool('BobMary') mb = Bool('MaryBob') jm = Bool('JimMary') mj = Bool('MaryJim') bio_l = Bool('BioLisa') bio_b = Bool('BioBob') bio_j = Bool('BioJim') bio_m = Bool('BioMary')
# Eventually we will have translated the whole graph structure to a SAT problem, can solve this and get what we need # to install cycles = nx.recursive_simple_cycles(G) for cycle in cycles: G.remove_nodes_from(cycle[1:]) for n in G.nodes(data=True): direct_descendants = G[n[0]].keys() nodes = G.nodes(data=True) node_descendant = [] var_groups = {} for descendant in direct_descendants: if 'conflict' in nodes[descendant].keys( ) and nodes[descendant]['conflict'] is True: v = Bool(descendant) node_descendant.append(Not(v)) var_mapping[descendant] = v elif 'required' in nodes[descendant].keys( ) and nodes[descendant]['required'] == 1: node_descendant.append(True) trues.append(descendant) else: # print("got here") if nodes[descendant]['opt_dep_group'] in var_groups.keys(): v = Bool(descendant) var_groups[nodes[descendant]['opt_dep_group']].append(v) var_mapping[descendant] = v else: var_groups[nodes[descendant]['opt_dep_group']] = [] v = Bool(descendant)
def diagram(model): board = np.array([piece(model, r, c) for (r, c) in rectangle(H, W)]).reshape(H, W) return "%s" % '\n'.join(map(lambda row: ' '.join(map(str, row)), board)) # http://forum.stratego.com/topic/1134-stratego-quizz-and-training-forum/?p=11667 # http://forum.stratego.com/topic/1134-stratego-quizz-and-training-forum/?p=441746 print( "The minimum number of bombs on a Stratego setup area such that each 2x3 and 3x2 rectangle has at least one bomb." ) # Variables is_bomb = np.array([ Bool("is_bomb_%s%s" % (r, c)) for (r, c) in rectangle(H, W) ]).reshape(H, W).tolist() # Bomb placement def at_least_one_bomb_for_each_rectangle(h, w): return [ PbGe([(is_bomb[r + dr][c + dc], 1) for (dr, dc) in rectangle(h, w)], 1) for (r, c) in rectangle(H - h + 1, W - w + 1) ] # Clauses s = Optimize() s.add(at_least_one_bomb_for_each_rectangle(2, 3)) s.add(at_least_one_bomb_for_each_rectangle(3, 2))
def reencode_quantifiers(expr, boundvariables, quantifiers): z3.set_option(max_args=10000000, max_lines=1000000, max_depth=10000000, max_visited=1000000) smt2string = toSMT2Benchmark(expr) # Have to scan the string, because other methods proved to be too slow. log('Detect declarations of the free variables in SMTLIB2 string') free_variables = re.findall( '\(declare-fun (\w+) \(\) (Bool)|\(declare-fun (\w+) \(\) \(\_ BitVec (\d+)\)', smt2string) free_variables += re.findall( '\(declare-const (\w+) (Bool)|\(declare-const (\w+) \(\_ BitVec (\d+)\)', smt2string) for fv in free_variables: if str(fv).startswith('?'): print( 'Error: Variable starts with "?". Potential for confusion with quantified variables. This case is not handled.' ) exit() log(' Found {} free variables'.format(len(free_variables))) # Turn free variables into z3 variabes and add them to the quantifier for idx, (a, b, x, y) in enumerate(free_variables): assert (a != '' or x != '') if a != '': assert (b == 'Bool') free_variables[idx] = Bool(a) else: free_variables[idx] = BitVec(x, int(y)) quantifiers = [['e', free_variables]] + quantifiers log('Replacing de Bruijn indices by variables') matches = re.findall('\?(\d+)', smt2string) deBruijnIDXs = map(int, set(matches)) assert (len(deBruijnIDXs) <= len(boundvariables)) # sort de Bruijn indeces in decreasing order so that replacing smaller numbers does not accidentally match larger numbers deBruijnIDXs = list(deBruijnIDXs) deBruijnIDXs.sort() deBruijnIDXs.reverse() for idx in deBruijnIDXs: smt2string = smt2string.replace('?{}'.format(idx), str(boundvariables[-(1 + int(idx))])) log('Generating SMTLIB without quantifiers') # introduce quantified variables to enable re-parsing declarations = [] for var in boundvariables: if is_bv(var): declarations.append('(declare-fun {} () (_ BitVec {}))'.format( str(var), var.size())) else: assert (is_bool(var)) declarations.append('(declare-fun {} () Bool)'.format(str(var))) smt2string = '\n'.join(declarations) + '\n' + smt2string log('Reparsing SMTLIB without quantifiers') flat_constraints = parse_smt2_string(smt2string) # log('Extract all variables') # allvariables = get_vars(flat_constraints) # # log('Search for free variables') # freevariables = [] # known_vars = set(map(str,boundvariables)) # for idx, var in enumerate(allvariables): # if idx+1 % 10000 == 0: # log(' {} variables checked if free'.format(idx)) # if str(var) not in known_vars: # freevariables.append(var.n) # var.n because var is only the AstRefKey object # # log('Found {} free variables'.format(len(freevariables))) # # quantifiers = [['e', freevariables]] + quantifiers # delete empty quantifiers i = 0 while i < len(quantifiers): if len(quantifiers[i][1]) == 0: del (quantifiers[i]) else: i += 1 for i in range(len(quantifiers) - 1): if quantifiers[i][0] == quantifiers[i + 1][0]: mergedQuantifiers[-1][1] += quantifiers[i + 1][1] else: mergedQuantifiers += [quantifiers[i + 1]] # merge successive quantifiers of the same type if len(quantifiers) > 0: mergedQuantifiers = [quantifiers[0]] for i in range(len(quantifiers) - 1): if quantifiers[i][0] == quantifiers[i + 1][0]: mergedQuantifiers[-1][1] += quantifiers[i + 1][1] else: mergedQuantifiers += [quantifiers[i + 1]] quantifiers = mergedQuantifiers # print quantifiers return quantifiers, And(flat_constraints)
def to_bool(reference: PackageReference, time_step: int) -> Bool: return Bool('%s_%i' % (reference, time_step))
r, c) in lakes() else '2' if m.evaluate(is_scout[r][c]) else '.' def diagram(model): b = np.array([piece(model, r, c) for (r, c) in board()]).reshape(H, W) return "%s" % '\n'.join(map(lambda row: ' '.join(map(str, row)), b)) # https://en.wikipedia.org/wiki/Dominating_set # http://forum.stratego.com/topic/1134-stratego-quizz-and-training-forum/?p=441845 print( "The minimum number of scouts on a Stratego board such that each square is occupied or threatened by a scout." ) # Variables is_scout = np.array([Bool("is_scout_%s%s" % (r, c)) for (r, c) in board()]).reshape(H, W).tolist() # Piece placement no_scouts_in_lakes = [Not(is_scout[r][c]) for (r, c) in lakes()] # Scout moves in the left (L), right (R), downward (D) and upward (U) directions def L_scout_moves_from(r, c): if r in chain(range(0, 4), range(6, H)): return range(0, c) elif c in range(0, 2): return range(0, c) elif c in range(4, 6): return range(4, c) elif c in range(8, W):
not_solve = True while(not_solve): print("Trying maximal layers = {}...".format(T)) # Variables # at cycle t, logical qubit q is mapped to pi[q][t] pi = [[Int("map_q{}_t{}".format(i, j)) for j in range(T)] for i in range(M)] # time coordinate for gate l is time[l] time = IntVector('time', L) # space coordinate for gate l is space[l] space = IntVector('space', L) # if at cycle t, there is a SWAP finishing on edge k, then sigma[k][t]=1 sigma = [[Bool("ifswap_e{}_t{}".format(i, j)) for j in range(T)] for i in range(K)] # for swap optimization # if objective_name == "swap": num_swap = Int('num_swap') # for fidelity optimization if objective_name == "fidelity": u = [Int("num_1qbg_p{}".format(n)) for n in range(N)] v = [Int("num_2qbg_e{}".format(k)) for k in range(K)] vv = [Int("num_swap_e{}".format(k)) for k in range(K)] w = [Int("num_meas_p{}".format(n)) for n in range(N)] fidelity = Int('log_fidelity')
def bool_var(self, expr): return Bool(expr.id)
def isBool(self, who): return Bool(who)
def SMT_general_model(instance): # -------------------------- # PARAMETERS # -------------------------- # Define dimensions parameters x = 0 y = 1 # Define wrapping paper roll height and width roll_width = instance['roll_width'] roll_height = instance['roll_height'] # Define wrapping paper roll coordinates X_COORDINATES = range(roll_width) Y_COORDINATES = range(roll_height) # Define the number of pieces to cut n_pieces = instance['n_pieces'] # Define pieces as a set of integers from 0 to num. of presents-1 PIECES = range(n_pieces) # Define the dimensions of the pieces to cut pieces_dimensions = instance['pieces_dimensions'] # Define lower and upper bounds for the dimensions lower_bounds = [0, 0] upper_bounds = [roll_width, roll_height] # -------------------------- # VARIABLES # -------------------------- # DECISION VARIABLES # Define bottom-left corner of the pieces of paper to cut as 2-D (width-height) array of int decision variables pieces_corners = [[Int("x_%s" % i), Int("y_%s" % i)] for i in PIECES] # Define rotation property for the pieces of paper pieces_rotation = [Bool("rotation_%s" % i) for i in PIECES] # -------------------------- # FUNCTIONS # -------------------------- # Function to obtain the width and height of a piece of paper based on their positioning (if rotated or not) def get_dimension(i, axis): if axis == x: return If(pieces_rotation[i], pieces_dimensions[i][y], pieces_dimensions[i][x]) else: return If(pieces_rotation[i], pieces_dimensions[i][x], pieces_dimensions[i][y]) # -------------------------- # CONSTRAINTS # -------------------------- # DOMAIN CONSTRAINTS: reduce the domain for the bottom-left corners of the pieces of paper # The cut can not be done outside the paper roll: the bottom-left corner coordinates of the pieces of paper to cut # must not exceed the paper roll coordinates limit, considering also the dimension of the piece of paper domain_bound_constraints = [ And( And(pieces_corners[i][x] >= lower_bounds[x], pieces_corners[i][x] <= upper_bounds[x] - get_dimension(i, x)), And(pieces_corners[i][y] >= lower_bounds[y], pieces_corners[i][y] <= upper_bounds[y] - get_dimension(i, y))) for i in PIECES ] # IMPLIED CUMULATIVE CONSTRAINTS: define the maximum number of usable paper # The maximum usable quantity of paper is defined by the paper roll dimensions cumulative_constraints = [ Sum([ If( And(y_coord >= pieces_corners[i][y], y_coord < pieces_corners[i][y] + get_dimension(i, y)), get_dimension(i, x), 0) for i in PIECES ]) == roll_width for y_coord in Y_COORDINATES ] + [ Sum([ If( And(x_coord >= pieces_corners[i][x], x_coord < pieces_corners[i][x] + get_dimension(i, x)), get_dimension(i, y), 0) for i in PIECES ]) == roll_height for x_coord in X_COORDINATES ] # NON-OVERLAPPING CONSTRAINT: define the non-overlapping property fo the pieces of paper # The cutted pieces of paper must not overlap: the bottom-left corner coordinates must not be equal to other # coordinates of the paper roll which are already occupied by other pieces of paper non_overlapping_constraints = [ Or(pieces_corners[i][x] + get_dimension(i, x) <= pieces_corners[j][x], pieces_corners[i][y] + get_dimension(i, y) <= pieces_corners[j][y], pieces_corners[j][x] + get_dimension(j, x) <= pieces_corners[i][x], pieces_corners[j][y] + get_dimension(j, y) <= pieces_corners[i][y]) for i in PIECES for j in PIECES if i < j ] # ORDERING CONSTRAINTS: define an ordering property for the pieces of paper which have the same dimension # The pieces of the same dimension must be ordered in order to reduce the number of solutions same_dimension_constraint = [ lex_less(pieces_corners[i], pieces_corners[j]) for i in PIECES for j in PIECES if i < j and ((pieces_dimensions[i][x] == pieces_dimensions[j][y] and pieces_dimensions[i][y] == pieces_dimensions[j][x]) or (pieces_dimensions[i][x] == pieces_dimensions[j][x] and pieces_dimensions[i][y] == pieces_dimensions[j][y])) ] # Same constraint for the problem where rotation of pieces is not an option # same_dimension_constraint = [lex_less(pieces_corners[i], pieces_corners[j]) # for i in PIECES for j in PIECES if i < j and # pieces_dimensions[i] == pieces_dimensions[j]] # OPTIMIZATION CONSTRAINTS: constraint to speed up the search of solutions # If a piece is square (width == height), do not consider the solution with the piece rotated square_pieces_constraint = [ Not(pieces_rotation[i]) for i in PIECES if pieces_dimensions[i][x] == pieces_dimensions[i][y] ] # -------------------------- # SOLUTION # -------------------------- solver = Solver() solver.add(domain_bound_constraints + cumulative_constraints + non_overlapping_constraints + same_dimension_constraint + square_pieces_constraint) return solver, PIECES, pieces_corners, pieces_rotation
Statement 2: q Statement 3: Not(q) The program will output the variables that are true and analyze the result. Expected output (with Python 3): >>> python lady.py Lady in Room I = True That is, the lady is in Room I. ''' from z3 import Bool, And, Or, Not, Sum, If, Solver p = Bool('Lady in Room I') # Lady in Room I q = Bool('Lady in Room II') # Lady in Room II r = Bool('Lady in Room III') # Lady in Room III solver = Solver() solver.add( # The lady is in only one of the three rooms Sum([If(b, 1, 0) for b in [p, q, r]]) == 1, # At most one statement is true Or( # Room I is true And(Not(p), Not(q), q), # Room II is true And(p, q, q), # Room III is true And(p, Not(q), Not(q)),
def _create_vars(self, vertices): for vertex in vertices: for i in range(self.colors_num): key = str(vertex.id * self.colors_num + i + 1) self.vars[key] = Bool(key)