-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMinimization.py
123 lines (102 loc) · 3.47 KB
/
Minimization.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from bqskitrs import HilbertSchmidtResidualsFunction, LeastSquaresMinimizerNative
from bqskitrs import HilbertSchmidtCostFunction
from qiskit import QuantumCircuit
import numpy as np
from bqskit.ext import qiskit_to_bqskit
from bqskit.qis.unitary import UnitaryMatrix
from typing import TypeVar
Self = TypeVar('Self', bound='Minimizer')
class HilbertSchmidtResiduals(
HilbertSchmidtResidualsFunction,
):
'''
A cost function that uses the Hilbert-Schmidt norm of the difference
between two matrices as the cost where the cost is zero if the target and circuit unitary
differ only by a global phase.
'''
class HilbertSchmidtResidualsGenerator:
def gen_cost(
self,
circuit: QuantumCircuit,
target: np.ndarray
):
# circuit = qiskit_to_bqskit(circuit)
target = UnitaryMatrix(target)
return HilbertSchmidtResiduals(circuit, target)
class HilbertSchmidtCost(
HilbertSchmidtCostFunction,
):
'''
A cost function that uses the Hilbert-Schmidt norm of the difference
between two matrices as the cost where the cost is zero if the target and circuit unitary
differ only by a global phase.
'''
class HilbertSchmidtCostGenerator:
def gen_cost(
self,
circuit,
target: np.ndarray
):
# circuit = qiskit_to_bqskit(circuit)
target = UnitaryMatrix(target)
return HilbertSchmidtCost(circuit, target)
class Minimizer(
LeastSquaresMinimizerNative
):
'''
A minimizer that uses the least squares method to minimize the cost function.
'''
def __new__(
cls, num_threads: int = 4, ftol: float = 1e-6,
gtol: float = 1e-10, report: bool = False,
) -> Self:
return super().__new__(cls, num_threads, ftol, gtol, report)
class minimization:
def __init__(
self,
cost_fn_gen=None,
minimizer=None) -> None:
if cost_fn_gen is None:
cost_fn_gen = HilbertSchmidtResidualsGenerator()
if minimizer is None:
minimizer = Minimizer()
self.cost_fn_gen = cost_fn_gen
self.minimizer = minimizer
def instaniate(
self,
circuit: QuantumCircuit,
target: np.ndarray,
x0: np.ndarray
):
circuit = qiskit_to_bqskit(circuit)
target = UnitaryMatrix(target)
cost = self.cost_fn_gen.gen_cost(circuit, target)
return self.minimizer(cost, x0)
def multi_start_instaniate_inplace(
self,
circuit: QuantumCircuit,
target: np.ndarray,
num_starts: int
):
circuit = qiskit_to_bqskit(circuit)
target = UnitaryMatrix(target)
start_gen = [
2 * np.pi * np.random.random(circuit.num_params)
for i in range(num_starts)
]
cost = self.cost_fn_gen.gen_cost(circuit, target)
params_list = [self.instaniate(circuit, target, x0) for x0 in start_gen]
params = sorted(params_list, key=lambda x: cost(x))[0]
circuit.set_params(params)
if __name__ == '__main__':
import qiskit.quantum_info as qi
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc_a = qi.Operator(qc).data
h = HilbertSchmidtResidualsGenerator()
# h = HilbertSchmidResidualsGenerator()
bqc = qiskit_to_bqskit(qc)
params = np.random.random(bqc.num_params)
res = h.gen_cost(qc, qc_a).get_cost(params)
print(res)