Source code for quantum_launcher.problems.problem_formulations.bqm
1from typing import Tuple
2import ast
3import numpy as np
4from pyqubo import Spin
5from quantum_launcher.base import adapter, formatter
6from quantum_launcher.problems.problem_initialization import Raw
7
8
[docs]
9@adapter('qubo', 'bqm')
10def qubo_to_bqm(qubo_with_offset) -> dict:
11 qubo, offset = qubo_with_offset
12 bqm, _ = QUBOMatrix(qubo, offset).qubo_matrix_into_bqm()
13 return bqm
14
15
[docs]
16class QUBOMatrix:
17 def __init__(self, qubo_matrix, offset):
18 self.qubo_matrix = qubo_matrix
19 self.offset = offset
20
21 if type(self.qubo_matrix) == str:
22 self.qubo_matrix = np.array(ast.literal_eval(self.qubo_matrix))
23
24 self.symetric = True
25 self._check_if_symetric()
26
27 def _check_if_symetric(self):
28 """
29 Function to check if matrix is symetric
30 """
31 self.symetric = (self.qubo_matrix.transpose()
32 == self.qubo_matrix).all()
33 if not self.symetric:
34 self.qubo_matrix = self._remove_lower_triangle(self.qubo_matrix)
35
36 def _remove_lower_triangle(self, matrix):
37 """
38 Function to remove lower triangle from matrix
39 """
40 for i in range(len(matrix)):
41 for j in range(len(matrix)):
42 if i > j:
43 matrix[i][j] = 0
44 return matrix
45
46 def _get_values_and_qubits(self, matrix):
47 """
48 Function to get values and qubits from matrix in form of dictionary
49 where keys are indexes of qubits and values are values of matrix
50 The function does not take into account zeros in matrix
51 Example:
52 matrix = [[0,1,2],[1,0,3],[2,3,0]]
53 result = {(0,1):1, (0,2):2, (1,0):1, (1,2):3, (2,0):2, (2,1):3}
54 Function also return second value which is the number of qubits
55 """
56 result = {
57 (x, y): c for y, r in enumerate(matrix) for x, c in enumerate(r) if c != 0
58 }
59 return result, len(matrix)
60
[docs]
61 def qubo_matrix_into_bqm(self):
62 values_and_qubits, number_of_qubits = self._get_values_and_qubits(
63 self.qubo_matrix
64 )
65 qubits = [Spin(f"x{i}") for i in range(number_of_qubits)]
66 H = 0
67 for (x, y), value in values_and_qubits.items():
68 if self.symetric:
69 H += value / len(set((x, y))) * qubits[x] * qubits[y]
70 else:
71 H += value * qubits[x] * qubits[y]
72 model = H.compile()
73 bqm = model.to_bqm()
74 bqm.offset += self.offset
75 return bqm, model
76
77
[docs]
78@formatter(Raw, 'bqm')
79def Rawbqm(problem: Raw):
80 return problem.instance