Source code for quantum_launcher.problems.problem_formulations.qubo

  1""" Basic problems for Orca """
  2from typing import Tuple
  3import numpy as np
  4from pyqubo import Array
  5from quantum_launcher.problems.problem_formulations.jssp.pyqubo_scheduler import get_jss_bqm
  6import quantum_launcher.problems.problem_initialization as problem
  7
  8from quantum_launcher.base import formatter, adapter
  9
 10
[docs] 11@adapter('qubo', 'qubo_fn') 12def qubo_to_fn(qubo): 13 # TODO check 14 def qubo_fn(bin_vec): 15 return np.dot(bin_vec, np.dot(qubo, bin_vec)) 16 return qubo_fn
17 18
[docs] 19@formatter(problem.MaxCut, 'qubo') 20def get_maxcut_qubo(problem: problem.MaxCut): 21 """ Returns Qubo function """ 22 n = len(problem.instance) 23 Q = np.zeros((n, n)) 24 for (i, j) in problem.instance.edges: 25 Q[i, i] += -1 26 Q[j, j] += -1 27 Q[i, j] += 1 28 Q[j, i] += 1 29 30 return Q, 0
31 32 33@formatter(problem.EC, 'qubo') 34class ECOrca: 35 gamma = 1 36 delta = 0.05 37 38 def Jrr(self, route1, route2): 39 s = len(set(route1).intersection(set(route2))) 40 return s / 2 41 42 def hr(self, route1, routes): 43 i_sum = 0 44 for r in routes: 45 i_sum += len(set(r).intersection(set(route1))) 46 s = i_sum - len(route1) * 2 47 return s / 2 48 49 def calculate_jrr_hr(self, problem: problem.EC): 50 Jrr_dict = dict() 51 indices = np.triu_indices(len(problem.instance), 1) 52 for i1, i2 in zip(indices[0], indices[1]): 53 Jrr_dict[(i1, i2)] = self.Jrr( 54 problem.instance[i1], problem.instance[i2]) 55 56 hr_dict = dict() 57 for i in range(len(problem.instance)): 58 hr_dict[i] = self.hr(problem.instance[i], problem.instance) 59 60 return Jrr_dict, hr_dict 61 62 def calculate_lengths_tab(self, problem: problem.EC): 63 tab = [] 64 for route in problem.instance: 65 tab.append(len(route)) 66 return tab 67 68 def calculate_num_elements(self, problem: problem.EC): 69 d = dict() 70 for route in problem.instance: 71 for el in route: 72 d[el] = 1 73 return len(d) 74 75 def calculate_instance_size(self, problem: problem.EC): 76 # Calculate instance size for training 77 return len(problem.instance) 78 79 def __call__(self, problem: problem.EC): 80 self.num_elements = self.calculate_num_elements(problem) 81 self.len_routes = self.calculate_lengths_tab(problem) 82 Q = np.zeros((len(problem.instance), len(problem.instance))) 83 self.Jrr_dict, self.hr_dict = self.calculate_jrr_hr(problem) 84 for i in self.Jrr_dict: 85 Q[i[0]][i[1]] = self.Jrr_dict[i] 86 Q[i[1]][i[0]] = Q[i[0]][i[1]] 87 88 for i in self.hr_dict: 89 Q[i][i] = -self.hr_dict[i] 90 91 return Q, 0 92 93 94@formatter(problem.JSSP, 'qubo') 95class JSSPOrca: 96 gamma = 1 97 lagrange_one_hot = 1 98 lagrange_precedence = 2 99 lagrange_share = 5 100 101 def _fix_get_jss_bqm(self, instance, max_time, config, 102 lagrange_one_hot=0, 103 lagrange_precedence=0, 104 lagrange_share=0) -> Tuple[dict, list, None]: 105 pre_result = get_jss_bqm(instance, max_time, config, 106 lagrange_one_hot=lagrange_one_hot, 107 lagrange_precedence=lagrange_precedence, 108 lagrange_share=lagrange_share) 109 result = (pre_result.spin.linear, pre_result.spin.quadratic, 110 pre_result.spin.offset) # I need to change it into dict somehow 111 return result, list(result[0].keys()), None 112 113 def calculate_instance_size(self, problem: problem.JSSP): 114 # Calculate instance size for training 115 _, variables, _ = self._fix_get_jss_bqm(problem.instance, problem.max_time, self.config, 116 lagrange_one_hot=self.lagrange_one_hot, 117 lagrange_precedence=self.lagrange_precedence, 118 lagrange_share=self.lagrange_share) 119 return len(variables) 120 121 def get_len_all_jobs(self, problem: problem.JSSP): 122 result = 0 123 for job in problem.instance.values(): 124 result += len(job) 125 return result 126 127 def one_hot_to_jobs(self, binary_vector, problem: problem.JSSP): 128 actually_its_qubo, variables, model = self._fix_get_jss_bqm(problem.instance, problem.max_time, self.config, 129 lagrange_one_hot=self.lagrange_one_hot, 130 lagrange_precedence=self.lagrange_precedence, 131 lagrange_share=self.lagrange_share) 132 result = [variables[i] 133 for i in range(len(variables)) if binary_vector[i] == 1] 134 return result 135 136 def _set_config(self): 137 self.config = {} 138 self.config['parameters'] = {} 139 self.config['parameters']['job_shop_scheduler'] = {} 140 self.config['parameters']['job_shop_scheduler']['problem_version'] = "optimization" 141 142 def __call__(self, problem: problem.JSSP): 143 # Define the matrix Q used for QUBO 144 self.config = {} 145 self.instance_size = self.calculate_instance_size(problem) 146 self._set_config() 147 actually_its_qubo, variables, model = self._fix_get_jss_bqm(problem.instance, problem.max_time, self.config, 148 lagrange_one_hot=self.lagrange_one_hot, 149 lagrange_precedence=self.lagrange_precedence, 150 lagrange_share=self.lagrange_share) 151 reverse_dict_map = {v: i for i, v in enumerate(variables)} 152 153 Q = np.zeros((self.instance_size, self.instance_size)) 154 155 for (label_i, label_j), value in actually_its_qubo[1].items(): 156 i = reverse_dict_map[label_i] 157 j = reverse_dict_map[label_j] 158 Q[i, j] += value 159 Q[j, i] = Q[i, j] 160 161 for label_i, value in actually_its_qubo[0].items(): 162 i = reverse_dict_map[label_i] 163 Q[i, i] += value 164 return Q / max(np.max(Q), -np.min(Q)), 0 165 166
[docs] 167@formatter(problem.Raw, 'qubo') 168def get_raw_qubo(problem: problem.Raw): 169 return problem.instance
170 171
[docs] 172@formatter(problem.GraphColoring, 'qubo') 173def get_graph_coloring_qubo(problem: problem.GraphColoring): 174 """ Returns Qubo function """ 175 num_qubits = problem.instance.number_of_nodes() * problem.num_colors 176 x = Array.create('x', shape=(problem.instance.number_of_nodes(), problem.num_colors), vartype='BINARY') 177 qubo = 0 178 for node in problem.instance.nodes: 179 qubo += (1 - sum(x[node, i] for i in range(problem.num_colors))) ** 2 180 for n1, n2 in problem.instance.edges: 181 for c in range(problem.num_colors): 182 qubo += (x[n1, c] * x[n2, c]) 183 model = qubo.compile() 184 qubo_dict, offset = model.to_qubo() 185 Q_matrix = np.zeros((num_qubits, num_qubits)) 186 for i in range(num_qubits): 187 for j in range(num_qubits): 188 n1, c1 = i//problem.num_colors, i % problem.num_colors 189 n2, c2 = j//problem.num_colors, j % problem.num_colors 190 key = ("x["+str(n1)+"]["+str(c1)+"]", "x["+str(n2)+"]["+str(c2)+"]") 191 if key in qubo_dict: 192 Q_matrix[i, j] = qubo_dict[key] 193 return Q_matrix, offset