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
tequila/circuit/circuit.py
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
-
from tequila.circuit._gates_impl import QGateImpl, assign_variable, list_assignment
|
2
|
+
from tequila.circuit._gates_impl import QGateImpl, assign_variable, list_assignment, GlobalPhaseGateImpl, PhaseGateImpl
|
3
3
|
from tequila.utils.exceptions import TequilaException, TequilaWarning
|
4
4
|
from tequila.utils.bitstrings import BitNumbering
|
5
5
|
import typing
|
6
6
|
import copy
|
7
7
|
from collections import defaultdict
|
8
|
+
import numpy as np
|
8
9
|
import warnings
|
9
10
|
|
10
11
|
from .qpic import export_to
|
11
12
|
|
12
13
|
|
13
|
-
class QCircuit
|
14
|
+
class QCircuit:
|
14
15
|
"""
|
15
16
|
Fundamental class representing an abstract circuit.
|
16
17
|
|
@@ -66,7 +67,6 @@ class QCircuit():
|
|
66
67
|
spots = [table[q] for q in qus]
|
67
68
|
|
68
69
|
if max(spots) == len(moms):
|
69
|
-
|
70
70
|
moms.append(Moment([g]))
|
71
71
|
else:
|
72
72
|
moms[max(spots)].add_gate(g)
|
@@ -92,8 +92,8 @@ class QCircuit():
|
|
92
92
|
for g in self.gates:
|
93
93
|
p = 0
|
94
94
|
qus = g.qubits
|
95
|
-
if g.
|
96
|
-
if hasattr(g.parameter,
|
95
|
+
if g.is_parameterized():
|
96
|
+
if hasattr(g.parameter, "extract_variables"):
|
97
97
|
p = 1
|
98
98
|
|
99
99
|
if p == 0:
|
@@ -150,6 +150,10 @@ class QCircuit():
|
|
150
150
|
else:
|
151
151
|
return self._gates
|
152
152
|
|
153
|
+
@gates.setter
|
154
|
+
def gates(self, other):
|
155
|
+
self._gates = list(other)
|
156
|
+
|
153
157
|
@property
|
154
158
|
def numbering(self) -> BitNumbering:
|
155
159
|
return BitNumbering.LSB
|
@@ -170,9 +174,11 @@ class QCircuit():
|
|
170
174
|
self._min_n_qubits = other
|
171
175
|
if other < self.max_qubit() + 1:
|
172
176
|
raise TequilaException(
|
173
|
-
"You are trying to set n_qubits to "
|
174
|
-
|
175
|
-
|
177
|
+
"You are trying to set n_qubits to "
|
178
|
+
+ str(other)
|
179
|
+
+ " but your circuit needs at least: "
|
180
|
+
+ str(self.max_qubit() + 1)
|
181
|
+
)
|
176
182
|
return self
|
177
183
|
|
178
184
|
def __init__(self, gates=None, parameter_map=None):
|
@@ -210,7 +216,7 @@ class QCircuit():
|
|
210
216
|
"""
|
211
217
|
parameter_map = defaultdict(list)
|
212
218
|
for idx, gate in enumerate(self.gates):
|
213
|
-
if gate.
|
219
|
+
if gate.is_parameterized():
|
214
220
|
variables = gate.extract_variables()
|
215
221
|
for variable in variables:
|
216
222
|
parameter_map[variable] += [(idx, gate)]
|
@@ -276,7 +282,6 @@ class QCircuit():
|
|
276
282
|
last_idx = -1
|
277
283
|
|
278
284
|
for idx, circuit, do_replace in dataset:
|
279
|
-
|
280
285
|
# failsafe
|
281
286
|
if hasattr(circuit, "gates"):
|
282
287
|
gatelist = circuit.gates
|
@@ -285,14 +290,14 @@ class QCircuit():
|
|
285
290
|
else:
|
286
291
|
gatelist = [circuit]
|
287
292
|
|
288
|
-
new_gatelist += self.gates[last_idx + 1:idx]
|
293
|
+
new_gatelist += self.gates[last_idx + 1 : idx]
|
289
294
|
new_gatelist += gatelist
|
290
295
|
if not do_replace:
|
291
296
|
new_gatelist.append(self.gates[idx])
|
292
297
|
|
293
298
|
last_idx = idx
|
294
299
|
|
295
|
-
new_gatelist += self.gates[last_idx + 1:]
|
300
|
+
new_gatelist += self.gates[last_idx + 1 :]
|
296
301
|
|
297
302
|
result = QCircuit(gates=new_gatelist)
|
298
303
|
result.n_qubits = max(result.n_qubits, self.n_qubits)
|
@@ -347,11 +352,11 @@ class QCircuit():
|
|
347
352
|
whether or not all gates in the circuit are paremtrized
|
348
353
|
"""
|
349
354
|
for gate in self.gates:
|
350
|
-
if not gate.
|
355
|
+
if not gate.is_parameterized():
|
351
356
|
return False
|
352
357
|
else:
|
353
|
-
if hasattr(gate,
|
354
|
-
if not hasattr(gate.parameter,
|
358
|
+
if hasattr(gate, "parameter"):
|
359
|
+
if not hasattr(gate.parameter, "wrap"):
|
355
360
|
return False
|
356
361
|
else:
|
357
362
|
continue
|
@@ -367,11 +372,11 @@ class QCircuit():
|
|
367
372
|
whether or not all gates in the circuit are unparametrized
|
368
373
|
"""
|
369
374
|
for gate in self.gates:
|
370
|
-
if not gate.
|
375
|
+
if not gate.is_parameterized():
|
371
376
|
continue
|
372
377
|
else:
|
373
|
-
if hasattr(gate,
|
374
|
-
if not hasattr(gate.parameter,
|
378
|
+
if hasattr(gate, "parameter"):
|
379
|
+
if not hasattr(gate.parameter, "wrap"):
|
375
380
|
continue
|
376
381
|
else:
|
377
382
|
return False
|
@@ -441,6 +446,76 @@ class QCircuit():
|
|
441
446
|
else:
|
442
447
|
return QCircuit(gates=[gate])
|
443
448
|
|
449
|
+
def to_matrix(self, variables=None):
|
450
|
+
"""
|
451
|
+
take the circuit and return the unitary matrix corresponding to it.
|
452
|
+
Parameters
|
453
|
+
----------
|
454
|
+
variables: dict:
|
455
|
+
(Default value = None)
|
456
|
+
a dictionary mapping variable names to values. If None, the circuit must not contain any variables.
|
457
|
+
If the circuit contains variables, they must be provided here.
|
458
|
+
|
459
|
+
Returns
|
460
|
+
-------
|
461
|
+
np.ndarray:
|
462
|
+
the unitary matrix corresponding to the circuit.
|
463
|
+
"""
|
464
|
+
import quimb.gates
|
465
|
+
import quimb.tensor as qtn
|
466
|
+
from tequila import compile_circuit
|
467
|
+
|
468
|
+
num_variables = len(self.extract_variables())
|
469
|
+
|
470
|
+
if num_variables == 0:
|
471
|
+
variables = {}
|
472
|
+
elif variables is None:
|
473
|
+
raise TequilaException(
|
474
|
+
f"QCircuit.to_matrix(): no variables provided, but the circuit has {num_variables} variables"
|
475
|
+
)
|
476
|
+
|
477
|
+
compiled_circuit = compile_circuit(
|
478
|
+
self,
|
479
|
+
)
|
480
|
+
compiled_circuit = compiled_circuit.map_variables(variables)
|
481
|
+
|
482
|
+
gate_mapping = {"Rx": "RX", "Ry": "RY", "Rz": "RZ", "H": "H", "X": "X"}
|
483
|
+
|
484
|
+
quimb_circuit = qtn.Circuit(self.n_qubits)
|
485
|
+
|
486
|
+
# quimb uses MSB convention, so we need to modify the qubit indices
|
487
|
+
# to LSB
|
488
|
+
for g in compiled_circuit.gates:
|
489
|
+
if g.name not in gate_mapping:
|
490
|
+
raise TequilaException(
|
491
|
+
f"Gate {g.name} is not supported for conversion to matrix. "
|
492
|
+
f"Supported gates: {list(gate_mapping.keys())}"
|
493
|
+
)
|
494
|
+
|
495
|
+
if g.is_parameterized():
|
496
|
+
quimb_circuit.apply_gate(
|
497
|
+
gate_mapping[g.name],
|
498
|
+
params=[float(g.parameter())],
|
499
|
+
qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
|
500
|
+
parameterize=True,
|
501
|
+
)
|
502
|
+
elif g.is_controlled():
|
503
|
+
quimb_circuit.apply_gate(
|
504
|
+
gate_mapping[g.name],
|
505
|
+
qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
|
506
|
+
controls=[abs(c - self.n_qubits + 1) for c in list(g.control)],
|
507
|
+
)
|
508
|
+
else:
|
509
|
+
quimb_circuit.apply_gate(
|
510
|
+
gate_mapping[g.name],
|
511
|
+
qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
|
512
|
+
)
|
513
|
+
|
514
|
+
uni = quimb_circuit.get_uni()
|
515
|
+
unitary = np.array(uni.to_dense())
|
516
|
+
|
517
|
+
return unitary
|
518
|
+
|
444
519
|
def to_networkx(self):
|
445
520
|
"""
|
446
521
|
Turn a given quantum circuit from tequila into graph form via NetworkX
|
@@ -449,6 +524,7 @@ class QCircuit():
|
|
449
524
|
"""
|
450
525
|
# avoiding dependcies (only used here so far)
|
451
526
|
import networkx as nx
|
527
|
+
|
452
528
|
G = nx.Graph()
|
453
529
|
for q in self.qubits:
|
454
530
|
G.add_node(q)
|
@@ -457,20 +533,20 @@ class QCircuit():
|
|
457
533
|
if gate.control:
|
458
534
|
for s in gate.control:
|
459
535
|
for t in gate.target:
|
460
|
-
tstr =
|
536
|
+
tstr = ""
|
461
537
|
tstr += str(t)
|
462
538
|
target = int(tstr)
|
463
539
|
Gdict[s].append(target) # add target to key of correlated controls
|
464
540
|
for p in gate.target:
|
465
541
|
for r in gate.control:
|
466
|
-
cstr =
|
542
|
+
cstr = ""
|
467
543
|
cstr += str(r)
|
468
544
|
control = int(cstr)
|
469
545
|
Gdict[p].append(control) # add control to key of correlated targets
|
470
546
|
else:
|
471
547
|
for s in gate.target:
|
472
548
|
for t in gate.target:
|
473
|
-
tstr2 =
|
549
|
+
tstr2 = ""
|
474
550
|
tstr2 += str(t)
|
475
551
|
target2 = int(tstr2)
|
476
552
|
Gdict[s].append(target2)
|
@@ -479,8 +555,9 @@ class QCircuit():
|
|
479
555
|
for q in b:
|
480
556
|
lConn.append((a, q))
|
481
557
|
G.add_edges_from(lConn)
|
482
|
-
GPaths = list(
|
483
|
-
G)
|
558
|
+
GPaths = list(
|
559
|
+
nx.connected_components(G)
|
560
|
+
) # connections of various qubits, excluding repetitions (ex- (1,3) instead of (1,3) and (3,1))
|
484
561
|
GIso = [g for g in GPaths if len(g) == 1] # list of Isolated qubits
|
485
562
|
return G
|
486
563
|
|
@@ -511,7 +588,10 @@ class QCircuit():
|
|
511
588
|
whether or not the circuit is properly constructed.
|
512
589
|
|
513
590
|
"""
|
514
|
-
for
|
591
|
+
for (
|
592
|
+
k,
|
593
|
+
v,
|
594
|
+
) in self._parameter_map.items():
|
515
595
|
test = [self.gates[x[0]] == x[1] for x in v]
|
516
596
|
test += [k in self._gates[x[0]].extract_variables() for x in v]
|
517
597
|
return all(test)
|
@@ -536,8 +616,7 @@ class QCircuit():
|
|
536
616
|
# currently its recreated in the init function
|
537
617
|
return QCircuit(gates=new_gates)
|
538
618
|
|
539
|
-
def add_controls(self, control, inpl: typing.Optional[bool] = False)
|
540
|
-
-> typing.Optional[QCircuit]:
|
619
|
+
def add_controls(self, control, inpl: typing.Optional[bool] = False) -> typing.Optional[QCircuit]:
|
541
620
|
"""Depending on the truth value of inpl:
|
542
621
|
- return controlled version of self with control as the control qubits if inpl;
|
543
622
|
- mutate self so that the qubits in control are added as the control qubits if not inpl.
|
@@ -573,8 +652,9 @@ class QCircuit():
|
|
573
652
|
if len(control_lst) < len(gate.control) + len(control):
|
574
653
|
# warnings.warn("Some of the controls {} were already included in the control "
|
575
654
|
# "of a gate {}.".format(control, gate), TequilaWarning)
|
576
|
-
raise TequilaWarning(
|
577
|
-
|
655
|
+
raise TequilaWarning(
|
656
|
+
f"Some of the controls {control} were already included in the control of a gate {gate}."
|
657
|
+
)
|
578
658
|
else:
|
579
659
|
control_lst, not_control = list(control), list()
|
580
660
|
|
@@ -582,8 +662,9 @@ class QCircuit():
|
|
582
662
|
if any(qubit in control for qubit in not_control):
|
583
663
|
# warnings.warn("The target and control {} were the same qubit for a gate {}."
|
584
664
|
# .format(control, gate), TequilaWarning)
|
585
|
-
raise TequilaWarning(
|
586
|
-
|
665
|
+
raise TequilaWarning(
|
666
|
+
f"The target for a gate {gate} and the control list {control_lst} had a common qubit."
|
667
|
+
)
|
587
668
|
|
588
669
|
cgate._control = tuple(control_lst)
|
589
670
|
cgate.finalize()
|
@@ -601,22 +682,28 @@ class QCircuit():
|
|
601
682
|
gates = self.gates
|
602
683
|
control = list_assignment(control)
|
603
684
|
|
604
|
-
for gate in gates:
|
605
|
-
if gate
|
685
|
+
for i, gate in enumerate(gates):
|
686
|
+
if isinstance(gate, GlobalPhaseGateImpl):
|
687
|
+
gate = PhaseGateImpl(phase=gate.parameter, target=control[0])
|
688
|
+
gates[i] = gate
|
689
|
+
not_control = []
|
690
|
+
control_lst = list(control[1:])
|
691
|
+
elif gate.is_controlled():
|
606
692
|
control_lst = list(set(list(gate.control) + list(control)))
|
607
693
|
|
608
694
|
# Need to check duplicates
|
609
|
-
not_control = list(set(qubit for qubit in list(gate.qubits)
|
610
|
-
if qubit not in list(gate.control)))
|
695
|
+
not_control = list(set(qubit for qubit in list(gate.qubits) if qubit not in list(gate.control)))
|
611
696
|
|
612
697
|
# Raise TequilaWarning if control qubit is duplicated
|
613
698
|
if len(control_lst) < len(gate.control) + len(control):
|
614
699
|
# warnings.warn("Some of the controls {} were already included in the control "
|
615
700
|
# "of a gate {}.".format(control, gate), TequilaWarning)
|
616
|
-
raise TequilaWarning(
|
617
|
-
|
618
|
-
|
619
|
-
|
701
|
+
raise TequilaWarning(
|
702
|
+
f"Some of the controls {control} were already included "
|
703
|
+
f"in the control of a gate {gate}. "
|
704
|
+
f"This might be because the same instance of a gate is used in multiple places, "
|
705
|
+
f"e.g. because the same circuit was appended twice."
|
706
|
+
)
|
620
707
|
else:
|
621
708
|
control_lst, not_control = list(control), list()
|
622
709
|
|
@@ -624,8 +711,7 @@ class QCircuit():
|
|
624
711
|
if any(qubit in control for qubit in not_control):
|
625
712
|
# warnings.warn("The target and control {} were the same qubit for a gate {}."
|
626
713
|
# .format(control, gate), TequilaWarning)
|
627
|
-
raise TequilaWarning(f
|
628
|
-
f'and the control list {control} had a common qubit.')
|
714
|
+
raise TequilaWarning(f"The target for a gate {gate} and the control list {control} had a common qubit.")
|
629
715
|
|
630
716
|
gate._control = tuple(control_lst)
|
631
717
|
gate.finalize()
|
@@ -650,9 +736,9 @@ class QCircuit():
|
|
650
736
|
for k, v in variables.items():
|
651
737
|
if k not in my_variables:
|
652
738
|
warnings.warn(
|
653
|
-
"map_variables: variable {} is not part of circuit with variables {}".format(k,
|
654
|
-
|
655
|
-
|
739
|
+
"map_variables: variable {} is not part of circuit with variables {}".format(k, my_variables),
|
740
|
+
TequilaWarning,
|
741
|
+
)
|
656
742
|
|
657
743
|
new_gates = [copy.deepcopy(gate).map_variables(variables) for gate in self.gates]
|
658
744
|
|
@@ -688,11 +774,11 @@ class Moment(QCircuit):
|
|
688
774
|
mu = []
|
689
775
|
mp = []
|
690
776
|
for gate in self.gates:
|
691
|
-
if not gate.
|
777
|
+
if not gate.is_parameterized():
|
692
778
|
mu.append(gate)
|
693
779
|
else:
|
694
|
-
if hasattr(gate,
|
695
|
-
if not hasattr(gate.parameter,
|
780
|
+
if hasattr(gate, "parameter"):
|
781
|
+
if not hasattr(gate.parameter, "wrap"):
|
696
782
|
mu.append(gate)
|
697
783
|
else:
|
698
784
|
mp.append(gate)
|
@@ -725,8 +811,8 @@ class Moment(QCircuit):
|
|
725
811
|
for q in g.qubits:
|
726
812
|
if q in occ:
|
727
813
|
raise TequilaException(
|
728
|
-
|
729
|
-
|
814
|
+
"cannot have doubly occupied qubits, which occurred at qubit {}".format(str(q))
|
815
|
+
)
|
730
816
|
else:
|
731
817
|
occ.append(q)
|
732
818
|
if sort:
|
@@ -787,8 +873,7 @@ class Moment(QCircuit):
|
|
787
873
|
if q not in first_overlap:
|
788
874
|
first_overlap.append(q)
|
789
875
|
else:
|
790
|
-
raise TequilaException(
|
791
|
-
'cannot have a moment with multiple operations acting on the same qubit!')
|
876
|
+
raise TequilaException("cannot have a moment with multiple operations acting on the same qubit!")
|
792
877
|
|
793
878
|
new = self.with_gate(gl[0])
|
794
879
|
for g in gl[1:]:
|
@@ -815,8 +900,8 @@ class Moment(QCircuit):
|
|
815
900
|
for n in newq:
|
816
901
|
if n in prev:
|
817
902
|
raise TequilaException(
|
818
|
-
|
819
|
-
|
903
|
+
"cannot add gate {} to moment; qubit {} already occupied.".format(str(gate), str(n))
|
904
|
+
)
|
820
905
|
|
821
906
|
self._gates.append(gate)
|
822
907
|
self.sort_gates()
|
@@ -837,17 +922,17 @@ class Moment(QCircuit):
|
|
837
922
|
QCircuit or Moment:
|
838
923
|
self, with unwanted gate removed and new gates inserted. May not be a moment.
|
839
924
|
"""
|
840
|
-
if hasattr(gates,
|
925
|
+
if hasattr(gates, "__iter__"):
|
841
926
|
gs = gates
|
842
927
|
else:
|
843
928
|
gs = [gates]
|
844
929
|
|
845
930
|
new = self.gates[:position]
|
846
931
|
new.extend(gs)
|
847
|
-
new.extend(self.gates[(position + 1):])
|
932
|
+
new.extend(self.gates[(position + 1) :])
|
848
933
|
try:
|
849
934
|
return Moment(gates=new)
|
850
|
-
except:
|
935
|
+
except Exception:
|
851
936
|
return QCircuit(gates=new)
|
852
937
|
|
853
938
|
def as_circuit(self):
|
@@ -869,11 +954,11 @@ class Moment(QCircuit):
|
|
869
954
|
whether or not EVERY gate in self.gates is parameterized.
|
870
955
|
"""
|
871
956
|
for gate in self.gates:
|
872
|
-
if not gate.
|
957
|
+
if not gate.is_parameterized():
|
873
958
|
return False
|
874
959
|
else:
|
875
|
-
if hasattr(gate,
|
876
|
-
if not hasattr(gate.parameter,
|
960
|
+
if hasattr(gate, "parameter"):
|
961
|
+
if not hasattr(gate.parameter, "wrap"):
|
877
962
|
return False
|
878
963
|
else:
|
879
964
|
continue
|
@@ -888,7 +973,6 @@ class Moment(QCircuit):
|
|
888
973
|
return result
|
889
974
|
|
890
975
|
def __iadd__(self, other):
|
891
|
-
|
892
976
|
new = self.as_circuit()
|
893
977
|
if isinstance(other, QGateImpl):
|
894
978
|
other = new.wrap_gate(other)
|
@@ -923,24 +1007,24 @@ class Moment(QCircuit):
|
|
923
1007
|
try:
|
924
1008
|
result = self.add_gate(other.gates[0])
|
925
1009
|
result._min_n_qubits += len(other.qubits)
|
926
|
-
except:
|
1010
|
+
except Exception:
|
927
1011
|
result = self.as_circuit() + QCircuit.wrap_gate(other)
|
928
|
-
result._min_n_qubits = max(self.as_circuit()._min_n_qubits,
|
929
|
-
QCircuit.wrap_gate(other)._min_n_qubits)
|
1012
|
+
result._min_n_qubits = max(self.as_circuit()._min_n_qubits, QCircuit.wrap_gate(other)._min_n_qubits)
|
930
1013
|
|
931
1014
|
else:
|
932
1015
|
if isinstance(other, QGateImpl):
|
933
1016
|
try:
|
934
1017
|
result = self.add_gate(other)
|
935
1018
|
result._min_n_qubits += len(other.qubits)
|
936
|
-
except:
|
1019
|
+
except Exception:
|
937
1020
|
result = self.as_circuit() + QCircuit.wrap_gate(other)
|
938
|
-
result._min_n_qubits = max(self.as_circuit()._min_n_qubits,
|
939
|
-
QCircuit.wrap_gate(other)._min_n_qubits)
|
1021
|
+
result._min_n_qubits = max(self.as_circuit()._min_n_qubits, QCircuit.wrap_gate(other)._min_n_qubits)
|
940
1022
|
else:
|
941
1023
|
raise TequilaException(
|
942
|
-
|
943
|
-
str(type(other))
|
1024
|
+
"cannot add moments to types other than QCircuit,Moment,or Gate; recieved summand of type {}".format(
|
1025
|
+
str(type(other))
|
1026
|
+
)
|
1027
|
+
)
|
944
1028
|
return result
|
945
1029
|
|
946
1030
|
@staticmethod
|
@@ -969,36 +1053,36 @@ class Moment(QCircuit):
|
|
969
1053
|
TequilaException
|
970
1054
|
"""
|
971
1055
|
raise TequilaException(
|
972
|
-
|
973
|
-
|
1056
|
+
"this method should never be called from Moment. Call from the QCircuit class itself instead."
|
1057
|
+
)
|
974
1058
|
|
975
1059
|
|
976
|
-
def find_unused_qubit(U0: QCircuit = None, U1: QCircuit = None)->int:
|
977
|
-
|
978
|
-
Function that checks which are the active qubits of two circuits and
|
1060
|
+
def find_unused_qubit(U0: QCircuit = None, U1: QCircuit = None) -> int:
|
1061
|
+
"""
|
1062
|
+
Function that checks which are the active qubits of two circuits and
|
979
1063
|
provides an unused qubit that is not among them. If all qubits are used
|
980
1064
|
it adds a new one.
|
981
1065
|
|
982
1066
|
Parameters
|
983
1067
|
----------
|
984
1068
|
U0 : QCircuit, corresponding to the first state.
|
985
|
-
|
1069
|
+
|
986
1070
|
U1 : QCircuit, corresponding to the second state.
|
987
1071
|
|
988
1072
|
Returns
|
989
1073
|
-------
|
990
1074
|
control_qubit : int
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
active_qubits = list(set(U0.qubits+U1.qubits))
|
1075
|
+
|
1076
|
+
"""
|
1077
|
+
|
1078
|
+
active_qubits = list(set(U0.qubits + U1.qubits))
|
995
1079
|
# default
|
996
1080
|
free_qubit = max(active_qubits) + 1
|
997
1081
|
# see if we can use another one
|
998
|
-
for n in range(max(active_qubits)+1):
|
1082
|
+
for n in range(max(active_qubits) + 1):
|
999
1083
|
if n not in active_qubits:
|
1000
1084
|
free_qubit = n
|
1001
1085
|
break
|
1002
1086
|
assert free_qubit not in active_qubits
|
1003
|
-
|
1087
|
+
|
1004
1088
|
return free_qubit
|