def add_precedence_constraints(self, precedence_pairs): for job, pairs in precedence_pairs.items(): for i, t, k, tprime in pairs: self.operation_order_const += \ pyqubo.Constraint( self.bin_vars[job][i + 1][t] * self.bin_vars[job][k + 1][tprime], "operation_order__{}_{}_{}__{}_{}_{}".format(job, i + 1, t, job, k + 1, tprime) )
def add_machine_cap_constraints(self, machines): for machine_cap_pairs in machines.values(): for i, k in machine_cap_pairs: self.machine_cap_const += \ pyqubo.Constraint( self.bin_vars[i[0]][i[1]][i[2]] * self.bin_vars[k[0]][k[1]][k[2]], "machine_cap__{}_{}_{}__{}_{}_{}".format(i[0], i[1], i[2], k[0], k[1], k[2]) )
def TSPHamiltonian(citiesSize: int, pathsWeight: nptyping.Array[int]): if pathsWeightChecker(citiesSize, pathsWeight): pass else: sys.exit() timeSteps = citiesSize x = pyqubo.Array.create("x", (citiesSize - 1, citiesSize - 1), "BINARY") # goal -> start costHamiltonian = pyqubo.Sum(0, citiesSize - 1, lambda start: pathsWeight[citiesSize - 1, start] * x[start][0]) # on the way costHamiltonian += pyqubo.Sum( 0, timeSteps - 2, lambda time: pyqubo.Sum( 0, citiesSize - 2, lambda i: pyqubo.Sum(i + 1, citiesSize - 1, lambda j: pathsWeight[i, j] * x[i][time] * x[j][time + 1]), ), ) # on the way -> goal costHamiltonian += pyqubo.Sum(0, citiesSize - 1, lambda j: pathsWeight[j, citiesSize - 1] * x[j][timeSteps - 2]) ## Constrain timeConstrain = pyqubo.Constraint( pyqubo.Sum(0, timeSteps - 1, lambda time: (pyqubo.Sum(0, citiesSize - 1, lambda i: x[i][time]) - 1) ** 2), label="time", ) visitConstrain = pyqubo.Constraint( pyqubo.Sum(0, citiesSize - 1, lambda i: (pyqubo.Sum(0, timeSteps - 1, lambda time: x[i][time]) - 1) ** 2), label="city", ) hamiltonian = ( costHamiltonian + pyqubo.Placeholder("lamTime") * timeConstrain + pyqubo.Placeholder("lamVisit") * visitConstrain ) return hamiltonian
def test_logical_model_to_physical_with_placeholder_qubo(qubo): # Note: This test is needed to test a PhysicalModel whose offset is pyqubo.core.Coefficient a = qubo.variables("a", shape=(4,)) onehot = pyqubo.Constraint((pyqubo.Sum(0, 4, lambda i: a[i]) - 1) ** 2, label="one-hot") hamiltonian = onehot * pyqubo.Placeholder("A") qubo.from_pyqubo(hamiltonian) placeholder = {"A": 2.0} physical = qubo.to_physical(placeholder=placeholder) assert physical._offset == 2.0
def add_start_once_constraints(self, start_times): for job, op_num, op_times in start_times: # constraint is (sum(time_vars) - 1)**2; penalizes more or less than one start time self.start_once_const += \ pyqubo.Constraint( ( pyqubo.Sum( 0, len(op_times), lambda t: self.bin_vars[job][op_num][op_times[t]] ) - 1 ) ** 2, "start_once_{}_o{}".format(job, op_num) )
def knapsack(W, weights, costs): xs = pyqubo.Array.create('x', shape=(len(weights)), vartype='BINARY') ## 価値の制約 X = -sum([c * x for (x, c) in zip(xs, costs)]) ## OneHot Encoding a = pyqubo.OneHotEncInteger('y', 1, W, strength=100) ## 重さの制約 Y = (a - sum([w * x for (x, w) in zip(xs, weights)]))**2 ## ハミルトニアン(コスト関数) H = X + pyqubo.Constraint(Y, label="one_hot") ## モデル作成とQUBOの生成 model = H.compile() q, offset = model.to_qubo() # print(q) ## 解答 sampleset = dimod.ExactSolver().sample_qubo(q) solution, broken, e = model.decode_dimod_response(sampleset, topk=1)[0] return solution
def tsp_mapping( prev_model: sawatabi.model.LogicalModel, prev_sampleset: dimod.SampleSet, curr_data: List[Tuple[float, Tuple[int, Dict[str, List[float]]]]], incoming: List[Tuple[float, Tuple[int, Dict[str, List[float]]]]], outgoing: List[Tuple[float, Tuple[int, Dict[str, List[float]]]]], ) -> sawatabi.model.LogicalModel: """ Mapping -- Update model based on the input data elements Parameters ---------- prev_model : sawatabi.model.LogicalModel Previous LogicalModel. prev_sampleset : dimod.SampleSet, Previous SampleSet. curr_data : List Elements in the current window (= prev data + incoming - outgoing). curr_data : [ (1.0, (1, {'Sendai': [140.87194, 38.26889]})), (2.0, (2, {'Tokyo': [139.69167, 35.689440000000005]})), (3.0, (3, {'Yokohama': [139.6425, 35.44778]})), (4.0, (4, {'Nagoya': [136.90667, 35.180279999999996]})), (5.0, (5, {'Kyoto': [135.75556, 35.021390000000004]})) ] incoming : List Elements just coming into the current window. incoming: [ (5.0, (5, {'Kyoto': [135.75556, 35.021390000000004]})) ] outgoing : List Elements just going from the current window. outgoing: [ (0.0, (0, {'Sapporo': [141.34694, 43.064170000000004]})) ] Returns ------- model : sawatabi.model.LogicalModel LogicalModel of TSP created from data in the current window. """ import pyqubo from geopy.distance import geodesic model: sawatabi.model.LogicalModel = prev_model.empty() # print(f"incoming: {incoming}", type(incoming)) # print(f"curr_data: {curr_data}", type(curr_data)) # print(f"outgoing: {outgoing}", type(outgoing)) # prepare binary vector with bit(i, j) n_city = len(curr_data) if n_city > 0: binary_vector = model.append("city", shape=(n_city, n_city)) # Update variables else: return model # Constraint not to visit more than one citie at the same time. time_const = 0.0 for i in range(n_city): time_const += pyqubo.Constraint( (pyqubo.Sum(0, n_city, lambda j: binary_vector[i, j]) - 1)**2, label="time{}".format(i)) # Constraint not to visit the same city more than once. city_const = 0.0 for j in range(n_city): city_const += pyqubo.Constraint( (pyqubo.Sum(0, n_city, lambda i: binary_vector[i, j]) - 1)**2, label="city{}".format(j)) # Objective term n_cities = [list(c[1][1].values())[0] for c in curr_data] traveling_distance = 0.0 for i in range(n_city): # i: city to visit for j in range(n_city): # j: city to visit for k in range(n_city): # k: visit order # Scale down O(100)km -> O(1)km or convenience long_lat_dist = geodesic( (n_cities[i][1], n_cities[i][0]), (n_cities[j][1], n_cities[j][0])).km / 100 traveling_distance += long_lat_dist * binary_vector[ k, i] * binary_vector[(k + 1) % n_city, j] # Build an Hamiltonian from the constraint terms and the objective term. hamiltonian_tsp = traveling_distance + pyqubo.Placeholder( "time") * time_const + pyqubo.Placeholder("city") * city_const # Load QUBO from the PyQUBO expression into the Sawatabi model. model.from_pyqubo(hamiltonian_tsp) # print(f"model: {model}", type(model)) return model
def optimize(game_type, W, c, w, min_count): N = len(w) # x_max = {k: int(W / v) for k, v in w.items()} offset_value = {x: int(min_count[x]) * int(y) for x, y in w.items()} new_W = W - sum(offset_value.values()) x_max = {k: int((new_W) / v) for k, v in w.items()} print('min_count') print(min_count) print('offset_value') print(offset_value) print('sum_offset_value') print(sum(offset_value.values())) print('new_W') print(new_W) print('x_max') print(x_max) for k, v in x_max.items(): if v <= 0: return "paramater error" # print("x_max: ") # print(x_max) x = pyq.Array([ pyq.LogEncInteger('x_{}'.format(i), (0, x_max[i])) for i in x_max.keys() ]) y = pyq.LogEncInteger('y', (0, new_W)) A, B = pyq.Placeholder("A"), pyq.Placeholder("B") HA = pyq.Constraint(A * (new_W - sum(w[a] * x[a] for a in range(N)) - y)**2, label='HA') HB = -B * sum(c[a] * x[a] for a in range(N)) Q = HA + HB model = Q.compile() feed_dict = {'A': 1, 'B': 1} qubo, offset = model.to_qubo(feed_dict=feed_dict) #iteration回数 iteration = 1000 sampler = oj.SASampler(num_reads=iteration) response = sampler.sample_qubo(qubo) def decode_solution(sampleset): decoded = model.decode_sampleset(response, feed_dict=feed_dict) solution = decoded[0].subh x = np.zeros(N, dtype=int) y = 0 for k, v in solution.items(): if 'x' in k: index = int(k.split('_')[1]) x[index] = v elif 'y' in k: y = v return {'x': x, 'y': y} result = decode_solution(response) print(result['x']) result_x = result['x'] print('result_x') print(result_x) # gacha_count = {v: result_x[k] for k,v in game_type.items()} # print(gacha_count) gacha_result = { game_id[str(v)]: result_x[k] + min_count[k] for k, v in enumerate(game_type) } gacha_count = { str(v): result_x[k] + min_count[k] for k, v in enumerate(game_type) } print('gacha_result') print(gacha_result) print('gacha_count') print(gacha_count) for k, v in gacha_result.items(): print(k) print(v) sum_money = sum(offset_value) for k, v in gacha_count.items(): sum_money += v * int(gacha_bid[k]) print('合計金額:') print(sum_money) return gacha_result