Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/tequila/circuit/_gates_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ def __init__(self, name, target: UnionList, control: UnionList = None, generator
self._target = tuple(list_assignment(target))
self._control = tuple(list_assignment(control))
self.finalize()
self.generator = generator
if generator:
self.generator = generator

def copy(self):
return copy.deepcopy(self)
Expand Down
20 changes: 20 additions & 0 deletions src/tequila/circuit/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,9 @@ def map_variables(self, variables: dict, *args, **kwargs):

return QCircuit(gates=new_gates)

def as_subcircuit_gate(self) -> QCircuit:
return QCircuit.wrap_gate(SubcircuitGate(self))


class Moment(QCircuit):
"""
Expand Down Expand Up @@ -1060,3 +1063,20 @@ def find_unused_qubit(U0: QCircuit = None, U1: QCircuit = None) -> int:
assert free_qubit not in active_qubits

return free_qubit


class SubcircuitGate(QGateImpl):
"""
Wraps a QCircuit object. When this is added to another circuit,
the structure of this subcircuit is kept (instead of flattening
it to a list of basic gates). This allows reusing this subcircuit
and e.g. compilation results while only storing it once. For
example, this is useful when building QSVT circuits.
"""

def __init__(self, circuit: QCircuit):
super().__init__(name="CachedSubcircuit", target=tuple(range(circuit.n_qubits)))
self.circuit = circuit

def dagger(self):
return SubcircuitGate(self.circuit.dagger())
11 changes: 10 additions & 1 deletion src/tequila/circuit/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import warnings

from tequila import TequilaException
from tequila.circuit.circuit import QCircuit
from tequila.circuit.circuit import QCircuit, SubcircuitGate
from tequila.circuit.gates import Rx, Ry, H, X, S, Rz, ExpPauli, CNOT, Phase, T, Z, GlobalPhase
from tequila.circuit._gates_impl import (
RotationGateImpl,
Expand Down Expand Up @@ -318,7 +318,16 @@ def compile_circuit(self, abstract_circuit: QCircuit, variables=None, *args, **k
# Keep a dicitionary of compiled pauli_rotations
pauli_dict = {}

compiled_subcircuits = {}

for idx, gate in gatelist:
if isinstance(gate, SubcircuitGate):
if id(gate.circuit) not in compiled_subcircuits:
compiled_subcircuits[id(gate.circuit)] = self.compile_circuit(gate.circuit)
cg = compiled_subcircuits[id(gate.circuit)]
compiled_gates.append((idx, cg))
continue

cg = gate
controlled = gate.is_controlled()

Expand Down
2 changes: 1 addition & 1 deletion src/tequila/circuit/gates.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from tequila.circuit.circuit import QCircuit
from tequila.circuit.circuit import QCircuit, SubcircuitGate
from tequila.objective.objective import Variable, assign_variable
from tequila.circuit import _gates_impl as impl
import typing
Expand Down
6 changes: 4 additions & 2 deletions src/tequila/simulators/simulator_base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from tequila.circuit._gates_impl import GlobalPhaseGateImpl
from tequila.utils import TequilaException, to_float, TequilaWarning
from tequila.circuit.circuit import QCircuit
from tequila.circuit.circuit import QCircuit, SubcircuitGate
from tequila.utils.keymap import KeyMapSubregisterToRegister
from tequila.utils.misc import to_float
from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
Expand Down Expand Up @@ -314,7 +314,9 @@ def create_circuit(self, abstract_circuit: QCircuit, circuit=None, *args, **kwar
result = self.initialize_circuit(*args, **kwargs)

for g in abstract_circuit.gates:
if g.is_parameterized():
if isinstance(g, SubcircuitGate):
self.create_circuit(g.circuit, result)
elif g.is_parameterized():
self.add_parametrized_gate(g, result, *args, **kwargs)
else:
self.add_basic_gate(g, result, *args, **kwargs)
Expand Down
Loading