Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
qgd_Circuit.py
Go to the documentation of this file.
1 
3 """
4 Created on Tue Jun 30 15:44:26 2020
5 Copyright 2020 Peter Rakyta, Ph.D.
6 
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10 
11  http://www.apache.org/licenses/LICENSE-2.0
12 
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions andP
17 limitations under the License.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see http://www.gnu.org/licenses/.
21 
22 @author: Peter Rakyta, Ph.D.
23 """
24 
25 """A Python interface class representing Squander circuit."""
26 
27 
28 import numpy as np
29 from squander.gates.qgd_Circuit_Wrapper import qgd_Circuit_Wrapper
30 
31 
32 from squander.gates.gates_Wrapper import (
33  U1,
34  U2,
35  U3,
36  H,
37  X,
38  Y,
39  Z,
40  S,
41  Sdg,
42  T,
43  Tdg,
44  CH,
45  CNOT,
46  CZ,
47  R,
48  RX,
49  RY,
50  RZ,
51  SX,
52  SYC,
53  CRY,
54  CRZ,
55  CRX,
56  CP,
57  CU,
58  CR,
59  CROT,
60  SXdg,
61  CCX,
62  CSWAP,
63  SWAP,
64  RXX,
65  RYY,
66  RZZ,
67 )
68 
69 
70 class qgd_Circuit(qgd_Circuit_Wrapper):
71  """A QGD Python interface class for the Gates_Block."""
72 
73  def __init__(self, qbit_num):
74  """Constructor of the class.
75 
76  Args:
77  qbit_num: The number of qubits spanning the operations
78  """
79 
80  # call the constructor of the wrapper class
81  super().__init__(qbit_num)
82 
83  def add_U1(self, target_qbit):
84  """Add a U1 gate to the front of the gate structure.
85 
86  Args:
87  target_qbit: Target qubit index (int)
88  """
89 
90  # call the C wrapper function
91  super().add_U1(target_qbit)
92 
93  def add_U2(self, target_qbit):
94  """Add a U2 gate to the front of the gate structure.
95 
96  Args:
97  target_qbit: Target qubit index (int)
98  """
99 
100  # call the C wrapper function
101  super().add_U2(target_qbit)
102 
103  def add_U3(self, target_qbit):
104  """Add a U3 gate to the front of the gate structure.
105 
106  Args:
107  target_qbit: Target qubit index (int)
108  """
109 
110  # call the C wrapper function
111  super().add_U3(target_qbit)
112 
113  def add_RX(self, target_qbit):
114  """Add a RX gate to the front of the gate structure.
115 
116  Args:
117  target_qbit: Target qubit index (int)
118  """
119 
120  # call the C wrapper function
121  super().add_RX(target_qbit)
122 
123  def add_R(self, target_qbit):
124  """Add a R gate to the front of the gate structure.
125 
126  Args:
127  target_qbit: Target qubit index (int)
128  """
129 
130  # call the C wrapper function
131  super().add_R(target_qbit)
132 
133  def add_RY(self, target_qbit):
134  """Add a RY gate to the front of the gate structure.
135 
136  Args:
137  target_qbit: Target qubit index (int)
138  """
139 
140  # call the C wrapper function
141  super().add_RY(target_qbit)
142 
143  def add_RZ(self, target_qbit):
144  """Add a RZ gate to the front of the gate structure.
145 
146  Args:
147  target_qbit: Target qubit index (int)
148  """
149 
150  # call the C wrapper function
151  super().add_RZ(target_qbit)
152 
153  def add_CNOT(self, target_qbit, control_qbit):
154  """Add a CNOT gate to the front of the gate structure.
155 
156  Args:
157  target_qbit: Target qubit index (int)
158  control_qbit: Control qubit index (int)
159  """
160 
161  # call the C wrapper function
162  super().add_CNOT(target_qbit, control_qbit)
163 
164  def add_CZ(self, target_qbit, control_qbit):
165  """Add a CZ gate to the front of the gate structure.
166 
167  Args:
168  target_qbit: Target qubit index (int)
169  control_qbit: Control qubit index (int)
170  """
171 
172  # call the C wrapper function
173  super().add_CZ(target_qbit, control_qbit)
174 
175  def add_CH(self, target_qbit, control_qbit):
176  """Add a CH gate to the front of the gate structure.
177 
178  Args:
179  target_qbit: Target qubit index (int)
180  control_qbit: Control qubit index (int)
181  """
182 
183  # call the C wrapper function
184  super().add_CH(target_qbit, control_qbit)
185 
186  def add_CU(self, target_qbit, control_qbit):
187  """Add a CU gate to the front of the gate structure.
188 
189  Args:
190  target_qbit: Target qubit index (int)
191  control_qbit: Control qubit index (int)
192  """
193 
194  # call the C wrapper function
195  super().add_CU(target_qbit, control_qbit)
196 
197  def add_SYC(self, target_qbit, control_qbit):
198  """Add a SYC gate to the front of the gate structure.
199 
200  Args:
201  target_qbit: Target qubit index (int)
202  control_qbit: Control qubit index (int)
203  """
204 
205  # call the C wrapper function
206  super().add_SYC(target_qbit, control_qbit)
207 
208  def add_H(self, target_qbit):
209  """Add a Hadamard gate to the front of the gate structure.
210 
211  Args:
212  target_qbit: Target qubit index (int)
213  """
214 
215  # call the C wrapper function
216  super().add_H(target_qbit)
217 
218  def add_X(self, target_qbit):
219  """Add a X gate to the front of the gate structure.
220 
221  Args:
222  target_qbit: Target qubit index (int)
223  """
224 
225  # call the C wrapper function
226  super().add_X(target_qbit)
227 
228  def add_Y(self, target_qbit):
229  """Add a Y gate to the front of the gate structure.
230 
231  Args:
232  target_qbit: Target qubit index (int)
233  """
234 
235  # call the C wrapper functionerror
236  super().add_Y(target_qbit)
237 
238  def add_Z(self, target_qbit):
239  """Add a Z gate to the front of the gate structure.
240 
241  Args:
242  target_qbit: Target qubit index (int)
243  """
244 
245  # call the C wrapper function
246  super().add_Z(target_qbit)
247 
248  def add_SX(self, target_qbit):
249  """Add a SX gate to the front of the gate structure.
250 
251  Args:
252  target_qbit: Target qubit index (int)
253  """
254 
255  # call the C wrapper function
256  super().add_SX(target_qbit)
257 
258  def add_SXdg(self, target_qbit):
259  """Add a SXdg gate to the front of the gate structure.
260 
261  Args:
262  target_qbit: Target qubit index (int)
263  """
264 
265  # call the C wrapper function
266  super().add_SXdg(target_qbit)
267 
268  def add_S(self, target_qbit):
269  """Add a S gate to the front of the gate structure.
270 
271  Args:
272  target_qbit: Target qubit index (int)
273  """
274 
275  # call the C wrapper function
276  super().add_S(target_qbit)
277 
278  def add_Sdg(self, target_qbit):
279  """Add a Sdg gate to the front of the gate structure.
280 
281  Args:
282  target_qbit: Target qubit index (int)
283  """
284 
285  # call the C wrapper function
286  super().add_Sdg(target_qbit)
287 
288  def add_T(self, target_qbit):
289  """Add a T gate to the front of the gate structure.
290 
291  Args:
292  target_qbit: Target qubit index (int)
293  """
294 
295  # call the C wrapper function
296  super().add_T(target_qbit)
297 
298  def add_Tdg(self, target_qbit):
299  """Add a Tdg gate to the front of the gate structure.
300 
301  Args:
302  target_qbit: Target qubit index (int)
303  """
304 
305  # call the C wrapper function
306  super().add_Tdg(target_qbit)
307 
308  def add_adaptive(self, target_qbit, control_qbit):
309  """Add an adaptive gate to the front of the gate structure.
310 
311  Args:
312  target_qbit: Target qubit index (int)
313  control_qbit: Control qubit index (int)
314  """
315 
316  # call the C wrapper function
317  super().add_adaptive(target_qbit, control_qbit)
318 
319  def add_CROT(self, target_qbit, control_qbit):
320  """Add a CROT gate to the front of the gate structure.
321 
322  Args:
323  target_qbit: Target qubit index (int)
324  control_qbit: Control qubit index (int)
325  """
326 
327  # call the C wrapper function
328  super(qgd_Circuit, self).add_CROT(target_qbit, control_qbit)
329 
330  def add_CR(self, target_qbit, control_qbit):
331  """Add a CR gate to the front of the gate structure.
332 
333  Args:
334  target_qbit: Target qubit index (int)
335  control_qbit: Control qubit index (int)
336  """
337 
338  # call the C wrapper function
339  super(qgd_Circuit, self).add_CR(target_qbit, control_qbit)
340 
341  def add_CRY(self, target_qbit, control_qbit):
342  """Add a CRY gate to the front of the gate structure.
343 
344  Args:
345  target_qbit: Target qubit index (int)
346  control_qbit: Control qubit index (int)
347  """
348 
349  # call the C wrapper function
350  super(qgd_Circuit, self).add_CRY(target_qbit, control_qbit)
351 
352  def add_CRZ(self, target_qbit, control_qbit):
353  """Add a CRZ gate to the front of the gate structure.
354 
355  Args:
356  target_qbit: Target qubit index (int)
357  control_qbit: Control qubit index (int)
358  """
359 
360  # call the C wrapper function
361  super(qgd_Circuit, self).add_CRZ(target_qbit, control_qbit)
362 
363  def add_CRX(self, target_qbit, control_qbit):
364  """Add a CRX gate to the front of the gate structure.
365 
366  Args:
367  target_qbit: Target qubit index (int)
368  control_qbit: Control qubit index (int)
369  """
370 
371  # call the C wrapper function
372  super(qgd_Circuit, self).add_CRX(target_qbit, control_qbit)
373 
374  def add_CP(self, target_qbit, control_qbit):
375  """Add a CP gate to the front of the gate structure.
376 
377  Args:
378  target_qbit: Target qubit index (int)
379  control_qbit: Control qubit index (int)
380  """
381 
382  # call the C wrapper function
383  super(qgd_Circuit, self).add_CP(target_qbit, control_qbit)
384 
385  def add_SWAP(self, target_qbits, target_qbit2=-1):
386  """Add a SWAP gate to the front of the gate structure.
387 
388  Args:
389  target_qbits: List of target qubits (list of int) - at least 2 qubits required
390  target_qbit2: Optional second qubit if target_qbits is a single int
391  """
392  # Ensure target_qbits is a list
393  if isinstance(target_qbits, (list, tuple)):
394  super(qgd_Circuit, self).add_SWAP(list(target_qbits))
395  if isinstance(target_qbits, int) and target_qbit2 != -1:
396  super(qgd_Circuit, self).add_SWAP(list([target_qbits, target_qbit2]))
397 
398  def add_RXX(self, target_qbits, target_qbit2=-1):
399  """Add a RXX gate to the front of the gate structure.
400 
401  Args:
402  target_qbits: List of target qubits (list of int) - at least 2 qubits required
403  target_qbit2: Optional second qubit if target_qbits is a single int
404  """
405  # Ensure target_qbits is a list
406  if isinstance(target_qbits, (list, tuple)):
407  super(qgd_Circuit, self).add_RXX(list(target_qbits))
408  if isinstance(target_qbits, int) and target_qbit2 != -1:
409  super(qgd_Circuit, self).add_RXX(list([target_qbits, target_qbit2]))
410 
411  def add_RYY(self, target_qbits, target_qbit2=-1):
412  """Add a RYY gate to the front of the gate structure.
413 
414  Args:
415  target_qbits: List of target qubits (list of int) - at least 2 qubits required
416  target_qbit2: Optional second qubit if target_qbits is a single int
417  """
418  # Ensure target_qbits is a list
419  if isinstance(target_qbits, (list, tuple)):
420  super(qgd_Circuit, self).add_RYY(list(target_qbits))
421  if isinstance(target_qbits, int) and target_qbit2 != -1:
422  super(qgd_Circuit, self).add_RYY(list([target_qbits, target_qbit2]))
423 
424  def add_RZZ(self, target_qbits, target_qbit2=-1):
425  """Add a RZZ gate to the front of the gate structure.
426 
427  Args:
428  target_qbits: List of target qubits (list of int) - at least 2 qubits required
429  target_qbit2: Optional second qubit if target_qbits is a single int
430  """
431  # Ensure target_qbits is a list
432  if isinstance(target_qbits, (list, tuple)):
433  super(qgd_Circuit, self).add_RZZ(list(target_qbits))
434  if isinstance(target_qbits, int) and target_qbit2 != -1:
435  super(qgd_Circuit, self).add_RZZ(list([target_qbits, target_qbit2]))
436 
437  def add_CSWAP(self, target_qbits, control_qbits):
438  """Add a CSWAP (Fredkin) gate to the front of the gate structure.
439 
440  Args:
441  target_qbits: Target qubits (list of int) - exactly 2 for standard CSWAP
442  control_qbits: Control qubit(s) (int or list of int) - exactly 1 for standard CSWAP
443 
444  Note:
445  Accepts both list and single integer inputs for control_qbits. Examples:
446  - add_CSWAP([0,1], 2) -> control_qbits becomes [2] (standard Fredkin gate)
447  - add_CSWAP([0,1], [2]) -> control_qbits stays [2] (standard Fredkin gate)
448  Currently only supports exactly 1 control qubit (standard Fredkin gate).
449  """
450  # Convert target_qbits to list if needed
451  if not isinstance(target_qbits, (list, tuple)):
452  raise TypeError("target_qbits must be a list or tuple")
453  target_qbits = list(target_qbits)
454 
455  # Convert control_qbits to list if it's a single integer
456  if isinstance(control_qbits, int):
457  control_qbits = [control_qbits]
458  elif isinstance(control_qbits, (list, tuple)):
459  control_qbits = list(control_qbits)
460  else:
461  raise TypeError("control_qbits must be an int, list, or tuple")
462 
463  # call the C wrapper function
464  super(qgd_Circuit, self).add_CSWAP(target_qbits, control_qbits)
465 
466  def add_CCX(self, target_qbit, control_qbits):
467  """Add a CCX gate to the front of the gate structure.
468 
469  Args:
470  target_qbit: Target qubit index (int)
471  control_qbits: Control qubits (list of int or tuple) - at least 2 control qubits required
472 
473  Note:
474  control_qbits can be a list or tuple. Example:
475  - add_CCX(0, [1,2]) -> standard CCX with 2 controls
476  """
477  # Convert control_qbits to list if needed
478  if isinstance(control_qbits, int):
479  raise TypeError(
480  "control_qbits must be a list or tuple (CCX requires at least 2 control qubits)"
481  )
482  elif isinstance(control_qbits, (list, tuple)):
483  control_qbits = list(control_qbits)
484  else:
485  raise TypeError("control_qbits must be a list or tuple")
486 
487  # call the C wrapper function
488  super(qgd_Circuit, self).add_CCX(target_qbit, control_qbits)
489 
490  def add_Circuit(self, gate):
491  """Add a block of operations (subcircuit) to the front of the gate structure.
492 
493  Args:
494  gate: A qgd_Circuit instance representing the subcircuit to add
495  """
496 
497  # call the C wrapper function
498  super().add_Circuit(gate)
499 
500  def add_GENERAL(self, operation_mtx, target_qbits=None, control_qbits=None, is_f32=False):
501  """Add a GENERAL_OPERATION gate from an explicit unitary matrix.
502 
503  Args:
504  operation_mtx: Square operation matrix with shape (2**qbit_num, 2**qbit_num)
505  target_qbits: Optional list of target qubits used as metadata
506  control_qbits: Optional list of control qubits used as metadata
507  is_f32: If True, interpret operation_mtx as complex64
508  """
509 
510  if target_qbits is None:
511  target_qbits = []
512  if control_qbits is None:
513  control_qbits = []
514 
515  super().add_GENERAL(operation_mtx, target_qbits, control_qbits, is_f32=is_f32)
516 
517  def get_Matrix(self, parameters_mtx, is_f32=False):
518  """Retrieve the matrix representation of the circuit operation.
519 
520  Args:
521  parameters_mtx: Parameter array (numpy array) for parametric gates
522  is_f32: If True, use float32 precision (default False)
523 
524  Returns:
525  numpy.ndarray: The matrix representation of the circuit
526  """
527 
528  parameters_mtx = np.asarray(
529  parameters_mtx,
530  dtype=np.float32 if is_f32 else np.float64,
531  )
532 
533  # call the C wrapper function
534  return super().get_Matrix(parameters_mtx, is_f32=is_f32)
535 
536  def get_Parameter_Num(self):
537  """Get the number of free parameters in the gate structure.
538 
539  Returns:
540  int: The number of free parameters
541  """
542 
543  # call the C wrapper function
544  return super().get_Parameter_Num()
545 
546  def apply_to(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False):
547  """Apply the gate circuit operation on the input matrix.
548 
549  Args:
550  parameters_mtx: Parameter array (numpy array) for parametric gates
551  unitary_mtx: Input matrix (numpy array) to be transformed
552  parallel: Parallel execution mode (int, optional, default=1)
553  is_f32: Use float32/complex64 precision (bool, optional, default=False)
554  """
555 
556  # call the C wrapper function
557  super().apply_to(parameters_mtx, unitary_mtx, parallel=parallel, is_f32=is_f32)
558 
559  def apply_from_right(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False):
560  """Apply the gate circuit from the right on the input matrix.
561 
562  Args:
563  parameters_mtx: Parameter array (numpy array) for parametric gates
564  unitary_mtx: Input matrix (numpy array) to be transformed
565  parallel: Parallel execution mode (int, optional, default=1)
566  is_f32: Use float32/complex64 precision (bool, optional, default=False)
567  """
568 
569  # call the C wrapper function
570  super().apply_from_right(parameters_mtx, unitary_mtx, parallel=parallel, is_f32=is_f32)
571 
572  def apply_to_list(self, inputs, parameters_mtx, parallel=1, is_f32=False):
573  """Apply the circuit to a list of input matrices with float32/float64 dispatch.
574 
575  Args:
576  inputs: List of numpy arrays to transform in-place (complex128 or complex64 when is_f32=True)
577  parameters_mtx: Parameter array (float64 or float32 when is_f32=True)
578  parallel: Parallel execution mode (int, optional, default=1)
579  is_f32: Use float32/complex64 precision (bool, optional, default=False)
580  """
581  super().apply_to_list(inputs, parameters_mtx, parallel, is_f32=is_f32)
582 
583  def apply_derivate_to(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False):
584  """Evaluate the derivative of the circuit on an input matrix w.r.t. all free parameters.
585 
586  Args:
587  parameters_mtx: Parameter array (float64 or float32 when is_f32=True)
588  unitary_mtx: Input matrix (complex128 or complex64 when is_f32=True)
589  parallel: Parallel execution mode (int, optional, default=1)
590  is_f32: Use float32/complex64 precision (bool, optional, default=False)
591 
592  Returns:
593  list of numpy arrays: One matrix per free parameter (complex128 or complex64 when is_f32=True)
594  """
595  return super().apply_derivate_to(parameters_mtx, unitary_mtx, parallel, is_f32=is_f32)
596 
597  def apply_to_combined(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False):
598  """Evaluate forward circuit action and all derivatives in one call.
599 
600  Return format is a list where element 0 is the forward apply_to result,
601  and elements 1..N are derivatives w.r.t. each free parameter.
602 
603  Args:
604  parameters_mtx: Parameter array (float64 or float32 when is_f32=True)
605  unitary_mtx: Input matrix (complex128 or complex64 when is_f32=True)
606  parallel: Parallel execution mode (int, optional, default=1)
607  is_f32: Use float32/complex64 precision (bool, optional, default=False)
608 
609  Returns:
610  list of numpy arrays: [forward_output, derivative_0, derivative_1, ...]
611  """
612  return super().apply_to_combined(parameters_mtx, unitary_mtx, parallel, is_f32=is_f32)
613 
615  self, parameters=None, input_state=None, qubit_list=None
616  ):
617  """Calculate the second Rényi entropy of the quantum circuit.
618 
619  Args:
620  parameters: Parameter array (float64 numpy array, optional)
621  input_state: Input quantum state (complex numpy array, optional). If None, |0> is created
622  qubit_list: Subset of qubits for which the Rényi entropy should be calculated (list, optional)
623 
624  Returns:
625  float: The calculated second Rényi entropy
626  """
627 
628  # validate input parameters
629 
630  qbit_num = self.get_Qbit_Num()
631 
632  qubit_list_validated = list()
633  if isinstance(qubit_list, list) or isinstance(qubit_list, tuple):
634  for item in qubit_list:
635  if isinstance(item, int):
636  qubit_list_validated.append(item)
637  qubit_list_validated = list(set(qubit_list_validated))
638  else:
639  print("Elements of qbit_list should be integers")
640  return
641  elif qubit_list == None:
642  qubit_list_validated = [x for x in range(qbit_num)]
643 
644  else:
645  print("Elements of qbit_list should be integers")
646  return
647 
648  if parameters is None:
649  print("get_Second_Renyi_entropy: array of input parameters is None")
650  return None
651 
652  if input_state is None:
653  matrix_size = 1 << qbit_num
654  input_state = np.zeros((matrix_size, 1), dtype=np.complex128)
655  input_state[0] = 1
656 
657  # evaluate the entropy
658  entropy = super().get_Second_Renyi_Entropy(
659  parameters, input_state, qubit_list_validated
660  )
661 
662  return entropy
663 
664  def get_Qbit_Num(self):
665  """Get the number of qubits in the circuit.
666 
667  Returns:
668  int: The number of qubits
669  """
670 
671  return super().get_Qbit_Num()
672 
673  def get_Qbits(self):
674  """Get the list of qubits involved in the circuit.
675 
676  Returns:
677  list: List of qubit indices involved in the circuit
678  """
679 
680  return super().get_Qbits()
681 
682  def set_min_fusion(self, min_fusion):
683  """Set the minimum fusion parameter in the circuit.
684 
685  Args:
686  min_fusion: Minimum fusion value (int)
687  """
688 
689  super().set_min_fusion(min_fusion)
690 
691  def get_Gates(self):
692  """Get the list of gates (or subcircuits) in the circuit.
693 
694  Returns:
695  list: List of gate objects in the circuit
696  """
697 
698  return super().get_Gates()
699 
700  def get_Gate_Nums(self):
701  """Get statistics on the gate counts in the circuit.
702 
703  Returns:
704  dict: Dictionary containing the gate type counts
705  """
706 
707  return super().get_Gate_Nums()
708 
709  def Remap_Qbits(self, qbit_map, qbit_num=None):
710  """Remap the qubits in the circuit.
711 
712  Args:
713  qbit_map: Dictionary mapping initial qubit indices to remapped qubit indices
714  Format: {int(initial_qbit): int(remapped_qbit)}
715  qbit_num: Number of qubits in the remapped circuit (int, optional).
716  Can be different from the original circuit. If None, uses the original number
717 
718  Returns:
719  qgd_Circuit: A newly created, remapped circuit instance
720  """
721 
722  if qbit_num == None:
723  qbit_num = self.get_Qbit_Num()
724 
725  return super().Remap_Qbits(qbit_map, qbit_num)
726 
728  """Get the starting index of the parameters in the parameter array.
729 
730  The starting index corresponds to the circuit in which the current gate is incorporated.
731 
732  Returns:
733  int: The starting index of parameters
734  """
735 
736  # call the C wrapper function
737  return super().get_Parameter_Start_Index()
738 
739  def get_Parents(self, gate):
740  """Get the list of parent gate indices.
741 
742  The parent gates can be obtained from the list of gates involved in the circuit.
743 
744  Args:
745  gate: Gate index (int) for which to retrieve parent gates
746 
747  Returns:
748  list: List of parent gate indices
749  """
750 
751  # call the C wrapper function
752  return super().get_Parents(gate)
753 
754  def get_Children(self, gate):
755  """Get the list of child gate indices.
756 
757  The children gates can be obtained from the list of gates involved in the circuit.
758 
759  Args:
760  gate: Gate index (int) for which to retrieve child gates
761 
762  Returns:
763  list: List of child gate indices
764  """
765 
766  # call the C wrapper function
767  return super().get_Children(gate)
768 
769  def add_Gate(self, qgd_gate):
770  """Add a generic gate to the circuit.
771 
772  Args:
773  qgd_gate: A gate object from the gates_Wrapper module
774 
775  Raises:
776  Exception: If the gate type is not implemented
777  """
778 
779  if isinstance(qgd_gate, H):
780  self.add_H(qgd_gate.get_Target_Qbit())
781  elif isinstance(qgd_gate, X):
782  self.add_X(qgd_gate.get_Target_Qbit())
783  elif isinstance(qgd_gate, Y):
784  self.add_Y(qgd_gate.get_Target_Qbit())
785  elif isinstance(qgd_gate, Z):
786  self.add_Z(qgd_gate.get_Target_Qbit())
787  elif isinstance(qgd_gate, CH):
788  self.add_CH(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
789  elif isinstance(qgd_gate, CZ):
790  self.add_CZ(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
791  elif isinstance(qgd_gate, RX):
792  self.add_RX(qgd_gate.get_Target_Qbit())
793  elif isinstance(qgd_gate, RY):
794  self.add_RY(qgd_gate.get_Target_Qbit())
795  elif isinstance(qgd_gate, RZ):
796  self.add_RZ(qgd_gate.get_Target_Qbit())
797  elif isinstance(qgd_gate, SX):
798  self.add_SX(qgd_gate.get_Target_Qbit())
799  elif isinstance(qgd_gate, SXdg):
800  self.add_SXdg(qgd_gate.get_Target_Qbit())
801  elif isinstance(qgd_gate, U1):
802  self.add_U1(qgd_gate.get_Target_Qbit())
803  elif isinstance(qgd_gate, U2):
804  self.add_U2(qgd_gate.get_Target_Qbit())
805  elif isinstance(qgd_gate, U3):
806  self.add_U3(qgd_gate.get_Target_Qbit())
807  elif isinstance(qgd_gate, CRY):
808  self.add_CRY(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
809  elif isinstance(qgd_gate, CNOT):
810  self.add_CNOT(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
811  elif isinstance(qgd_gate, S):
812  self.add_S(qgd_gate.get_Target_Qbit())
813  elif isinstance(qgd_gate, Sdg):
814  self.add_Sdg(qgd_gate.get_Target_Qbit())
815  elif isinstance(qgd_gate, T):
816  self.add_T(qgd_gate.get_Target_Qbit())
817  elif isinstance(qgd_gate, Tdg):
818  self.add_Tdg(qgd_gate.get_Target_Qbit())
819  elif isinstance(qgd_gate, R):
820  self.add_R(qgd_gate.get_Target_Qbit())
821  elif isinstance(qgd_gate, CROT):
822  self.add_CROT(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
823  elif isinstance(qgd_gate, CR):
824  self.add_CR(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
825  elif isinstance(qgd_gate, SYC):
826  self.add_SYC(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
827  elif isinstance(qgd_gate, CRZ):
828  self.add_CRZ(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
829  elif isinstance(qgd_gate, CRX):
830  self.add_CRX(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
831  elif isinstance(qgd_gate, CP):
832  self.add_CP(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
833  elif isinstance(qgd_gate, CU):
834  self.add_CU(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbit())
835  elif isinstance(qgd_gate, SWAP):
836  self.add_SWAP(qgd_gate.get_Target_Qbits())
837  elif isinstance(qgd_gate, RXX):
838  self.add_RXX(qgd_gate.get_Target_Qbits())
839  elif isinstance(qgd_gate, RYY):
840  self.add_RYY(qgd_gate.get_Target_Qbits())
841  elif isinstance(qgd_gate, RZZ):
842  self.add_RZZ(qgd_gate.get_Target_Qbits())
843  elif isinstance(qgd_gate, CSWAP):
844  self.add_CSWAP(qgd_gate.get_Target_Qbits(), qgd_gate.get_Control_Qbits())
845  elif isinstance(qgd_gate, CCX):
846  self.add_CCX(qgd_gate.get_Target_Qbit(), qgd_gate.get_Control_Qbits())
847  else:
848  raise Exception("Cannot add gate: unimplemented gate type")
def apply_to(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False)
Definition: qgd_Circuit.py:546
def add_GENERAL(self, operation_mtx, target_qbits=None, control_qbits=None, is_f32=False)
Definition: qgd_Circuit.py:500
def apply_to_combined(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False)
Definition: qgd_Circuit.py:597
def apply_from_right(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False)
Definition: qgd_Circuit.py:559
def add_SWAP(self, target_qbits, target_qbit2=-1)
Definition: qgd_Circuit.py:385
def Remap_Qbits(self, qbit_map, qbit_num=None)
Definition: qgd_Circuit.py:709
def add_CH(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:175
def add_CNOT(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:153
def add_RYY(self, target_qbits, target_qbit2=-1)
Definition: qgd_Circuit.py:411
def apply_derivate_to(self, parameters_mtx, unitary_mtx, parallel=1, is_f32=False)
Definition: qgd_Circuit.py:583
def set_min_fusion(self, min_fusion)
Definition: qgd_Circuit.py:682
def get_Matrix(self, parameters_mtx, is_f32=False)
Definition: qgd_Circuit.py:517
def add_CRY(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:341
def add_CCX(self, target_qbit, control_qbits)
Definition: qgd_Circuit.py:466
def add_CRX(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:363
def add_RXX(self, target_qbits, target_qbit2=-1)
Definition: qgd_Circuit.py:398
def add_CR(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:330
def add_CSWAP(self, target_qbits, control_qbits)
Definition: qgd_Circuit.py:437
def add_RZZ(self, target_qbits, target_qbit2=-1)
Definition: qgd_Circuit.py:424
def add_CROT(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:319
def apply_to_list(self, inputs, parameters_mtx, parallel=1, is_f32=False)
Definition: qgd_Circuit.py:572
def add_CP(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:374
def get_Second_Renyi_Entropy(self, parameters=None, input_state=None, qubit_list=None)
Definition: qgd_Circuit.py:616
def add_SYC(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:197
def add_CZ(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:164
def add_adaptive(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:308
def add_CU(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:186
def add_CRZ(self, target_qbit, control_qbit)
Definition: qgd_Circuit.py:352