Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
test_float32_wrapper.py
Go to the documentation of this file.
1 import numpy as np
2 
3 from squander import (
4  N_Qubit_Decomposition,
5  N_Qubit_Decomposition_adaptive,
6  N_Qubit_Decomposition_custom,
7  N_Qubit_Decomposition_Tabu_Search,
8  N_Qubit_Decomposition_Tree_Search,
9 )
10 from squander.gates.qgd_Circuit import qgd_Circuit as Circuit
11 
12 
13 def _identity(n=2, dtype=np.complex64):
14  return np.eye(1 << n, dtype=dtype)
15 
16 
18  config = {"use_float": True}
19  classes = (
20  N_Qubit_Decomposition,
21  N_Qubit_Decomposition_adaptive,
22  N_Qubit_Decomposition_custom,
23  N_Qubit_Decomposition_Tree_Search,
24  N_Qubit_Decomposition_Tabu_Search,
25  )
26 
27  for cls in classes:
28  decomp = cls(_identity(dtype=np.complex64), config=config)
29  assert decomp.get_Qbit_Num() == 2
30 
31 
33  decomp = N_Qubit_Decomposition(_identity(dtype=np.complex128), config={"use_float": True})
34  params = np.array([], dtype=np.float64)
35 
36  unitary = np.asarray(decomp.get_Unitary())
37  matrix = np.asarray(decomp.get_Matrix(params))
38 
39  assert unitary.dtype == np.complex64
40  assert matrix.dtype == np.complex64
41 
42 
44  decomp = N_Qubit_Decomposition(_identity(dtype=np.complex64), config={"use_float": True})
45  params = np.array([], dtype=np.float32)
46 
47  unitary = np.asarray(decomp.get_Unitary())
48  matrix = np.asarray(decomp.get_Matrix(params))
49 
50  assert unitary.dtype == np.complex64
51  assert matrix.dtype == np.complex64
52  np.testing.assert_allclose(matrix, np.eye(4, dtype=np.complex64), atol=1e-6)
53 
54 
56  decomp = N_Qubit_Decomposition_adaptive(_identity(dtype=np.complex64), config={"use_float": True})
57  replacement = _identity(dtype=np.complex64)
58 
59  assert decomp.set_Unitary(replacement) == 0
60  unitary = np.asarray(decomp.get_Unitary())
61 
62  assert unitary.dtype == np.complex64
63  np.testing.assert_allclose(unitary, replacement, atol=1e-6)
64 
65 
67  decomp = N_Qubit_Decomposition(_identity(dtype=np.complex64), config={"use_float": True})
68  params = np.array([], dtype=np.float32)
69  batch = np.zeros((2, 0), dtype=np.float32)
70 
71  assert np.isclose(decomp.Optimization_Problem(params), 0.0, atol=1e-6)
72 
73  grad = np.asarray(decomp.Optimization_Problem_Grad(params))
74  assert grad.dtype == np.float32
75  assert grad.size == 0
76 
77  cost, combined_grad = decomp.Optimization_Problem_Combined(params)
78  assert np.isclose(cost, 0.0, atol=1e-6)
79  assert np.asarray(combined_grad).dtype == np.float32
80 
81  batched = np.asarray(decomp.Optimization_Problem_Batch(batch))
82  assert batched.dtype == np.float32
83  np.testing.assert_allclose(batched, np.zeros(2, dtype=np.float32), atol=1e-6)
84 
85 
87  qbit_num = 4
88  inner = Circuit(qbit_num)
89  parameters = []
90  for qbit in range(qbit_num):
91  inner.add_U3(qbit)
92  parameters.extend([0.1, 0.2, 0.3])
93  inner.add_CNOT(1, 0)
94  for qbit in range(qbit_num):
95  inner.add_U3(qbit)
96  parameters.extend([0.1, 0.2, 0.3])
97 
98  outer = Circuit(qbit_num)
99  outer.add_Circuit(inner)
100  parameters = np.asarray(parameters, dtype=np.float32)
101 
103  _identity(qbit_num, dtype=np.complex64),
104  config={"use_float": True, "parallel": 0},
105  )
106  decomp.set_Gate_Structure(outer)
107 
108  for _ in range(20):
109  cost, grad = decomp.Optimization_Problem_Combined(parameters)
110  assert np.isfinite(cost)
111  assert np.asarray(grad).dtype == np.float32
112 
113 
115  qbit_num = 3
116  inner = Circuit(qbit_num)
117  inner.add_U3(0)
118  inner.add_U3(1)
119  inner.add_CNOT(1, 0)
120  inner.add_U3(2)
121  inner.add_CNOT(2, 1)
122  inner.add_U3(0)
123 
124  outer = Circuit(qbit_num)
125  outer.add_U3(2)
126  outer.add_Circuit(inner)
127  outer.add_U3(1)
128 
129  parameters = np.linspace(0.1, 1.7, 18, dtype=np.float64)
131  _identity(qbit_num, dtype=np.complex128),
132  config={"parallel": 0},
133  )
134  decomp.set_Gate_Structure(outer)
135 
136  _, grad = decomp.Optimization_Problem_Combined(parameters)
137  grad = np.asarray(grad)
138 
139  eps = 1e-7
140  finite_diff = np.empty_like(parameters)
141  for idx in range(parameters.size):
142  params_plus = parameters.copy()
143  params_minus = parameters.copy()
144  params_plus[idx] += eps
145  params_minus[idx] -= eps
146  finite_diff[idx] = (
147  decomp.Optimization_Problem(params_plus)
148  - decomp.Optimization_Problem(params_minus)
149  ) / (2 * eps)
150 
151  np.testing.assert_allclose(grad, finite_diff, rtol=1e-5, atol=1e-6)
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...
A base class to determine the decomposition of an N-qubit unitary into a sequence of CNOT and U3 gate...