tequila-basic 1.9.9__py3-none-any.whl → 1.9.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tequila/__init__.py +29 -14
- tequila/apps/__init__.py +14 -5
- tequila/apps/_unary_state_prep_impl.py +145 -112
- tequila/apps/adapt/__init__.py +9 -1
- tequila/apps/adapt/adapt.py +154 -113
- tequila/apps/krylov/__init__.py +1 -1
- tequila/apps/krylov/krylov.py +23 -21
- tequila/apps/robustness/helpers.py +10 -6
- tequila/apps/robustness/interval.py +238 -156
- tequila/apps/unary_state_prep.py +29 -23
- tequila/autograd_imports.py +8 -5
- tequila/circuit/__init__.py +2 -1
- tequila/circuit/_gates_impl.py +135 -67
- tequila/circuit/circuit.py +163 -79
- tequila/circuit/compiler.py +114 -105
- tequila/circuit/gates.py +288 -120
- tequila/circuit/gradient.py +35 -23
- tequila/circuit/noise.py +83 -74
- tequila/circuit/postselection.py +120 -0
- tequila/circuit/pyzx.py +10 -6
- tequila/circuit/qasm.py +201 -83
- tequila/circuit/qpic.py +63 -61
- tequila/grouping/binary_rep.py +148 -146
- tequila/grouping/binary_utils.py +84 -75
- tequila/grouping/compile_groups.py +334 -230
- tequila/grouping/ev_utils.py +77 -41
- tequila/grouping/fermionic_functions.py +383 -308
- tequila/grouping/fermionic_methods.py +170 -123
- tequila/grouping/overlapping_methods.py +69 -52
- tequila/hamiltonian/paulis.py +12 -13
- tequila/hamiltonian/paulistring.py +1 -1
- tequila/hamiltonian/qubit_hamiltonian.py +45 -35
- tequila/ml/__init__.py +1 -0
- tequila/ml/interface_torch.py +19 -16
- tequila/ml/ml_api.py +11 -10
- tequila/ml/utils_ml.py +12 -11
- tequila/objective/__init__.py +8 -3
- tequila/objective/braket.py +55 -47
- tequila/objective/objective.py +87 -55
- tequila/objective/qtensor.py +36 -27
- tequila/optimizers/__init__.py +31 -23
- tequila/optimizers/_containers.py +11 -7
- tequila/optimizers/optimizer_base.py +111 -83
- tequila/optimizers/optimizer_gd.py +258 -231
- tequila/optimizers/optimizer_gpyopt.py +56 -42
- tequila/optimizers/optimizer_scipy.py +157 -112
- tequila/quantumchemistry/__init__.py +66 -38
- tequila/quantumchemistry/chemistry_tools.py +393 -209
- tequila/quantumchemistry/encodings.py +121 -13
- tequila/quantumchemistry/madness_interface.py +170 -96
- tequila/quantumchemistry/orbital_optimizer.py +86 -41
- tequila/quantumchemistry/psi4_interface.py +166 -97
- tequila/quantumchemistry/pyscf_interface.py +70 -23
- tequila/quantumchemistry/qc_base.py +866 -414
- tequila/simulators/__init__.py +0 -3
- tequila/simulators/simulator_api.py +247 -105
- tequila/simulators/simulator_aqt.py +102 -0
- tequila/simulators/simulator_base.py +147 -53
- tequila/simulators/simulator_cirq.py +58 -42
- tequila/simulators/simulator_cudaq.py +600 -0
- tequila/simulators/simulator_ddsim.py +390 -0
- tequila/simulators/simulator_mqp.py +30 -0
- tequila/simulators/simulator_pyquil.py +190 -171
- tequila/simulators/simulator_qibo.py +95 -87
- tequila/simulators/simulator_qiskit.py +119 -107
- tequila/simulators/simulator_qlm.py +52 -26
- tequila/simulators/simulator_qulacs.py +74 -52
- tequila/simulators/simulator_spex.py +95 -60
- tequila/simulators/simulator_symbolic.py +6 -5
- tequila/simulators/test_spex_simulator.py +8 -11
- tequila/tools/convenience.py +4 -4
- tequila/tools/qng.py +72 -64
- tequila/tools/random_generators.py +38 -34
- tequila/utils/bitstrings.py +7 -7
- tequila/utils/exceptions.py +19 -5
- tequila/utils/joined_transformation.py +8 -10
- tequila/utils/keymap.py +0 -5
- tequila/utils/misc.py +6 -4
- tequila/version.py +1 -1
- tequila/wavefunction/qubit_wavefunction.py +47 -28
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/METADATA +13 -16
- tequila_basic-1.9.10.dist-info/RECORD +93 -0
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/WHEEL +1 -1
- tequila_basic-1.9.9.dist-info/RECORD +0 -88
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/licenses/LICENSE +0 -0
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/top_level.txt +0 -0
@@ -8,6 +8,7 @@ import numpy as np
|
|
8
8
|
import numpy.linalg as npl
|
9
9
|
import copy
|
10
10
|
|
11
|
+
|
11
12
|
def compile_commuting_parts(H, unitary_circuit="improved", *args, **kwargs):
|
12
13
|
"""
|
13
14
|
Compile the commuting parts of a QubitHamiltonian
|
@@ -20,7 +21,7 @@ def compile_commuting_parts(H, unitary_circuit="improved", *args, **kwargs):
|
|
20
21
|
-------
|
21
22
|
A list of tuples containing all-Z Hamiltonian and corresponding Rotations
|
22
23
|
"""
|
23
|
-
if "options" in kwargs and
|
24
|
+
if "options" in kwargs and kwargs["options"] is not None and "method" in kwargs["options"]:
|
24
25
|
method = kwargs["options"]["method"]
|
25
26
|
else:
|
26
27
|
method = "rlf"
|
@@ -30,8 +31,8 @@ def compile_commuting_parts(H, unitary_circuit="improved", *args, **kwargs):
|
|
30
31
|
return "qubit"
|
31
32
|
elif method == "lr" or method == "fff-lr":
|
32
33
|
return "fermionic"
|
33
|
-
|
34
|
-
if method_class(method) ==
|
34
|
+
|
35
|
+
if method_class(method) == "qubit":
|
35
36
|
if unitary_circuit is None or unitary_circuit.lower() == "improved":
|
36
37
|
# @ Zack
|
37
38
|
result, suggested_samples = _compile_commuting_parts_zb(H, *args, **kwargs)
|
@@ -41,46 +42,51 @@ def compile_commuting_parts(H, unitary_circuit="improved", *args, **kwargs):
|
|
41
42
|
commuting_parts, suggested_samples = binary_H.commuting_groups(*args, **kwargs)
|
42
43
|
result = [cH.get_qubit_wise() for cH in commuting_parts]
|
43
44
|
return result, suggested_samples
|
44
|
-
|
45
|
-
elif method_class(method) ==
|
45
|
+
|
46
|
+
elif method_class(method) == "fermionic":
|
46
47
|
options = kwargs["options"]
|
47
48
|
if "n_el" in options:
|
48
49
|
n_el = int(options["n_el"])
|
49
|
-
elif "mol_name" in options:
|
50
|
+
elif "mol_name" in options:
|
50
51
|
n_el = n_elec(options["mol_name"])
|
51
52
|
else:
|
52
|
-
raise TequilaException(
|
53
|
+
raise TequilaException(
|
54
|
+
"Please specify either {mol_name:} or {n_el:} in the dictionary provided as the keyward argument (optimize_measurements) to function (ExpectationValue)."
|
55
|
+
)
|
53
56
|
|
54
57
|
if "reverse_H_transf" in options:
|
55
58
|
reverse_H_transf = options["reverse_H_transf"]
|
56
59
|
else:
|
57
60
|
print("Using default reverse_H_transf, i.e., reverse_jordan_wigner.")
|
58
61
|
reverse_H_transf = _reverse_jordan_wigner
|
59
|
-
|
62
|
+
|
60
63
|
h_ferm = reverse_H_transf(H)
|
61
64
|
|
62
|
-
if method ==
|
65
|
+
if method == "lr":
|
63
66
|
u_ops, cartan_obt, cartan_tbt, suggested_samples = do_svd(h_ferm, n_el)
|
64
67
|
result = [get_fermion_wise(cartan_obt, u_ops[0])]
|
65
68
|
for i in range(len(cartan_tbt)):
|
66
|
-
result.append(get_fermion_wise(cartan_tbt[i], u_ops[i+1]))
|
69
|
+
result.append(get_fermion_wise(cartan_tbt[i], u_ops[i + 1]))
|
67
70
|
return result, suggested_samples
|
68
|
-
elif method ==
|
69
|
-
|
70
|
-
|
71
|
+
elif method == "fff-lr":
|
72
|
+
all_ops, u_ops, cartan_obt, cartan_tbt, suggested_samples = do_fff(
|
73
|
+
h_ferm, n_el, options=options, metric_estim=False
|
74
|
+
)
|
71
75
|
result = [get_fermion_wise(cartan_obt, u_ops[0])]
|
72
76
|
for i in range(len(cartan_tbt)):
|
73
|
-
result.append(get_fermion_wise(cartan_tbt[i], u_ops[i+1]))
|
77
|
+
result.append(get_fermion_wise(cartan_tbt[i], u_ops[i + 1]))
|
74
78
|
return result, suggested_samples
|
75
79
|
|
80
|
+
|
76
81
|
def _reverse_jordan_wigner(H):
|
77
|
-
|
82
|
+
"""
|
78
83
|
Default funcion used by fermionic methods to obtain the H in the second quantized form.
|
79
|
-
The user can specify a different reverse function if H was obtained from the fermionic
|
84
|
+
The user can specify a different reverse function if H was obtained from the fermionic
|
80
85
|
Hamiltonian using a mapping different than the JordanWigner transformation.
|
81
|
-
|
86
|
+
"""
|
82
87
|
return reverse_jordan_wigner(H.to_openfermion())
|
83
88
|
|
89
|
+
|
84
90
|
def _compile_commuting_parts_zb(H, *args, **kwargs):
|
85
91
|
# @ Zack add main function here and rest in this file
|
86
92
|
# should return list of commuting Hamiltonians in Z-Form and Circuits
|
@@ -132,28 +138,39 @@ def Tableau_algorithm(circuits):
|
|
132
138
|
num_qubits = U.n_qubits
|
133
139
|
Tableau, Phase_stabilizer, Phase_destabilizer, Circuit = initial_tableau(U, U.n_qubits)
|
134
140
|
|
135
|
-
Tableau, Phase_stabilizer, Phase_destabilizer, Q0 = first_round_hadamard(
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
Tableau, Phase_stabilizer, Phase_destabilizer,
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
Tableau, Phase_stabilizer, Phase_destabilizer,
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
Tableau, Phase_stabilizer, Phase_destabilizer,
|
154
|
-
|
155
|
-
|
156
|
-
|
141
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q0 = first_round_hadamard(
|
142
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
143
|
+
) # H
|
144
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q1 = first_round_cnot(
|
145
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
146
|
+
) # C
|
147
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q2 = first_round_phase(
|
148
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
149
|
+
) # P
|
150
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q3 = second_round_cnot(
|
151
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
152
|
+
) # C
|
153
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q4 = second_round_phase(
|
154
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
155
|
+
) # P
|
156
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q5 = third_round_cnot(
|
157
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
158
|
+
) # C
|
159
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q6 = second_round_hadamard(
|
160
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
161
|
+
) # H
|
162
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q7 = third_round_phase(
|
163
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
164
|
+
) # P
|
165
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q8 = fourth_round_cnot(
|
166
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
167
|
+
) # C
|
168
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q9 = fourth_round_phase(
|
169
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
170
|
+
) # P
|
171
|
+
Tableau, Phase_stabilizer, Phase_destabilizer, Q10 = final_round_cnot(
|
172
|
+
Tableau, Phase_stabilizer, Phase_destabilizer
|
173
|
+
) # C
|
157
174
|
# now the code will optimize the CNOT segments
|
158
175
|
# as put forth in https://arxiv.org/abs/quant-ph/0302002
|
159
176
|
|
@@ -268,7 +285,7 @@ def CNOT_matrix(list_of_gates, num_qubits):
|
|
268
285
|
else:
|
269
286
|
C_NOT_matrix = np.matmul(C_NOT_matrix, j) % 2
|
270
287
|
|
271
|
-
return
|
288
|
+
return C_NOT_matrix
|
272
289
|
|
273
290
|
|
274
291
|
def optimize_circuit(CNOT_matrix):
|
@@ -281,7 +298,7 @@ def optimize_circuit(CNOT_matrix):
|
|
281
298
|
## putting together the two circuits
|
282
299
|
|
283
300
|
# the CNOT gates in circuit two have the control and target qubits swapped
|
284
|
-
for U in
|
301
|
+
for U in circuit2:
|
285
302
|
control_qubit = U[1]
|
286
303
|
target_qubit = U[0]
|
287
304
|
optimized_circuit += tq.gates.CNOT(control_qubit, target_qubit)
|
@@ -292,7 +309,7 @@ def optimize_circuit(CNOT_matrix):
|
|
292
309
|
target_qubit = U[1]
|
293
310
|
optimized_circuit += tq.gates.CNOT(control_qubit, target_qubit)
|
294
311
|
|
295
|
-
return
|
312
|
+
return optimized_circuit
|
296
313
|
|
297
314
|
|
298
315
|
def Lwr_CNOT_Synth(C_NOT_matrix):
|
@@ -306,12 +323,12 @@ def Lwr_CNOT_Synth(C_NOT_matrix):
|
|
306
323
|
for sec in range(len(partitions)):
|
307
324
|
# eliminate duplicate rows
|
308
325
|
for j in range(m, m + iter):
|
309
|
-
if np.all(C_NOT_matrix[j, m:m + iter] == 0):
|
326
|
+
if np.all(C_NOT_matrix[j, m : m + iter] == 0):
|
310
327
|
break
|
311
328
|
for k in range(0, num_qubits):
|
312
329
|
if k < m + iter:
|
313
330
|
continue
|
314
|
-
if np.array_equal(C_NOT_matrix[j, m:m + iter], C_NOT_matrix[k, m:m + iter]):
|
331
|
+
if np.array_equal(C_NOT_matrix[j, m : m + iter], C_NOT_matrix[k, m : m + iter]):
|
315
332
|
target_qubit = k
|
316
333
|
control_qubit = j
|
317
334
|
C_NOT_matrix[target_qubit, :] = (C_NOT_matrix[control_qubit, :] + C_NOT_matrix[target_qubit, :]) % 2
|
@@ -326,8 +343,9 @@ def Lwr_CNOT_Synth(C_NOT_matrix):
|
|
326
343
|
if diag_one == 0:
|
327
344
|
target_qubit = j
|
328
345
|
control_qubit = row
|
329
|
-
C_NOT_matrix[target_qubit, :] = (
|
330
|
-
|
346
|
+
C_NOT_matrix[target_qubit, :] = (
|
347
|
+
C_NOT_matrix[target_qubit, :] + C_NOT_matrix[control_qubit, :]
|
348
|
+
) % 2
|
331
349
|
circ.append([control_qubit, target_qubit])
|
332
350
|
diag_one = 1
|
333
351
|
target_qubit = row
|
@@ -338,6 +356,7 @@ def Lwr_CNOT_Synth(C_NOT_matrix):
|
|
338
356
|
m += iter
|
339
357
|
return (C_NOT_matrix, circ)
|
340
358
|
|
359
|
+
|
341
360
|
def is_canonical(tableau, phase_stab, phase_destab):
|
342
361
|
dim = len(tableau)
|
343
362
|
eye = np.identity(dim)
|
@@ -346,71 +365,85 @@ def is_canonical(tableau, phase_stab, phase_destab):
|
|
346
365
|
else:
|
347
366
|
return False
|
348
367
|
|
368
|
+
|
349
369
|
def initial_tableau(circuit, number_of_qubits):
|
350
370
|
"""Goes through Thomsons circuit (expressed only in H,CNOT and S gates) to update the standard initial tableau
|
351
371
|
as a 2*n X 2*n binary matrix. The final tableau is a binary representation of the circuit"""
|
352
372
|
n = number_of_qubits
|
353
373
|
a = np.identity(2 * n)
|
354
374
|
x_destab = a[0:n, 0:n]
|
355
|
-
z_destab = a[0:n, n:2 * n]
|
356
|
-
x_stab = a[n:2 * n, 0:n]
|
357
|
-
z_stab = a[n:2 * n, n:2 * n]
|
375
|
+
z_destab = a[0:n, n : 2 * n]
|
376
|
+
x_stab = a[n : 2 * n, 0:n]
|
377
|
+
z_stab = a[n : 2 * n, n : 2 * n]
|
358
378
|
phase_destabilizer = np.zeros(n)
|
359
379
|
phase_stabilizer = np.zeros(n)
|
360
380
|
test_circuit = tq.circuit.QCircuit()
|
361
381
|
|
362
|
-
for U in
|
363
|
-
|
364
|
-
if U.name == 'Ry':
|
382
|
+
for U in circuit.gates:
|
383
|
+
if U.name == "Ry":
|
365
384
|
if U.parameter > 0:
|
366
385
|
# decomposing Ry as S^+ * H * S* H * S (we can only use clifford gates S,H,CNOT)
|
367
386
|
target_qubit = U.target[0]
|
368
387
|
test_circuit += tq.gates.S(target_qubit)
|
369
388
|
for i in range(0, n):
|
370
389
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
371
|
-
|
390
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
391
|
+
)
|
372
392
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
373
|
-
|
393
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
394
|
+
)
|
374
395
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
375
396
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
376
397
|
|
377
398
|
test_circuit += tq.gates.H(target_qubit)
|
378
399
|
for i in range(0, n):
|
379
400
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
380
|
-
|
401
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
402
|
+
)
|
381
403
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
382
|
-
|
383
|
-
|
384
|
-
|
404
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
405
|
+
)
|
406
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
407
|
+
z_destab[i, target_qubit],
|
408
|
+
x_destab[i, target_qubit],
|
409
|
+
)
|
385
410
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
386
411
|
|
387
412
|
for k in range(3):
|
388
413
|
test_circuit += tq.gates.S(target_qubit)
|
389
414
|
for i in range(0, n):
|
390
415
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
391
|
-
|
416
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
417
|
+
)
|
392
418
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
393
|
-
|
419
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
420
|
+
)
|
394
421
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
395
422
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
396
423
|
|
397
424
|
test_circuit += tq.gates.H(target_qubit)
|
398
425
|
for i in range(0, n):
|
399
426
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
400
|
-
|
427
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
428
|
+
)
|
401
429
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
402
|
-
|
403
|
-
|
404
|
-
|
430
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
431
|
+
)
|
432
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
433
|
+
z_destab[i, target_qubit],
|
434
|
+
x_destab[i, target_qubit],
|
435
|
+
)
|
405
436
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
406
437
|
|
407
438
|
for k in range(3):
|
408
439
|
test_circuit += tq.gates.S(target_qubit)
|
409
440
|
for i in range(0, n):
|
410
441
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
411
|
-
|
442
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
443
|
+
)
|
412
444
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
413
|
-
|
445
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
446
|
+
)
|
414
447
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
415
448
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
416
449
|
|
@@ -419,95 +452,119 @@ def initial_tableau(circuit, number_of_qubits):
|
|
419
452
|
test_circuit += tq.gates.S(target_qubit)
|
420
453
|
for i in range(0, n):
|
421
454
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
422
|
-
|
455
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
456
|
+
)
|
423
457
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
424
|
-
|
458
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
459
|
+
)
|
425
460
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
426
461
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
427
462
|
|
428
463
|
test_circuit += tq.gates.H(target_qubit)
|
429
464
|
for i in range(0, n):
|
430
465
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
431
|
-
|
466
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
467
|
+
)
|
432
468
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
433
|
-
|
434
|
-
|
435
|
-
|
469
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
470
|
+
)
|
471
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
472
|
+
z_destab[i, target_qubit],
|
473
|
+
x_destab[i, target_qubit],
|
474
|
+
)
|
436
475
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
437
476
|
|
438
477
|
test_circuit += tq.gates.S(target_qubit)
|
439
478
|
for i in range(0, n):
|
440
479
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
441
|
-
|
480
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
481
|
+
)
|
442
482
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
443
|
-
|
483
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
484
|
+
)
|
444
485
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
445
486
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
446
487
|
|
447
488
|
test_circuit += tq.gates.H(target_qubit)
|
448
489
|
for i in range(0, n):
|
449
490
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
450
|
-
|
491
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
492
|
+
)
|
451
493
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
i, target_qubit]
|
494
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
495
|
+
)
|
496
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
497
|
+
z_destab[i, target_qubit],
|
498
|
+
x_destab[i, target_qubit],
|
499
|
+
)
|
500
|
+
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
457
501
|
|
458
502
|
for k in range(3):
|
459
503
|
test_circuit += tq.gates.S(target_qubit)
|
460
504
|
for i in range(0, n):
|
461
505
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
462
|
-
|
506
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
507
|
+
)
|
463
508
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
464
|
-
|
509
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
510
|
+
)
|
465
511
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
466
512
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
467
513
|
|
468
|
-
if U.name ==
|
514
|
+
if U.name == "Phase":
|
469
515
|
target_qubit = U.target[0]
|
470
516
|
test_circuit += tq.gates.S(target_qubit)
|
471
517
|
for i in range(0, n):
|
472
518
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
473
|
-
|
519
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
520
|
+
)
|
474
521
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
475
|
-
|
522
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
523
|
+
)
|
476
524
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
477
525
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
478
526
|
|
479
527
|
# decomposing Rx as H*S^3*H, (we can only use clifford gates S,H,CNOT)
|
480
|
-
if U.name ==
|
528
|
+
if U.name == "Rx":
|
481
529
|
if U.parameter > 0:
|
482
|
-
|
483
530
|
target_qubit = U.target[0]
|
484
531
|
test_circuit += tq.gates.H(target_qubit)
|
485
532
|
for i in range(0, n):
|
486
533
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
487
|
-
|
534
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
535
|
+
)
|
488
536
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
489
|
-
|
490
|
-
|
491
|
-
|
537
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
538
|
+
)
|
539
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
540
|
+
z_destab[i, target_qubit],
|
541
|
+
x_destab[i, target_qubit],
|
542
|
+
)
|
492
543
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
493
544
|
|
494
545
|
test_circuit += tq.gates.S(target_qubit)
|
495
546
|
for i in range(0, n):
|
496
547
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
497
|
-
|
548
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
549
|
+
)
|
498
550
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
499
|
-
|
551
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
552
|
+
)
|
500
553
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
501
554
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
502
555
|
|
503
556
|
test_circuit += tq.gates.H(target_qubit)
|
504
557
|
for i in range(0, n):
|
505
558
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
506
|
-
|
559
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
560
|
+
)
|
507
561
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
508
|
-
|
509
|
-
|
510
|
-
|
562
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
563
|
+
)
|
564
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
565
|
+
z_destab[i, target_qubit],
|
566
|
+
x_destab[i, target_qubit],
|
567
|
+
)
|
511
568
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
512
569
|
|
513
570
|
else:
|
@@ -515,42 +572,54 @@ def initial_tableau(circuit, number_of_qubits):
|
|
515
572
|
test_circuit += tq.gates.H(target_qubit)
|
516
573
|
for i in range(0, n):
|
517
574
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
518
|
-
|
575
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
576
|
+
)
|
519
577
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
520
|
-
|
521
|
-
|
522
|
-
|
578
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
579
|
+
)
|
580
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
581
|
+
z_destab[i, target_qubit],
|
582
|
+
x_destab[i, target_qubit],
|
583
|
+
)
|
523
584
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
524
585
|
|
525
586
|
for j in range(3):
|
526
587
|
test_circuit += tq.gates.S(target_qubit)
|
527
588
|
for i in range(0, n):
|
528
589
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
529
|
-
|
590
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
591
|
+
)
|
530
592
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
531
|
-
|
593
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
594
|
+
)
|
532
595
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
533
596
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
534
597
|
|
535
598
|
test_circuit += tq.gates.H(target_qubit)
|
536
599
|
for i in range(0, n):
|
537
600
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
538
|
-
|
601
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
602
|
+
)
|
539
603
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
540
|
-
|
541
|
-
|
542
|
-
|
604
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
605
|
+
)
|
606
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
607
|
+
z_destab[i, target_qubit],
|
608
|
+
x_destab[i, target_qubit],
|
609
|
+
)
|
543
610
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
544
611
|
|
545
|
-
if U.name ==
|
612
|
+
if U.name == "Rz":
|
546
613
|
if U.parameter > 0:
|
547
614
|
target_qubit = U.target[0]
|
548
615
|
test_circuit += tq.gates.S(target_qubit)
|
549
616
|
for i in range(0, n):
|
550
617
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
551
|
-
|
618
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
619
|
+
)
|
552
620
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
553
|
-
|
621
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
622
|
+
)
|
554
623
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
555
624
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
556
625
|
else:
|
@@ -559,36 +628,43 @@ def initial_tableau(circuit, number_of_qubits):
|
|
559
628
|
test_circuit += tq.gates.S(target_qubit)
|
560
629
|
for i in range(0, n):
|
561
630
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
562
|
-
|
631
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
632
|
+
)
|
563
633
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
564
|
-
|
634
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
635
|
+
)
|
565
636
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
566
637
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
567
638
|
|
568
|
-
if U.name ==
|
569
|
-
|
639
|
+
if U.name == "H":
|
570
640
|
target_qubit = U.target[0]
|
571
641
|
test_circuit += tq.gates.H(target_qubit)
|
572
642
|
for i in range(0, n):
|
573
643
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
574
|
-
|
644
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
645
|
+
)
|
575
646
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
576
|
-
|
577
|
-
|
578
|
-
|
647
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
648
|
+
)
|
649
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
650
|
+
z_destab[i, target_qubit],
|
651
|
+
x_destab[i, target_qubit],
|
652
|
+
)
|
579
653
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
580
654
|
|
581
|
-
if U.name ==
|
655
|
+
if U.name == "X":
|
582
656
|
target_qubit = U.target[0]
|
583
657
|
control_qubit = U.control[0]
|
584
658
|
test_circuit += tq.gates.CNOT(control_qubit, target_qubit)
|
585
659
|
for i in range(0, n):
|
586
660
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
587
|
-
|
588
|
-
|
661
|
+
(int(x_destab[i, control_qubit]) * int(z_destab[i, target_qubit]))
|
662
|
+
* (int(x_destab[i, target_qubit]) ^ int(z_destab[i, control_qubit]) ^ 1)
|
663
|
+
)
|
589
664
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
590
|
-
|
591
|
-
|
665
|
+
(int(x_stab[i, control_qubit]) * int(z_stab[i, target_qubit]))
|
666
|
+
* (int(x_stab[i, target_qubit]) ^ int(z_stab[i, control_qubit]) ^ 1)
|
667
|
+
)
|
592
668
|
x_stab[i, target_qubit] = int(x_stab[i, target_qubit]) ^ int(x_stab[i, control_qubit])
|
593
669
|
x_destab[i, target_qubit] = int(x_destab[i, target_qubit]) ^ int(x_destab[i, control_qubit])
|
594
670
|
z_stab[i, control_qubit] = int(z_stab[i, control_qubit]) ^ int(z_stab[i, target_qubit])
|
@@ -601,13 +677,13 @@ def initial_tableau(circuit, number_of_qubits):
|
|
601
677
|
|
602
678
|
|
603
679
|
def first_round_hadamard(tableau, phase_stabilizer, phase_destabilizer):
|
604
|
-
"""Hadamard gates makes the X stabilizer matrix of the tableau have full rank
|
680
|
+
"""Hadamard gates makes the X stabilizer matrix of the tableau have full rank"""
|
605
681
|
num_qubits = int(len(tableau[0, :]) / 2)
|
606
682
|
circ = []
|
607
683
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
608
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
609
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
610
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
684
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
685
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
686
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
611
687
|
rank = npl.matrix_rank(x_stab)
|
612
688
|
|
613
689
|
if is_canonical(tableau, phase_stabilizer, phase_destabilizer):
|
@@ -633,11 +709,15 @@ def first_round_hadamard(tableau, phase_stabilizer, phase_destabilizer):
|
|
633
709
|
circ.append(tq.gates.H(target=target_qubit))
|
634
710
|
for i in range(0, num_qubits):
|
635
711
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
636
|
-
|
712
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
713
|
+
)
|
637
714
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
638
|
-
|
639
|
-
|
640
|
-
|
715
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
716
|
+
)
|
717
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
718
|
+
z_destab[i, target_qubit],
|
719
|
+
x_destab[i, target_qubit],
|
720
|
+
)
|
641
721
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
642
722
|
destabilizer = np.concatenate((x_destab, z_destab), axis=1)
|
643
723
|
stabilizer = np.concatenate((x_stab, z_stab), axis=1)
|
@@ -654,9 +734,9 @@ def first_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
654
734
|
"""CNOT gates make the X stabilizer matrix the identity matrix"""
|
655
735
|
num_qubits = int(len(tableau[0, :]) / 2)
|
656
736
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
657
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
658
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
659
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
737
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
738
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
739
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
660
740
|
circ = []
|
661
741
|
|
662
742
|
if is_canonical(tableau, phase_stabilizer, phase_destabilizer):
|
@@ -676,16 +756,19 @@ def first_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
676
756
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
677
757
|
for k in range(0, num_qubits):
|
678
758
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
679
|
-
|
680
|
-
|
759
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
760
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
761
|
+
)
|
681
762
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
682
|
-
|
683
|
-
|
763
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
764
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
765
|
+
)
|
684
766
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
685
767
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
686
768
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
687
769
|
z_destab[k, control_qubit] = int(z_destab[k, control_qubit]) ^ int(
|
688
|
-
z_destab[k, target_qubit]
|
770
|
+
z_destab[k, target_qubit]
|
771
|
+
)
|
689
772
|
|
690
773
|
# if one on diagnal guassian elimination on rows below
|
691
774
|
diag_one = 1
|
@@ -697,17 +780,18 @@ def first_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
697
780
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
698
781
|
for k in range(0, num_qubits):
|
699
782
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
700
|
-
|
701
|
-
|
783
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
784
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
785
|
+
)
|
702
786
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
703
|
-
|
704
|
-
|
787
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
788
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
789
|
+
)
|
705
790
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
706
791
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
707
792
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
708
793
|
z_destab[k, control_qubit] = int(z_destab[k, control_qubit]) ^ int(z_destab[k, target_qubit])
|
709
794
|
|
710
|
-
|
711
795
|
# making matrix identity
|
712
796
|
for i in reversed(range(num_qubits)):
|
713
797
|
for j in range(i - 1, -1, -1):
|
@@ -717,11 +801,13 @@ def first_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
717
801
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
718
802
|
for k in range(num_qubits):
|
719
803
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
720
|
-
|
721
|
-
|
804
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
805
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
806
|
+
)
|
722
807
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
723
|
-
|
724
|
-
|
808
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
809
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
810
|
+
)
|
725
811
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
726
812
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
727
813
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
@@ -733,15 +819,14 @@ def first_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
733
819
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
734
820
|
|
735
821
|
|
736
|
-
|
737
822
|
def first_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
738
823
|
"""This phase round adds a diagonal matrix D to the Z stabilizer matrix such that Z + D = M*M' for some
|
739
824
|
invertible M"""
|
740
825
|
num_qubits = int(len(tableau[0, :]) / 2)
|
741
826
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
742
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
743
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
744
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
827
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
828
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
829
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
745
830
|
matrix = copy.deepcopy(z_stab)
|
746
831
|
M = np.identity(num_qubits)
|
747
832
|
circ = []
|
@@ -773,9 +858,11 @@ def first_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
773
858
|
circ.append(tq.gates.S(target=target_qubit))
|
774
859
|
for i in range(0, num_qubits):
|
775
860
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
776
|
-
|
861
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
862
|
+
)
|
777
863
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
778
|
-
|
864
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
865
|
+
)
|
779
866
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
780
867
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
781
868
|
destabilizer = np.concatenate((x_destab, z_destab), axis=1)
|
@@ -784,14 +871,13 @@ def first_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
784
871
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
785
872
|
|
786
873
|
|
787
|
-
|
788
874
|
def second_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
789
|
-
"""performs a cholesky decompostion of the symmetric Z = D + M*M' stabilizer matrix
|
875
|
+
"""performs a cholesky decompostion of the symmetric Z = D + M*M' stabilizer matrix"""
|
790
876
|
num_qubits = int(len(tableau[0, :]) / 2)
|
791
877
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
792
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
793
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
794
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
878
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
879
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
880
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
795
881
|
matrix = copy.deepcopy(z_stab)
|
796
882
|
circ = []
|
797
883
|
|
@@ -820,11 +906,13 @@ def second_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
820
906
|
if control_qubit != target_qubit:
|
821
907
|
for l in range(0, num_qubits):
|
822
908
|
phase_destabilizer[l] = int(phase_destabilizer[l]) ^ (
|
823
|
-
|
824
|
-
|
909
|
+
(int(x_destab[l, control_qubit]) * int(z_destab[l, target_qubit]))
|
910
|
+
* (int(x_destab[l, target_qubit]) ^ int(z_destab[l, control_qubit]) ^ 1)
|
911
|
+
)
|
825
912
|
phase_stabilizer[l] = int(phase_stabilizer[l]) ^ (
|
826
|
-
|
827
|
-
|
913
|
+
(int(x_stab[l, control_qubit]) * int(z_stab[l, target_qubit]))
|
914
|
+
* (int(x_stab[l, target_qubit]) ^ int(z_stab[l, control_qubit]) ^ 1)
|
915
|
+
)
|
828
916
|
x_stab[l, target_qubit] = int(x_stab[l, target_qubit]) ^ int(x_stab[l, control_qubit])
|
829
917
|
x_destab[l, target_qubit] = int(x_destab[l, target_qubit]) ^ int(x_destab[l, control_qubit])
|
830
918
|
z_stab[l, control_qubit] = int(z_stab[l, control_qubit]) ^ int(z_stab[l, target_qubit])
|
@@ -838,15 +926,14 @@ def second_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
838
926
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
839
927
|
|
840
928
|
|
841
|
-
|
842
929
|
def second_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
843
930
|
"""phase on all the qubits eliminates the Z_stabilizer to the Zero Matrix, additional phases set all the stabilizer
|
844
931
|
phase bits to zero"""
|
845
932
|
num_qubits = int(len(tableau[0, :]) / 2)
|
846
933
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
847
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
848
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
849
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
934
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
935
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
936
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
850
937
|
bits_to_flip = []
|
851
938
|
circ = []
|
852
939
|
|
@@ -859,9 +946,11 @@ def second_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
859
946
|
circ.append(tq.gates.S(target_qubit))
|
860
947
|
for i in range(num_qubits):
|
861
948
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
862
|
-
|
949
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
950
|
+
)
|
863
951
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
864
|
-
|
952
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
953
|
+
)
|
865
954
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
866
955
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
867
956
|
# zeroing out remaining stabilizer phase bits
|
@@ -876,9 +965,11 @@ def second_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
876
965
|
circ.append(tq.gates.S(target_qubit))
|
877
966
|
for k in range(num_qubits):
|
878
967
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
879
|
-
|
968
|
+
int(x_destab[k, target_qubit]) * int(z_destab[k, target_qubit])
|
969
|
+
)
|
880
970
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
881
|
-
|
971
|
+
int(x_stab[k, target_qubit]) * int(z_stab[k, target_qubit])
|
972
|
+
)
|
882
973
|
z_stab[k, target_qubit] = int(z_stab[k, target_qubit]) ^ int(x_stab[k, target_qubit])
|
883
974
|
z_destab[k, target_qubit] = int(z_destab[k, target_qubit]) ^ int(x_destab[k, target_qubit])
|
884
975
|
destabilizer = np.concatenate((x_destab, z_destab), axis=1)
|
@@ -891,9 +982,9 @@ def third_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
891
982
|
"""CNOT gates make the X stabilizer matrix the identity matrix"""
|
892
983
|
num_qubits = int(len(tableau[0, :]) / 2)
|
893
984
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
894
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
895
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
896
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
985
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
986
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
987
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
897
988
|
circ = []
|
898
989
|
|
899
990
|
if is_canonical(tableau, phase_stabilizer, phase_destabilizer):
|
@@ -909,11 +1000,13 @@ def third_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
909
1000
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
910
1001
|
for k in range(0, num_qubits):
|
911
1002
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
912
|
-
|
913
|
-
|
1003
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
1004
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
1005
|
+
)
|
914
1006
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
915
|
-
|
916
|
-
|
1007
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
1008
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
1009
|
+
)
|
917
1010
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
918
1011
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
919
1012
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
@@ -925,14 +1018,13 @@ def third_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
925
1018
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
926
1019
|
|
927
1020
|
|
928
|
-
|
929
1021
|
def second_round_hadamard(tableau, phase_stabilizer, phase_destabilizer):
|
930
|
-
""""Apply Hadmard on all the bits puts the stabilizer matrix into canonical form"""
|
1022
|
+
""" "Apply Hadmard on all the bits puts the stabilizer matrix into canonical form"""
|
931
1023
|
num_qubits = int(len(tableau[0, :]) / 2)
|
932
1024
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
933
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
934
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
935
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
1025
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
1026
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
1027
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
936
1028
|
bits_to_flip = []
|
937
1029
|
circ = []
|
938
1030
|
|
@@ -945,11 +1037,15 @@ def second_round_hadamard(tableau, phase_stabilizer, phase_destabilizer):
|
|
945
1037
|
circ.append(tq.gates.H(target=target_qubit))
|
946
1038
|
for i in range(0, num_qubits):
|
947
1039
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
948
|
-
|
1040
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
1041
|
+
)
|
949
1042
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
950
|
-
|
951
|
-
|
952
|
-
|
1043
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
1044
|
+
)
|
1045
|
+
x_destab[i, target_qubit], z_destab[i, target_qubit] = (
|
1046
|
+
z_destab[i, target_qubit],
|
1047
|
+
x_destab[i, target_qubit],
|
1048
|
+
)
|
953
1049
|
z_stab[i, target_qubit], x_stab[i, target_qubit] = x_stab[i, target_qubit], z_stab[i, target_qubit]
|
954
1050
|
destabilizer = np.concatenate((x_destab, z_destab), axis=1)
|
955
1051
|
stabilizer = np.concatenate((x_stab, z_stab), axis=1)
|
@@ -957,14 +1053,13 @@ def second_round_hadamard(tableau, phase_stabilizer, phase_destabilizer):
|
|
957
1053
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
958
1054
|
|
959
1055
|
|
960
|
-
|
961
1056
|
def third_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
962
1057
|
"""Adds a diagonal matrix to the Z destabilizer matrix such that Zd + D = M*M' for some invertible M"""
|
963
1058
|
num_qubits = int(len(tableau[0, :]) / 2)
|
964
1059
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
965
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
966
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
967
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
1060
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
1061
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
1062
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
968
1063
|
matrix = copy.deepcopy(z_destab)
|
969
1064
|
M = np.identity(num_qubits)
|
970
1065
|
circ = []
|
@@ -995,9 +1090,11 @@ def third_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
995
1090
|
circ.append(tq.gates.S(target=target_qubit))
|
996
1091
|
for i in range(0, num_qubits):
|
997
1092
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
998
|
-
|
1093
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
1094
|
+
)
|
999
1095
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
1000
|
-
|
1096
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
1097
|
+
)
|
1001
1098
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
1002
1099
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
1003
1100
|
destabilizer = np.concatenate((x_destab, z_destab), axis=1)
|
@@ -1006,14 +1103,13 @@ def third_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
1006
1103
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
1007
1104
|
|
1008
1105
|
|
1009
|
-
|
1010
1106
|
def fourth_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
1011
|
-
""""Performs a binary cholesky decomposition on the Z destabilizer matrix"""
|
1107
|
+
""" "Performs a binary cholesky decomposition on the Z destabilizer matrix"""
|
1012
1108
|
num_qubits = int(len(tableau[0, :]) / 2)
|
1013
1109
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
1014
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
1015
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
1016
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
1110
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
1111
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
1112
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
1017
1113
|
matrix = copy.deepcopy(z_destab)
|
1018
1114
|
M = np.identity(num_qubits)
|
1019
1115
|
circ = []
|
@@ -1041,11 +1137,13 @@ def fourth_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1041
1137
|
if control_qubit != target_qubit:
|
1042
1138
|
for l in range(0, num_qubits):
|
1043
1139
|
phase_destabilizer[l] = int(phase_destabilizer[l]) ^ (
|
1044
|
-
|
1045
|
-
|
1140
|
+
(int(x_destab[l, control_qubit]) * int(z_destab[l, target_qubit]))
|
1141
|
+
* (int(x_destab[l, target_qubit]) ^ int(z_destab[l, control_qubit]) ^ 1)
|
1142
|
+
)
|
1046
1143
|
phase_stabilizer[l] = int(phase_stabilizer[l]) ^ (
|
1047
|
-
|
1048
|
-
|
1144
|
+
(int(x_stab[l, control_qubit]) * int(z_stab[l, target_qubit]))
|
1145
|
+
* (int(x_stab[l, target_qubit]) ^ int(z_stab[l, control_qubit]) ^ 1)
|
1146
|
+
)
|
1049
1147
|
x_stab[l, target_qubit] = int(x_stab[l, target_qubit]) ^ int(x_stab[l, control_qubit])
|
1050
1148
|
x_destab[l, target_qubit] = int(x_destab[l, target_qubit]) ^ int(x_destab[l, control_qubit])
|
1051
1149
|
z_stab[l, control_qubit] = int(z_stab[l, control_qubit]) ^ int(z_stab[l, target_qubit])
|
@@ -1059,15 +1157,14 @@ def fourth_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1059
1157
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
1060
1158
|
|
1061
1159
|
|
1062
|
-
|
1063
1160
|
def fourth_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
1064
|
-
""""Phase gates make the Z destabilizer the Zero matrix, additional phases set all the destabilizer
|
1161
|
+
""" "Phase gates make the Z destabilizer the Zero matrix, additional phases set all the destabilizer
|
1065
1162
|
phase bits to 0"""
|
1066
1163
|
num_qubits = int(len(tableau[0, :]) / 2)
|
1067
1164
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
1068
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
1069
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
1070
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
1165
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
1166
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
1167
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
1071
1168
|
bits_to_flip = []
|
1072
1169
|
circ = []
|
1073
1170
|
|
@@ -1081,9 +1178,11 @@ def fourth_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
1081
1178
|
circ.append(tq.gates.S(target_qubit))
|
1082
1179
|
for i in range(num_qubits):
|
1083
1180
|
phase_destabilizer[i] = int(phase_destabilizer[i]) ^ (
|
1084
|
-
|
1181
|
+
int(x_destab[i, target_qubit]) * int(z_destab[i, target_qubit])
|
1182
|
+
)
|
1085
1183
|
phase_stabilizer[i] = int(phase_stabilizer[i]) ^ (
|
1086
|
-
|
1184
|
+
int(x_stab[i, target_qubit]) * int(z_stab[i, target_qubit])
|
1185
|
+
)
|
1087
1186
|
z_stab[i, target_qubit] = int(z_stab[i, target_qubit]) ^ int(x_stab[i, target_qubit])
|
1088
1187
|
z_destab[i, target_qubit] = int(z_destab[i, target_qubit]) ^ int(x_destab[i, target_qubit])
|
1089
1188
|
|
@@ -1098,9 +1197,11 @@ def fourth_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
1098
1197
|
circ.append(tq.gates.S(target_qubit))
|
1099
1198
|
for k in range(num_qubits):
|
1100
1199
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
1101
|
-
|
1200
|
+
int(x_destab[k, target_qubit]) * int(z_destab[k, target_qubit])
|
1201
|
+
)
|
1102
1202
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
1103
|
-
|
1203
|
+
int(x_stab[k, target_qubit]) * int(z_stab[k, target_qubit])
|
1204
|
+
)
|
1104
1205
|
z_stab[k, target_qubit] = int(z_stab[k, target_qubit]) ^ int(x_stab[k, target_qubit])
|
1105
1206
|
z_destab[k, target_qubit] = int(z_destab[k, target_qubit]) ^ int(x_destab[k, target_qubit])
|
1106
1207
|
|
@@ -1110,15 +1211,14 @@ def fourth_round_phase(tableau, phase_stabilizer, phase_destabilizer):
|
|
1110
1211
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
1111
1212
|
|
1112
1213
|
|
1113
|
-
|
1114
1214
|
def final_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
1115
1215
|
"""Final round of CNOT gates puts the Tableau into canonical form: a 2n X 2n identity matrix with all phase
|
1116
1216
|
bits zero"""
|
1117
1217
|
num_qubits = int(len(tableau[0, :]) / 2)
|
1118
1218
|
x_destab = tableau[0:num_qubits, 0:num_qubits]
|
1119
|
-
z_destab = tableau[0:num_qubits, num_qubits:2 * num_qubits]
|
1120
|
-
z_stab = tableau[num_qubits:2 * num_qubits, num_qubits:2 * num_qubits]
|
1121
|
-
x_stab = tableau[num_qubits:2 * num_qubits, 0:num_qubits]
|
1219
|
+
z_destab = tableau[0:num_qubits, num_qubits : 2 * num_qubits]
|
1220
|
+
z_stab = tableau[num_qubits : 2 * num_qubits, num_qubits : 2 * num_qubits]
|
1221
|
+
x_stab = tableau[num_qubits : 2 * num_qubits, 0:num_qubits]
|
1122
1222
|
circ = []
|
1123
1223
|
|
1124
1224
|
if is_canonical(tableau, phase_stabilizer, phase_destabilizer):
|
@@ -1132,11 +1232,13 @@ def final_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1132
1232
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
1133
1233
|
for k in range(0, num_qubits):
|
1134
1234
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
1135
|
-
|
1136
|
-
|
1235
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
1236
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
1237
|
+
)
|
1137
1238
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
1138
|
-
|
1139
|
-
|
1239
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
1240
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
1241
|
+
)
|
1140
1242
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
1141
1243
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
1142
1244
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
@@ -1147,17 +1249,18 @@ def final_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1147
1249
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
1148
1250
|
for k in range(0, num_qubits):
|
1149
1251
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
1150
|
-
|
1151
|
-
|
1252
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
1253
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
1254
|
+
)
|
1152
1255
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
1153
|
-
|
1154
|
-
|
1256
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
1257
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
1258
|
+
)
|
1155
1259
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
1156
1260
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
1157
1261
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
1158
1262
|
z_destab[k, control_qubit] = int(z_destab[k, control_qubit]) ^ int(z_destab[k, target_qubit])
|
1159
1263
|
|
1160
|
-
|
1161
1264
|
if x_destab[i, i] == 1:
|
1162
1265
|
ones = np.where(x_destab[i, :] == 1)[0]
|
1163
1266
|
control_qubit = i
|
@@ -1167,11 +1270,13 @@ def final_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1167
1270
|
circ.append(tq.gates.CNOT(control_qubit, target_qubit))
|
1168
1271
|
for k in range(0, num_qubits):
|
1169
1272
|
phase_destabilizer[k] = int(phase_destabilizer[k]) ^ (
|
1170
|
-
|
1171
|
-
|
1273
|
+
(int(x_destab[k, control_qubit]) * int(z_destab[k, target_qubit]))
|
1274
|
+
* (int(x_destab[k, target_qubit]) ^ int(z_destab[k, control_qubit]) ^ 1)
|
1275
|
+
)
|
1172
1276
|
phase_stabilizer[k] = int(phase_stabilizer[k]) ^ (
|
1173
|
-
|
1174
|
-
|
1277
|
+
(int(x_stab[k, control_qubit]) * int(z_stab[k, target_qubit]))
|
1278
|
+
* (int(x_stab[k, target_qubit]) ^ int(z_stab[k, control_qubit]) ^ 1)
|
1279
|
+
)
|
1175
1280
|
x_stab[k, target_qubit] = int(x_stab[k, target_qubit]) ^ int(x_stab[k, control_qubit])
|
1176
1281
|
x_destab[k, target_qubit] = int(x_destab[k, target_qubit]) ^ int(x_destab[k, control_qubit])
|
1177
1282
|
z_stab[k, control_qubit] = int(z_stab[k, control_qubit]) ^ int(z_stab[k, target_qubit])
|
@@ -1182,7 +1287,6 @@ def final_round_cnot(tableau, phase_stabilizer, phase_destabilizer):
|
|
1182
1287
|
return (tableau, phase_stabilizer, phase_destabilizer, circ)
|
1183
1288
|
|
1184
1289
|
|
1185
|
-
|
1186
1290
|
#
|
1187
1291
|
def REF_binary(matrix):
|
1188
1292
|
A = matrix
|
@@ -1210,7 +1314,7 @@ def REF_binary(matrix):
|
|
1210
1314
|
for i in range(current_row, n_rows):
|
1211
1315
|
if A[i, j] == 1:
|
1212
1316
|
A[i] = (A[i] + A[pivot_row]) % 2
|
1213
|
-
return
|
1317
|
+
return A
|
1214
1318
|
|
1215
1319
|
|
1216
1320
|
#
|