def by_amplify_limited(list_dependent_variables, num_registers, limitation): num_variables = len(list_dependent_variables) q = gen_symbols(BinaryPoly, num_variables, num_registers) # 各変数を1つのレジスタに割り当てるOne-het制約 const_onehot = [ equal_to(sum_poly([q[i][r] for r in range(num_registers)]), 1) for i in range(num_variables) ] # レジスタスピルを減らすために,依存関係のある変数同士が同一のレジスタに割り当てられない制約 const_spill = [ penalty(q[i][r] * q[j][r]) for i in range(num_variables) for j in list_dependent_variables[i] if i < j for r in range(num_registers) ] # ある変数が割り当てられるレジスタがわかっている時,必ずそのレジスタに割り当てられるようにする制約 const_limit = [ penalty(q[i][r]) for i, x in limitation.items() for r in range(num_registers) if r not in x ] constraints = sum(const_onehot) if len(const_spill) != 0: constraints += sum(const_spill) if len(const_limit) != 0: constraints += sum(const_limit) return {"qubits": q, "model": BinaryQuadraticModel(constraints)}
def time_constraint(self): """時間制約 Returns: [amplify.BinaryConstraint]: (\\sum_{i=1}^{N}(t_{i}x_{i}) - T)^2 """ return penalty((self.time_limit - sum_poly( self.num_tracks, lambda i: self.q[i] * (self.candidates[i].duration_ms // 1000)))**2)
def by_amplify(list_dependent_variables, num_registers): num_variables = len(list_dependent_variables) q = gen_symbols(BinaryPoly, num_variables, num_registers) # 各変数を1つのレジスタに割り当てるOne-het制約 const_onehot = [ equal_to(sum_poly([q[i][r] for r in range(num_registers)]), 1) for i in range(num_variables) ] # レジスタスピルを減らすために,依存関係のある変数同士が同一のレジスタに割り当てられない制約 const_spill = [ penalty(q[i][r] * q[j][r]) for i in range(num_variables) for j in list_dependent_variables[i] if i < j for r in range(num_registers) ] constraints = sum(const_onehot) + sum(const_spill) return {"qubits": q, "model": BinaryQuadraticModel(constraints)}
# 都道府県数 x 色数 の変数を作成 q = gen_symbols(BinaryPoly, num_region, num_colors) # 各領域に対する制約 # 一つの領域に一色のみ(one-hot) # sum_{c=0}^{C-1} q_{i,c} = 1 for all i reg_constraints = [ equal_to(sum_poly([q[i][c] for c in range(num_colors)]), 1) for i in range(num_region) ] # 隣接する領域間の制約 adj_constraints = [ # 都道府県コードと配列インデックスは1ずれてるので注意 penalty(q[i][c] * q[j - 1][c]) for i in range(num_region) for j in jm.adjacent(i + 1) # j: 隣接している都道府県コード if i + 1 < j for c in range(num_colors) ] constraints = sum(reg_constraints) + sum(adj_constraints) model = BinaryQuadraticModel(constraints) result = solver.solve(model) if len(result) == 0: raise RuntimeError("Any one of constraints is not satisfied.") values = result[0].values q_values = decode_solution(q, values, 1) color_indices = np.where(np.array(q_values) == 1)[1]
def quantum_solver_approx(N, M, query): # solve with Amplify (approximate version) q = gen_symbols(BinaryPoly, M, N, N) # represent the solution ########## constraints ########## # each layer doesn't have 2+ same values one_hot_constraints_layer = [ # m -> layer # n -> qubit # v -> value of qubit equal_to(sum(q[m][n][v] for n in range(N)), 1) for m in range(M) for v in range(N) ] # each qubit doesn't have 2+ values one_hot_constraints_num = [ # m -> layer # n -> qubit # v -> value of qubit equal_to(sum(q[m][n][v] for v in range(N)), 1) for m in range(M) for n in range(N) ] # every CX gate must be applied for 2 adjacent qubits CXgate_constraints = [] for m in range(M): for g0 in range(0, len(query[m]), 2): v0, v1 = query[m][g0], query[m][g0 + 1] # v0 and v1 must be adjacent each other for i in range(N): for j in range(i + 2, N): CXgate_constraints.append( penalty(q[m][i][v0] * q[m][j][v1])) CXgate_constraints.append( penalty(q[m][i][v1] * q[m][j][v0])) constraints = (sum(one_hot_constraints_layer) + sum(one_hot_constraints_num) + sum(CXgate_constraints)) cost = sum_poly( M - 1, lambda m: sum_poly( N, lambda i: sum_poly( N, lambda j: sum_poly(N, lambda v: q[m][i][v] * q[m + 1][j][v]) * ((N - 1) * (i + j) - 2 * i * j) / N))) ########## solve ########## solver = Solver(client) model = BinaryQuadraticModel(constraints * constraintWeight + cost) result = solver.solve(model) if len(result) == 0: raise RuntimeError("Any one of constraints is not satisfied.") values = result[0].values q_values = decode_solution(q, values, 1) # print(q_values_main) ########## decode the result into string ########## ans = [[-1 for n in range(N)] for m in range(M)] for m in range(M): for n in range(N): for v in range(N): if (q_values[m][n][v] > 0.5): ans[m][n] = v cost = 0 for m in range(M - 1): cost += calcCost(ans[m], ans[m + 1]) return cost, ans
def quantum_solver_strict(N, M, query): # solve by Amplify (strict version) q_all = gen_symbols(BinaryPoly, M * N * N + (M - 1) * N * N * N + (M - 1) * N * N) q = q_all[:M * N * N] # represent the solution q_sub = q_all[M * N * N:M * N * N + (M - 1) * N * N * N] # q_sub[m][i][j][v] = q[m][i][v] * q[m+1][j][v] q_C_matrix = q_all[ M * N * N + (M - 1) * N * N * N:] # q_C_matrix[m][i][j] = sum(q_sub[m][i][j][v] for v) ########## constraints ########## # each layer doesn't have 2+ same values one_hot_constraints_layer = [ # m -> layer # n -> physical qubit # v -> logical qubit equal_to(sum(q[(m * N + n) * N + v] for n in range(N)), 1) for m in range(M) for v in range(N) ] # each qubit doesn't have 2+ values one_hot_constraints_num = [ # m -> layer # n -> physical qubit # v -> logical qubit equal_to(sum(q[(m * N + n) * N + v] for v in range(N)), 1) for m in range(M) for n in range(N) ] # every CX gate must be applied for 2 adjacent qubits CXgate_constraints = [] for m in range(M): for g0 in range(0, len(query[m]), 2): v0, v1 = query[m][g0], query[m][g0 + 1] # v0 and v1 must be adjacent each other for i in range(N): for j in range(i + 2, N): CXgate_constraints.append( penalty(q[(m * N + i) * N + v0] * q[(m * N + j) * N + v1])) CXgate_constraints.append( penalty(q[(m * N + i) * N + v1] * q[(m * N + j) * N + v0])) # q_sub[m][i][j][v] = q[m][i][v] * q[m+1][j][v] sub_gate_constraints = [] for _idx in range((M - 1) * N**3): idx = _idx m = idx // (N**3) idx %= N**3 i = idx // (N**2) idx %= N**2 j = idx // N idx %= N v = idx sub_gate_constraints.append( penalty(3 * q_sub[((m * N + i) * N + j) * N + v] + q[(m * N + i) * N + v] * q[((m + 1) * N + j) * N + v] - 2 * q_sub[((m * N + i) * N + j) * N + v] * (q[(m * N + i) * N + v] + q[((m + 1) * N + j) * N + v]))) # q_C_matrix[m][i][j] = sum(q_sub[m][i][j][v] for v) C_matrix_sum_constraints = [] for _idx in range((M - 1) * N**2): idx = _idx m = idx // (N**2) idx %= N**2 i = idx // N idx %= N j = idx C_matrix_sum_constraints.append( equal_to( q_C_matrix[(m * N + i) * N + j] - sum(q_sub[((m * N + i) * N + j) * N + v] for v in range(N)), 0)) constraints = (sum(one_hot_constraints_layer) + sum(one_hot_constraints_num) + sum(CXgate_constraints) + sum(sub_gate_constraints) + sum(C_matrix_sum_constraints)) cost = [] for m in range(M - 1): for i1 in range(N): for j1 in range(i1): # i1 > j1 for i2 in range(N): for j2 in range(i2 + 1, N): # i2 < j2 cost.append(q_C_matrix[(m * N + i1) * N + j1] * q_C_matrix[(m * N + i2) * N + j2]) for j1 in range(i1 + 1, N): # i1 < j1 for i2 in range(N): for j2 in range(i2): # i2 > j2 cost.append(q_C_matrix[(m * N + i1) * N + j1] * q_C_matrix[(m * N + i2) * N + j2]) # print(constraints) # print(cost) ########## solve ########## solver = Solver(client) model = BinaryQuadraticModel(constraints * constraintWeight + sum(cost)) result = solver.solve(model) if len(result) == 0: raise RuntimeError("Any one of constraints is not satisfied.") values = result[0].values q_values = decode_solution(q_all, values, 1) # print(q_values_main) ########## decode the result into string ########## ans = [[-1 for n in range(N)] for m in range(M)] for m in range(M): for n in range(N): for v in range(N): if (q_values[(m * N + n) * N + v] > 0.5): ans[m][n] = v cost = 0 for m in range(M - 1): cost += calcCost(ans[m], ans[m + 1]) return cost, ans
client.token = "i5G6Ei3DKlGv2n6hsWBSBzWrmffLN4vn" #20210011まで有効 client.parameters.outputs.duplicate = True # 同じエネルギー値の解を列挙するオプション client.parameters.outputs.num_outputs = 0 # 見つかったすべての解を出力 # ソルバーの構築 solver = Solver(client) # ソルバーに使用するクライアントを設定 # バイナリ変数:要素数2 q = gen_symbols(BinaryPoly, 2) ########################################################### # NAND制約を与える多項式 g_NAND = q[0] * q[1] # NAND制約をペナルティ制約条件に変換 p_NAND = penalty(g_NAND) print("NAND") print(f"p_NAND = {p_NAND}") # 制約条件を満たす解を求める result = solver.solve(p_NAND) for sol in result: energy = sol.energy values = sol.values print(f"energy = {energy}, {q} = {decode_solution(q, values)}") ########################################################### # OR制約を与える多項式 g_OR = q[0] * q[1] - q[0] - q[1] + 1