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 room_total_satisfaction(self): """ルームの総満足度 Returns: [amplify.BinaryPoly]: \\sum_{j=1}^{M}P(j) """ return sum_poly(self.num_users, lambda j: self.someone_total_satisfaction(j))
def room_variance_satisfaction(self): """ルームの満足度の分散 Returns: [amplify.BinaryPoly]: \\sum_{j=1}^{M}(P_{avg}-P(j))^2 / M """ return sum_poly( self.num_users, lambda j: (self.room_average_satisfaction( ) - self.someone_total_satisfaction(j))**2) / self.num_users
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 make_hamiltonian(d, feed_dict): # set the number of cities N = len(d) # set hyperparameters lambda_1 = feed_dict['h1'] lambda_2 = feed_dict['h2'] # make variables x = gen_symbols(BinaryPoly, N, N) # set One-hot constraint for time h1 = [equal_to(sum_poly([x[n][i] for n in range(N)]), 1) for i in range(N)] # set One-hot constraint for city h2 = [equal_to(sum_poly([x[n][i] for i in range(N)]), 1) for n in range(N)] # compute the total of constraints const = lambda_1 * sum(h1) + lambda_2 * sum(h2) # set objective function obj = sum_poly(N, lambda n: sum_poly(N, lambda i: sum_poly(N, lambda j: d[i][j]*x[n][i]*x[(n+1)%N][j]), ), ) # compute model model = obj + const return x, model
def someone_total_satisfaction(self, j: int): """メンバーjの総満足度 Args: j (int): メンバーインデックス Returns: [amplify.BinaryPoly]: P(j) = \\sum_{i=1}^{N}p_{i,j}x_{i} """ return sum_poly(self.num_tracks, lambda i: self.q[i] * self.candidates[i].p[j])
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)}
solver = Solver(client) # 四色の定義 colors = ["red", "green", "blue", "yellow"] num_colors = len(colors) num_region = len(jm.pref_names) - 1 # 都道府県数を取得 # 都道府県数 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)
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
from amplify import BinaryQuadraticModel, Solver, decode_solution from amplify.client import FixstarsClient from amplify import BinaryPoly, gen_symbols, sum_poly from amplify.constraint import equal_to q = gen_symbols(BinaryPoly, 3) H = equal_to(sum_poly(q), 3) model = BinaryQuadraticModel(H) solver = Solver(client) result = solver.solve(model) values = result[0].values print(f"q = {decode_solution(q, values)}")
# 研究室学生数 nstudents = [4, 5, 4, 3, 3, 2, 4, 4, 4, 4, 5, 3, 4, 3, 3] assert nlab == len(nstudents), "研究室数と学生数配列の長さが違う" # グループ名 grps = ["CS1", "CS2", "CS3", "CS4"] ngrp = len(grps) # グループ数 ################################################################################## # QUBO変数の生成: nlab x ngrp q = gen_symbols(BinaryPoly, nlab, ngrp) # グループ内の教員数 T = [ sum_poly([q[i][j] * nteachers[i] for i in range(nlab)]) for j in range(ngrp) ] # グループ内の学生数 S = [ sum_poly([q[i][j] * nstudents[i] for i in range(nlab)]) for j in range(ngrp) ] ################################################################################## # コスト関数:各グループの学生数、教員数が等しいか? cost = sum_poly(ngrp, lambda j: (S[j] - S[ (j + 1) % ngrp])**2) + sum_poly(ngrp, lambda j: (T[j] - T[ (j + 1) % ngrp])**2)
print("OR") print(f"p_OR = {p_OR}") # 制約条件を満たす解を求める result = solver.solve(p_OR) for sol in result: energy = sol.energy values = sol.values print(f"energy = {energy}, {q} = {decode_solution(q, values)}") ########################################################### # 等式制約:one-hot制約 # バイナリ変数:要素数3 q = gen_symbols(BinaryPoly, 3) g = (sum_poly(q) - 1)**2 # one-hot 制約に対応したペナルティ関数 print("One-Hot") print(f"g = {g}") # 問題を解いて結果を表示 result = solver.solve(g) for sol in result: energy = sol.energy values = sol.values print(f"energy = {energy}, {q} = {decode_solution(q, values)}") ########################################################### # 等式制約:q0 * q1 + q2 = 1 g = equal_to(q[0] * q[1] + q[2], 1) # 等式制約
# インデックスをずらさないと、同一の変数が定義されてしまう print(s1, s2) # s1 の分だけインデックスをずらして変数生成 s3 = gen_symbols(BinaryPoly, len(s1), (4, )) # 異なる変数が定義できる print(s1, s3) ########################## # 例 1 # バイナリ変数を1次元配列形式に8個生成 q = gen_symbols(BinaryPoly, 8) # 二値変数や多項式のリストを指定すると、その総和を計算 f0 = sum_poly(q) print(f"f0 = {f0}") ########################## # 例 2 # バイナリ変数を3個生成 q = gen_symbols(BinaryPoly, 3) # インデックスを受け取る関数とインデックスの上限値を指定して、総和を取ることも可能 f1 = sum_poly(3, lambda i: sum_poly(3, lambda j: q[i] * q[j])) print(f"f1 = {f1}") ##########################
if j < len(pol_data[i][2]) - 1: angle_diff = pol_data[i][2][j + 1][2] - pol_data[i][2][j][2] pa_diff_each.append([pol_data[i][2][j][0], angle_diff]) else: angle_diff = pol_data[i][2][0][2] - pol_data[i][2][j][2] pa_diff_each.append([pol_data[i][2][j][0], angle_diff]) pa_diff_data.append([pol_data[i][0], pol_data[i][1], pa_diff_each]) # テンプレートとして持っているデータの個数をバイナリ変数の数とする。 # 1のとき、その角度パラメータである。0のときその角度パラメータではないとする。 q = gen_symbols(BinaryPoly, len(pa_diff_data)) # onehot条件: 当てはまる角度パラメータは1つだけ const_onehot = (sum_poly(q) - 1)**2 # 目的関数: 各回転位相での偏光角の違いを小さくするためのもの obj_pa = 0.0 coef = 1.0 / 180.0 for j in range(len(pa_test)): obj_pa_j = pa_test[j][1] for i in range(len(pa_data)): obj_pa_j -= pa_data[i][2][j][1] * q[i] obj_pa += coef**2 * obj_pa_j**2 # 目的関数: 各回転位相の偏光角の変化の違いを小さくするためのもの obj_pa_diff = 0.0
def find_feasible_solution(self): """find a feasible locations with makespan, found -> set self.used_edges """ # create variables q = [] index = 0 for t in range(self.makespan): q.append([]) for v in range(self.field["size"]): l = len(self.field["adj"][v])+1 # +1 -> stay at the current location q[-1].append( amplify.gen_symbols( amplify.BinaryPoly, index, (1, l) ) ) index += l # set starts constraints_starts = [ equal_to(sum_poly( q[0][v][0] ), 1) # q[timestep][node][0] for v in self.instance["starts"] ] for v in range(self.field["size"]): if v in self.instance["starts"]: continue # other locations for i in range(len(q[0][v][0])): q[0][v][0][i] = amplify.BinaryPoly(0) # set goals constraints_goals = [ equal_to(sum_poly([ q[-1][u][0][ self.field["adj"][u].index(v) ] for u in self.field["adj"][v] ] + [ q[-1][v][0][ len(self.field["adj"][v]) ] ]), 1) for v in self.instance["goals"] ] for v in range(self.field["size"]): # other locations for i in range(len(self.field["adj"][v])): if self.field["adj"][v][i] not in self.instance["goals"]: q[-1][v][0][i] = amplify.BinaryPoly(0) if v not in self.instance["goals"]: q[-1][v][0][-1] = amplify.BinaryPoly(0) # upper bound, in constraints_in = [ less_equal(sum_poly([ q[t][u][0][ self.field["adj"][u].index(v) ] for u in self.field["adj"][v] ] + [ q[t][v][0][ len(self.field["adj"][v]) ] ]), 1) for v, t in product(range(self.field["size"]), range(0, self.makespan-1)) ] # upper bound, out constraints_out = [ less_equal(sum_poly( q[t][v][0] ), 1) for v, t in product(range(self.field["size"]), range(1, self.makespan)) ] # continuity constraints_continuity = [ equal_to(sum_poly([ q[t][u][0][ self.field["adj"][u].index(v) ] for u in self.field["adj"][v] ] + [ q[t][v][0][ len(self.field["adj"][v]) ] ]) - sum_poly( q[t+1][v][0] ), 0) for v, t in product(range(self.field["size"]), range(0, self.makespan-1)) ] # branching for v in range(self.field["size"]): if not self.field["body"][v]: continue # unreachable vertexes from starts for t in range(0, min(self.DIST_TABLE_FROM_STARTS[v], self.makespan)): for i in range(len(q[t][v][0])): q[t][v][0][i] = amplify.BinaryPoly(0) # unreachable vertexes to goals for t in range(max(self.makespan - self.DIST_TABLE_FROM_GOALS[v] + 1, 0), self.makespan): for i in range(len(q[t][v][0])): q[t][v][0][i] = amplify.BinaryPoly(0) # set occupied vertex for v in range(self.field["size"]): if self.field["body"][v]: continue for t in range(0, self.makespan): q[t][v][0][-1] = amplify.BinaryPoly(0) # create model model = sum(constraints_starts) model += sum(constraints_goals) if len(constraints_in) > 0: model += sum(constraints_in) if len(constraints_out) > 0: model += sum(constraints_out) if len(constraints_continuity) > 0: model += sum(constraints_continuity) # setup client client = FixstarsClient() client.token = os.environ['TOKEN'] client.parameters.timeout = self.timeout # solve solver = amplify.Solver(client) result = solver.solve(model) if len(result) > 0: self.used_edges = amplify.decode_solution(q, result[0].values)
from amplify import BinaryPoly, gen_symbols, sum_poly, Solver from amplify.constraint import greater_equal from amplify.client import HitachiClient from secret import get_token import utils import time # 問題サイズ N=2,4,6,8,10,12,14,16 で実験 for N in range(2, 16 + 1, 2): # QUBO変数の2次元配列(正方格子グラフに対応) q = gen_symbols(BinaryPoly, N, N) # コスト関数(w_b で調整) cost_function = sum([sum_poly(q[i]) for i in range(N)]) # 制約(w_a で調整) constraint_x = sum([ greater_equal(q[i][j] + q[i + 1][j], 1) for i in range(N - 1) for j in range(N) ]) constraint_y = sum([ greater_equal(q[i][j] + q[i][j + 1], 1) for i in range(N) for j in range(N - 1) ]) constraint = constraint_x + constraint_y # クライアント設定 client = HitachiClient() client.token = get_token()
def make_hamiltonian(type_matrix, weak_matrix, resist_matrix, enemies, num_party, feed_dict): # set the number of types N = len(type_matrix) # set the number of enemies M = len(enemies) # set hyperparameters lambda_1 = feed_dict['h1'] lambda_2 = feed_dict['h2'] lambda_3 = feed_dict['h3'] # make variables x = gen_symbols(BinaryPoly, num_party, N) # set one-hot constraint for types h1 = [equal_to(sum_poly([x[i][j] for j in range(N)]), 1) for i in range(num_party)] # set weak constraint h2 = [less_equal(sum_poly(N, lambda j: sum_poly(num_party, lambda l: sum_poly(N, lambda k: enemies[i][j]*weak_matrix[j][k]*x[l][k]))), 2) for i in range(M)] # set resist constraint h3 = [greater_equal(sum_poly(N, lambda j: sum_poly(num_party, lambda l: sum_poly(N, lambda k: enemies[i][j]*resist_matrix[j][k]*x[l][k]))), 1) for i in range(M)] # compute the total of constraints const = lambda_1 * sum(h1) + lambda_2 * sum(h2) + lambda_3 * sum(h3) # set objective function obj = sum_poly(num_party, lambda i: sum_poly(N, lambda j: sum_poly(N, lambda k: sum_poly(M, lambda l: x[i][j]*type_matrix[j][k]*enemies[l][k])))) # compute model model = - obj + const return x, model