3 Created on Fri Jun 26 14:42:56 2020 4 Copyright 2020 Peter Rakyta, Ph.D. 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 10 http://www.apache.org/licenses/LICENSE-2.0 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. 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see http://www.gnu.org/licenses/. 21 @author: Peter Rakyta, Ph.D. 26 from squander
import Circuit
28 from squander.partitioning.partition
import PartitionCircuit
36 np.set_printoptions(linewidth=200)
46 random_initial_state =
True 51 execution_times_squander = {}
52 transformed_states_squander = {}
53 parameters_squander = {}
54 initial_state_squander = {}
56 for qbit_num
in range(qbit_num_min, qbit_num_max+1, 1):
59 matrix_size = 1 << qbit_num
61 if (random_initial_state ) :
62 initial_state_real = np.random.uniform(-1.0,1.0, (matrix_size,) )
63 initial_state_imag = np.random.uniform(-1.0,1.0, (matrix_size,) )
64 initial_state = initial_state_real + initial_state_imag*1j
65 initial_state = initial_state/np.linalg.norm(initial_state)
67 initial_state = np.zeros( (matrix_size), dtype=np.complex128 )
68 initial_state[0] = 1.0 + 0j
70 initial_state_squander[ qbit_num ] = initial_state.copy()
74 circuit_squander = Circuit( qbit_num )
77 for level
in range(levels):
80 for control_qbit
in range(qbit_num-1):
81 for target_qbit
in range(control_qbit+1, qbit_num):
83 circuit_squander.add_U3(target_qbit)
84 circuit_squander.add_U3(control_qbit)
86 circuit_squander.add_CRY( target_qbit=target_qbit, control_qbit=control_qbit )
87 gates_num = gates_num + 3
89 for target_qbit
in range(qbit_num):
90 circuit_squander.add_U3(target_qbit)
91 gates_num = gates_num + 1
96 num_of_parameters = circuit_squander.get_Parameter_Num()
100 parameters = np.random.rand(num_of_parameters)*2*np.pi
102 partitioned_circuit_squander, parameters_reordered, L =
PartitionCircuit(circuit_squander, parameters, 5,
"ilp-fusion")
107 partitioned_circuit_squander.set_min_fusion(14)
110 partitioned_circuit_squander.apply_to( parameters_reordered, initial_state )
111 t_SQUANDER = time.time() - t0
112 print(
"Time elapsed SQUANDER: ", t_SQUANDER,
" seconds at qbit_num = ", qbit_num,
' number of gates: ', gates_num )
114 execution_times_squander[ qbit_num ] = t_SQUANDER
115 transformed_states_squander[ qbit_num ] = np.reshape(initial_state, (initial_state.size,) )
116 parameters_squander[ qbit_num ] = parameters
119 print(
"SQUANDER execution times [s]:")
120 print( execution_times_squander )
126 execution_times_qiskit = {}
127 transformed_states_qiskit = {}
131 qiskit_version = qiskit.version.get_version_info()
133 from qiskit
import QuantumCircuit
134 import qiskit_aer
as Aer
136 if qiskit_version[0] ==
'1' or qiskit_version[0] ==
'2':
137 from qiskit
import transpile
138 elif qiskit_version[0] ==
'0':
139 from qiskit
import execute
144 for qbit_num
in range(qbit_num_min, qbit_num_max+1, 1):
147 matrix_size = 1 << qbit_num
149 initial_state = initial_state_squander[ qbit_num ]
151 parameters = parameters_squander[ qbit_num ]
157 circuit_qiskit = QuantumCircuit(qbit_num)
159 if random_initial_state:
160 circuit_qiskit.initialize( initial_state )
162 for level
in range(levels):
165 for control_qbit
in range(qbit_num-1):
166 for target_qbit
in range(control_qbit+1, qbit_num):
168 circuit_qiskit.u(parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2], target_qbit )
169 parameter_idx = parameter_idx+3
170 circuit_qiskit.u(parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2], control_qbit )
171 parameter_idx = parameter_idx+3
173 circuit_qiskit.cry( parameters[parameter_idx]*2, control_qbit, target_qbit )
174 parameter_idx = parameter_idx+1
176 for target_qbit
in range(qbit_num):
177 circuit_qiskit.u(parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2], target_qbit )
178 parameter_idx = parameter_idx+3
188 if qiskit_version[0] ==
'1' or qiskit_version[0] ==
'2':
190 circuit_qiskit.save_statevector()
192 backend = Aer.AerSimulator(method=
'statevector')
193 compiled_circuit = transpile(circuit_qiskit, backend)
194 result = backend.run(compiled_circuit).
result()
196 transformed_state = result.get_statevector(compiled_circuit)
199 elif qiskit_version[0] ==
'0':
202 simulator = Aer.get_backend(
'statevector_simulator')
204 backend = Aer.get_backend(
'aer_simulator')
205 result = execute(circuit_qiskit, simulator).
result()
207 transformed_state = result.get_statevector(circuit_qiskit)
211 t_qiskit = time.time() - t0
214 execution_times_qiskit[ qbit_num ] = t_qiskit
215 transformed_states_qiskit[ qbit_num ] = np.array(transformed_state)
217 print(
"QISKIT execution times [s]:")
218 print( execution_times_qiskit )
221 from qulacs
import Observable, QuantumCircuit, QuantumState
224 execution_times_qulacs = {}
225 transformed_states_qulacs = {}
228 for qbit_num
in range(qbit_num_min, qbit_num_max+1, 1):
231 matrix_size = 1 << qbit_num
233 initial_state = initial_state_squander[ qbit_num ]
235 parameters = parameters_squander[ qbit_num ]
241 state = QuantumState(qbit_num)
242 state.load( initial_state )
244 circuit_qulacs = QuantumCircuit(qbit_num)
246 for level
in range(levels):
249 for control_qbit
in range(qbit_num-1):
250 for target_qbit
in range(control_qbit+1, qbit_num):
252 circuit_qulacs.add_U3_gate(target_qbit, parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2] )
253 parameter_idx = parameter_idx+3
254 circuit_qulacs.add_U3_gate( control_qbit, parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2] )
255 parameter_idx = parameter_idx+3
259 RY_gate = qulacs.gate.RotY( target_qbit, parameters[parameter_idx]*2 )
260 RY_gate = qulacs.gate.to_matrix_gate( RY_gate )
261 RY_gate.add_control_qubit( control_qbit, 1)
262 circuit_qulacs.add_gate( RY_gate )
264 parameter_idx = parameter_idx+1
267 for target_qbit
in range(qbit_num):
268 circuit_qulacs.add_U3_gate( target_qbit, parameters[parameter_idx]*2, parameters[parameter_idx+1], parameters[parameter_idx+2] )
269 parameter_idx = parameter_idx+3
275 circuit_qulacs.update_quantum_state( state )
276 transformed_state = state.get_vector()
277 t_qulacs = time.time() - t0
280 execution_times_qulacs[ qbit_num ] = t_qulacs
281 transformed_states_qulacs[ qbit_num ] = np.array(transformed_state)
283 print(
"Qulacs execution times [s]:")
284 print( execution_times_qulacs )
288 print(
"Difference between the transformed state vectors:")
290 keys = transformed_states_qiskit.keys()
291 for qbit_num
in keys:
292 state_squander = transformed_states_squander[ qbit_num ]
293 state_qiskit = transformed_states_qiskit[ qbit_num ]
294 state_qulacs = transformed_states_qulacs[ qbit_num ]
296 print(
"Squander vs QISKIT: ", np.linalg.norm( state_squander-state_qiskit ) )
297 print(
"Squander vs Qulacs: ", np.linalg.norm( state_squander-state_qulacs ) )