Sequential Quantum Gate Decomposer  v1.9.3
Powerful decomposition of general unitarias into one- and two-qubit gates gates
example_CH_general_unitary.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 """
3 Created on Fri Jun 26 14:42:56 2020
4 Copyright 2020 Peter Rakyta, Ph.D.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 @author: Peter Rakyta, Ph.D.
19 """
20 
22 
23 from squander import N_Qubit_Decomposition
24 from squander import Circuit
25 
26 # cerate unitary q-bit matrix
27 from scipy.stats import unitary_group
28 from squander import utils
29 import numpy as np
30 
31 
32 
33 
35  # creating an instance of the wrapper class Circuit
36  Circuit_ret = Circuit( qbit_num )
37 
38  disentangle_qbit = qbit_num - 1
39 
40  for qbit in range(0, disentangle_qbit ):
41 
42  # creating an instance of the wrapper class Circuit
43  layer = Circuit( qbit_num )
44 
45 
46  # add U3 fate to the block
47  Theta = True
48  Phi = False
49  Lambda = True
50  layer.add_U3( qbit, Theta, Phi, Lambda )
51  layer.add_U3( disentangle_qbit, Theta, Phi, Lambda )
52 
53 
54  # Connecting every second target qubit with CNOT gate, and use CH gate otherwise
55  if ( qbit % 2 == 0 ):
56  # add CH gate to the block
57  layer.add_CH( qbit, disentangle_qbit )
58  else:
59  # add CNOT gate to the block
60  layer.add_CNOT( qbit, disentangle_qbit )
61 
62 
63 
64  Circuit_ret.add_Circuit( layer )
65 
66  return Circuit_ret
67 
68 
69 
70 
71 
72 # the number of qubits spanning the unitary
73 qbit_num = 2
74 
75 # determine the soze of the unitary to be decomposed
76 matrix_size = int(2**qbit_num)
77 
78 # creating a random unitary to be decomposed
79 Umtx = unitary_group.rvs(matrix_size)
80 
81 # creating an instance of the C++ class
82 decomp = N_Qubit_Decomposition( Umtx.conj().T )
83 
84 
85 # create custom gate structure
87 
88 
89 # adding custom gate structure to the decomposition
90 decomp.set_Gate_Structure( gate_structure )
91 
92 # set the number of block to be optimized in one shot
93 decomp.set_Optimization_Blocks( 20 )
94 
95 # starting the decomposition
96 decomp.Start_Decomposition()
97 
98 # get the decomposing operations
99 quantum_circuit = decomp.get_Qiskit_Circuit()
100 
101 
102 # print the quantum circuit
103 print(quantum_circuit)
104 
105 import numpy.linalg as LA
106 
107 # the unitary matrix from the result object
108 decomposed_matrix = utils.get_unitary_from_qiskit_circuit( quantum_circuit )
109 product_matrix = np.dot(Umtx,decomposed_matrix.conj().T)
110 phase = np.angle(product_matrix[0,0])
111 product_matrix = product_matrix*np.exp(-1j*phase)
112 
113 product_matrix = np.eye(matrix_size)*2 - product_matrix - product_matrix.conj().T
114 # the error of the decomposition
115 decomposition_error = (np.real(np.trace(product_matrix)))/2
116 
117 print('The error of the decomposition is ' + str(decomposition_error))
118 
119 from qiskit import visualization
120 visualization.circuit_drawer(quantum_circuit, output="latex_source", interactive=True, filename="cirquit_export", fold=10)
121 
122