def _gate_to_circuit(operation): from qiskit.circuit.quantumcircuit import QuantumCircuit from qiskit.circuit.quantumregister import QuantumRegister qr = QuantumRegister(operation.num_qubits) qc = QuantumCircuit(qr, name=operation.name) if hasattr(operation, 'definition') and operation.definition: for rule in operation.definition: if rule[0].name in {'id', 'barrier', 'measure', 'snapshot'}: raise QiskitError( 'Cannot make controlled gate with {} instruction'.format( rule[0].name)) qc.append(rule[0], qargs=[qr[bit.index] for bit in rule[1]], cargs=[]) else: qc.append(operation, qargs=qr, cargs=[]) return qc
def evolve_pauli( pauli: Pauli, time: Union[float, ParameterExpression] = 1.0, cx_structure: str = "chain", label: Optional[str] = None, ) -> QuantumCircuit: r"""Construct a circuit implementing the time evolution of a single Pauli string. For a Pauli string :math:`P = \{I, X, Y, Z\}^{\otimes n}` on :math:`n` qubits and an evolution time :math:`t`, the returned circuit implements the unitary operation .. math:: U(t) = e^{-itP}. Since only a single Pauli string is evolved the circuit decomposition is exact. Args: pauli: The Pauli to evolve. time: The evolution time. cx_structure: Determine the structure of CX gates, can be either "chain" for next-neighbor connections or "fountain" to connect directly to the top qubit. label: A label for the gate. Returns: A quantum circuit implementing the time evolution of the Pauli. """ num_non_identity = len([label for label in pauli.to_label() if label != "I"]) # first check, if the Pauli is only the identity, in which case the evolution only # adds a global phase if num_non_identity == 0: definition = QuantumCircuit(pauli.num_qubits, global_phase=-time) # if we evolve on a single qubit, if yes use the corresponding qubit rotation elif num_non_identity == 1: definition = _single_qubit_evolution(pauli, time) # same for two qubits, use Qiskit's native rotations elif num_non_identity == 2: definition = _two_qubit_evolution(pauli, time, cx_structure) # otherwise do basis transformation and CX chains else: definition = _multi_qubit_evolution(pauli, time, cx_structure) definition.name = f"exp(it {pauli.to_label()})" return definition
def _dec_ucg(self): """ Call to create a circuit that implements the uniformly controlled gate. If up_to_diagonal=True, the circuit implements the gate up to a diagonal gate and the diagonal gate is also returned. """ diag = np.ones(2**self.num_qubits).tolist() q = QuantumRegister(self.num_qubits) q_controls = q[1:] q_target = q[0] circuit = QuantumCircuit(q) # If there is no control, we use the ZYZ decomposition if not q_controls: theta, phi, lamb = euler_angles_1q(self.params[0]) circuit.u3(theta, phi, lamb, q) return circuit, diag # If there is at least one control, first, # we find the single qubit gates of the decomposition. (single_qubit_gates, diag) = self._dec_ucg_help() # Now, it is easy to place the C-NOT gates and some Hadamards and Rz(pi/2) gates # (which are absorbed into the single-qubit unitaries) to get back the full decomposition. for i, gate in enumerate(single_qubit_gates): # Absorb Hadamards and Rz(pi/2) gates if i == 0: squ = HGate().to_matrix().dot(gate) elif i == len(single_qubit_gates) - 1: squ = gate.dot(UCG._rz(np.pi / 2)).dot(HGate().to_matrix()) else: squ = HGate().to_matrix().dot(gate.dot(UCG._rz( np.pi / 2))).dot(HGate().to_matrix()) # Add single-qubit gate circuit.squ(squ, q_target) # The number of the control qubit is given by the number of zeros at the end # of the binary representation of (i+1) binary_rep = np.binary_repr(i + 1) num_trailing_zeros = len(binary_rep) - len(binary_rep.rstrip('0')) q_contr_index = num_trailing_zeros # Add C-NOT gate if not i == len(single_qubit_gates) - 1: circuit.cx(q_controls[q_contr_index], q_target) if not self.up_to_diagonal: # Important: the diagonal gate is given in the computational basis of the qubits # q[k-1],...,q[0],q_target (ordered with decreasing significance), # where q[i] are the control qubits and t denotes the target qubit. circuit.diag_gate(diag.tolist(), q) return circuit, diag
def _define(self): """Define the MCX gate using recursion.""" # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(self.num_qubits, name="q") qc = QuantumCircuit(q, name=self.name) if self.num_qubits == 4: qc._append(C3XGate(), q[:], []) self.definition = qc elif self.num_qubits == 5: qc._append(C4XGate(), q[:], []) self.definition = qc else: for instr, qargs, cargs in self._recurse(q[:-1], q_ancilla=q[-1]): qc._append(instr, qargs, cargs) self.definition = qc
def diagonalizing_clifford(pauli: Pauli) -> QuantumCircuit: """Get the clifford circuit to diagonalize the Pauli operator. Args: pauli: The Pauli to diagonalize. Returns: A circuit to diagonalize. """ cliff = QuantumCircuit(pauli.num_qubits) for i, pauli_i in enumerate(reversed(pauli.to_label())): if pauli_i == "Y": cliff.sdg(i) if pauli_i in ["X", "Y"]: cliff.h(i) return cliff
def _define(self): """ gate rzx(theta) a, b { h b; cx a, b; u1(theta) b; cx a, b; h b;} """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .h import HGate from .x import CXGate from .rz import RZGate theta = self.params[0] q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) rules = [(HGate(), [q[1]], []), (CXGate(), [q[0], q[1]], []), (RZGate(theta), [q[1]], []), (CXGate(), [q[0], q[1]], []), (HGate(), [q[1]], [])] qc._data = rules self.definition = qc
def _define(self): """ gate sx a { rz(-pi/2) a; h a; rz(-pi/2); } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .s import SdgGate from .h import HGate q = QuantumRegister(1, 'q') qc = QuantumCircuit(q, name=self.name, global_phase=pi / 4) rules = [ (SdgGate(), [q[0]], []), (HGate(), [q[0]], []), (SdgGate(), [q[0]], []) ] qc.data = rules self.definition = qc
def _define(self): """ gate cz a,b { h b; cx a,b; h b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .h import HGate from .x import CXGate q = QuantumRegister(2, "q") qc = QuantumCircuit(q, name=self.name) rules = [(HGate(), [q[1]], []), (CXGate(), [q[0], q[1]], []), (HGate(), [q[1]], [])] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def _define(self): """ gate csx a,b { h b; cu1(pi/2) a,b; h b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .h import HGate from .u1 import CU1Gate q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) rules = [ (HGate(), [q[1]], []), (CU1Gate(pi/2), [q[0], q[1]], []), (HGate(), [q[1]], []) ] qc.data = rules self.definition = qc
def _define(self): # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(self.num_qubits, 'q') qc = QuantumCircuit(q, name=self.name) if self.num_ctrl_qubits == 0: qc.p(self.params[0], 0) if self.num_ctrl_qubits == 1: qc.cp(self.params[0], 0, 1) else: from .u3 import _gray_code_chain scaled_lam = self.params[0] / (2 ** (self.num_ctrl_qubits - 1)) bottom_gate = CPhaseGate(scaled_lam) definition = _gray_code_chain(q, self.num_ctrl_qubits, bottom_gate) qc.data = definition self.definition = qc
def __init__(self, num_qubits: int, theta: Union[List[List[float]], np.ndarray]) -> None: """Create a new Global Mølmer–Sørensen (GMS) gate. Args: num_qubits: width of gate. theta: a num_qubits x num_qubits symmetric matrix of interaction angles for each qubit pair. The upper triangle is considered. """ super().__init__(num_qubits, name="gms") if not isinstance(theta, list): theta = [theta] * int((num_qubits ** 2 - 1) / 2) gms = QuantumCircuit(num_qubits, name="gms") for i in range(self.num_qubits): for j in range(i + 1, self.num_qubits): gms.append(RXXGate(theta[i][j]), [i, j]) self.append(gms.to_gate(), self.qubits)
def _define(self): """ gate pauli (p1 a1,...,pn an) { p1 a1; ... ; pn an; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit gates = {"X": XGate, "Y": YGate, "Z": ZGate} q = QuantumRegister(len(self.params[0]), "q") qc = QuantumCircuit(q, name=f"{self.name}({self.params[0]})") paulis = self.params[0] for i, p in enumerate(reversed(paulis)): if p == "I": continue qc._append(CircuitInstruction(gates[p](), (q[i], ), ())) self.definition = qc
def test_pauli_gate(self, method, device, pauli): """Test multi-qubit Pauli gate.""" pauli = qi.Pauli(pauli) circuit = QuantumCircuit(pauli.num_qubits) circuit.append(pauli, range(pauli.num_qubits)) backend = self.backend(method=method, device=device) label = 'final' if method == 'density_matrix': target = qi.DensityMatrix(circuit) circuit.save_density_matrix(label=label) state_fn = qi.DensityMatrix fidelity_fn = qi.state_fidelity elif method == 'stabilizer': target = qi.Clifford(circuit) circuit.save_stabilizer(label=label) state_fn = qi.Clifford.from_dict fidelity_fn = qi.process_fidelity elif method == 'unitary': target = qi.Operator(circuit) circuit.save_unitary(label=label) state_fn = qi.Operator fidelity_fn = qi.process_fidelity elif method == 'superop': target = qi.SuperOp(circuit) circuit.save_superop(label=label) state_fn = qi.SuperOp fidelity_fn = qi.process_fidelity else: target = qi.Statevector(circuit) circuit.save_statevector(label=label) state_fn = qi.Statevector fidelity_fn = qi.state_fidelity result = backend.run(transpile(circuit, backend, optimization_level=0), shots=1).result() # Check results success = getattr(result, 'success', False) self.assertTrue(success) data = result.data(0) self.assertIn(label, data) value = state_fn(data[label]) fidelity = fidelity_fn(target, value) self.assertGreater(fidelity, 0.9999)
def _define(self): """ gate c3sqrtx a,b,c,d { h d; cu1(-pi/8) a,d; h d; cx a,b; h d; cu1(pi/8) b,d; h d; cx a,b; h d; cu1(-pi/8) b,d; h d; cx b,c; h d; cu1(pi/8) c,d; h d; cx a,c; h d; cu1(-pi/8) c,d; h d; cx b,c; h d; cu1(pi/8) c,d; h d; cx a,c; h d; cu1(-pi/8) c,d; h d; } gate c4x a,b,c,d,e { h e; cu1(-pi/2) d,e; h e; c3x a,b,c,d; h d; cu1(pi/4) d,e; h d; c3x a,b,c,d; c3sqrtx a,b,c,e; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u1 import CU1Gate q = QuantumRegister(5, name='q') qc = QuantumCircuit(q, name=self.name) rules = [ (HGate(), [q[4]], []), (CU1Gate(-numpy.pi / 2), [q[3], q[4]], []), (HGate(), [q[4]], []), (C3XGate(), [q[0], q[1], q[2], q[3]], []), (HGate(), [q[4]], []), (CU1Gate(numpy.pi / 2), [q[3], q[4]], []), (HGate(), [q[4]], []), (C3XGate(), [q[0], q[1], q[2], q[3]], []), (C3XGate(numpy.pi / 8), [q[0], q[1], q[2], q[4]], []), ] qc._data = rules self.definition = qc
def _define(self): """ gate ecr a, b { rzx(pi/4) a, b; x a; rzx(-pi/4) a, b;} """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(2, "q") qc = QuantumCircuit(q, name=self.name) rules = [ (RZXGate(np.pi / 4), [q[0], q[1]], []), (XGate(), [q[0]], []), (RZXGate(-np.pi / 4), [q[0], q[1]], []), ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def _define(self): """ gate cphase(lambda) a,b { phase(lambda/2) a; cx a,b; phase(-lambda/2) b; cx a,b; phase(lambda/2) b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) qc.p(self.params[0] / 2, 0) qc.cx(0, 1) qc.p(-self.params[0] / 2, 1) qc.cx(0, 1) qc.p(self.params[0] / 2, 1) self.definition = qc
def synthesize(self, evolution): # get operators and time to evolve operators = evolution.operator time = evolution.time # construct the evolution circuit evolution_circuit = QuantumCircuit(operators[0].num_qubits) if not isinstance(operators, list): matrix = operators.to_matrix() else: matrix = sum(op.to_matrix() for op in operators) exp = expm(-1j * time * matrix) evolution_circuit.unitary(exp, evolution_circuit.qubits) return evolution_circuit
def _define(self): # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit q = QuantumRegister(self.num_qubits, 'q') qc = QuantumCircuit(q, name=self.name) if self.num_ctrl_qubits == 0: definition = U1Gate(self.params[0]).definition if self.num_ctrl_qubits == 1: definition = CU1Gate(self.params[0]).definition else: from .u3 import _gray_code_chain scaled_lam = self.params[0] / (2 ** (self.num_ctrl_qubits - 1)) bottom_gate = CU1Gate(scaled_lam) definition = _gray_code_chain(q, self.num_ctrl_qubits, bottom_gate) for instr, qargs, cargs in definition: qc._append(instr, qargs, cargs) self.definition = qc
def _circuit_xyx(theta, phi, lam, phase, simplify=True, atol=DEFAULT_ATOL): qr = QuantumRegister(1, 'qr') circuit = QuantumCircuit(qr, global_phase=phase) if simplify and math.isclose(theta, 0.0, abs_tol=atol): circuit._append(RXGate(phi + lam), [qr[0]], []) return circuit if not simplify or not math.isclose(lam, 0.0, abs_tol=atol): circuit._append(RXGate(lam), [qr[0]], []) if not simplify or not math.isclose(theta, 0.0, abs_tol=atol): circuit._append(RYGate(theta), [qr[0]], []) if not simplify or not math.isclose(phi, 0.0, abs_tol=atol): circuit._append(RXGate(phi), [qr[0]], []) return circuit
def _define(self): """ gate cswap a,b,c { cx c,b; ccx a,b,c; cx c,b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .x import CXGate, CCXGate q = QuantumRegister(3, 'q') qc = QuantumCircuit(q, name=self.name) rules = [(CXGate(), [q[2], q[1]], []), (CCXGate(), [q[0], q[1], q[2]], []), (CXGate(), [q[2], q[1]], [])] qc._data = rules self.definition = qc
def _build_additional_layers(self, circuit, which): if which == "appended": blocks = self._appended_blocks entanglements = self._appended_entanglement elif which == "prepended": blocks = reversed(self._prepended_blocks) entanglements = reversed(self._prepended_entanglement) else: raise ValueError("`which` must be either `appended` or `prepended`.") for block, ent in zip(blocks, entanglements): layer = QuantumCircuit(*self.qregs) if isinstance(ent, str): ent = get_entangler_map(block.num_qubits, self.num_qubits, ent) for indices in ent: layer.compose(block, indices, inplace=True) circuit.compose(layer, inplace=True)
def inverse(self): """Return the inverse. This does not re-compute the decomposition for the multiplexer with the inverse of the gates but simply inverts the existing decomposition. """ inverse_gate = Gate( name=self.name + "_dg", num_qubits=self.num_qubits, params=[]) # removing the params because arrays are deprecated definition = QuantumCircuit(*self.definition.qregs) for inst in reversed(self._definition): definition._append( inst.replace(operation=inst.operation.inverse())) definition.global_phase = -self.definition.global_phase inverse_gate.definition = definition return inverse_gate
def _define(self): """ gate crz(lambda) a,b { u1(lambda/2) b; cx a,b; u1(-lambda/2) b; cx a,b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u1 import U1Gate from .x import CXGate q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) rules = [(U1Gate(self.params[0] / 2), [q[1]], []), (CXGate(), [q[0], q[1]], []), (U1Gate(-self.params[0] / 2), [q[1]], []), (CXGate(), [q[0], q[1]], [])] qc._data = rules self.definition = qc
def _build_additional_layers(self, which): if which == 'appended': blocks = self._appended_blocks entanglements = self._appended_entanglement elif which == 'prepended': blocks = reversed(self._prepended_blocks) entanglements = reversed(self._prepended_entanglement) else: raise ValueError( '`which` must be either `appended` or `prepended`.') for i, (block, ent) in enumerate(zip(blocks, entanglements)): layer = QuantumCircuit(*self.qregs) if isinstance(ent, str): ent = get_entangler_map(block.num_qubits, self.num_qubits, ent) for indices in ent: layer.compose(block, indices, inplace=True) self += layer
def _define(self): """ gate xx_minus_yy(theta, beta) a, b { rz(-beta) b; rz(-pi/2) a; sx a; rz(pi/2) a; s b; cx a, b; ry(theta/2) a; ry(-theta/2) b; cx a, b; sdg b; rz(-pi/2) a; sxdg a; rz(pi/2) a; rz(beta) b; } """ theta, beta = self.params register = QuantumRegister(2, "q") circuit = QuantumCircuit(register, name=self.name) a, b = register rules = [ (RZGate(-beta), [b], []), (RZGate(-pi / 2), [a], []), (SXGate(), [a], []), (RZGate(pi / 2), [a], []), (SGate(), [b], []), (CXGate(), [a, b], []), (RYGate(theta / 2), [a], []), (RYGate(-theta / 2), [b], []), (CXGate(), [a, b], []), (SdgGate(), [b], []), (RZGate(-pi / 2), [a], []), (SXdgGate(), [a], []), (RZGate(pi / 2), [a], []), (RZGate(beta), [b], []), ] for instr, qargs, cargs in rules: circuit._append(instr, qargs, cargs) self.definition = circuit
def _circuit_u321(theta, phi, lam, phase, simplify=True, atol=DEFAULT_ATOL): rtol = 1e-9 # default is 1e-5, too far from atol=1e-12 qr = QuantumRegister(1, 'qr') circuit = QuantumCircuit(qr, global_phase=phase) if simplify and (math.isclose(theta, 0.0, abs_tol=atol, rel_tol=rtol)): phi_lam = phi + lam if not (math.isclose(phi_lam, 0.0, abs_tol=atol, rel_tol=rtol) or math.isclose(phi_lam, 2*np.pi, abs_tol=atol, rel_tol=rtol)): circuit._append(U1Gate(_mod2pi(phi+lam)), [qr[0]], []) elif simplify and math.isclose(theta, np.pi/2, abs_tol=atol, rel_tol=rtol): circuit._append(U2Gate(phi, lam), [qr[0]], []) else: circuit._append(U3Gate(theta, phi, lam), [qr[0]], []) return circuit
def cnot_chain(pauli: Pauli) -> QuantumCircuit: """CX chain. For example, for the Pauli with the label 'XYZIX'. .. parsed-literal:: ┌───┐ q_0: ──────────┤ X ├ └─┬─┘ q_1: ────────────┼── ┌───┐ │ q_2: ─────┤ X ├──■── ┌───┐└─┬─┘ q_3: ┤ X ├──■─────── └─┬─┘ q_4: ──■──────────── Args: pauli: The Pauli for which to construct the CX chain. Returns: A circuit implementing the CX chain. """ chain = QuantumCircuit(pauli.num_qubits) control, target = None, None # iterate over the Pauli's and add CNOTs for i, pauli_i in enumerate(pauli.to_label()): i = pauli.num_qubits - i - 1 if pauli_i != "I": if control is None: control = i else: target = i if control is not None and target is not None: chain.cx(control, target) control = i target = None return chain
def integrate_circuit( qc: QuantumCircuit, target_qubits: List[int], target_classical_bits: Optional[List[int]] = None, number_of_qubits: int = 5, add_measurements: bool = True, ) -> QuantumCircuit: """ Integrate circuit at specified qubits in a larger qubit system This can be used for example to integrate a single-qubit experiment in a 5-qubit circuit to be executed on a 5-qubit device. Args: qc: QuantumCircuit to be integrated target_qubits: List of qubits to map the circuit on target_classical_bits: If None, then use the registers allocated to the target qubits number_of_qubits: Number of qubits in the target system add_measurements: If True, then add a measure statement for all the new qubits Returns: Integrated circuit """ if qc.num_qubits > number_of_qubits: raise CircuitError( f'number of qubits {qc.num_qubits} in the specified circuit cannot exceed specified number of qubits {number_of_qubits} in the target system' ) output_qc = QuantumCircuit(number_of_qubits, number_of_qubits) qbits = [output_qc.qregs[0][i] for i in target_qubits] if target_classical_bits is None: cbits = [output_qc.cregs[0][i] for i in target_qubits] else: cbits = [output_qc.cregs[0][i] for i in target_classical_bits] output_qc = output_qc.compose(qc, qubits=qbits, clbits=cbits) if add_measurements: for qubit_index in range(number_of_qubits): if qubit_index not in target_qubits: output_qc.measure(qubit_index, qubit_index) return output_qc
def _define(self): """ gate ccx a,b,c { h c; cx b,c; tdg c; cx a,c; t c; cx b,c; tdg c; cx a,c; t b; t c; h c; cx a,b; t a; tdg b; cx a,b;} """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit # ┌───┐ # q_0: ───────────────────■─────────────────────■────■───┤ T ├───■── # │ ┌───┐ │ ┌─┴─┐┌┴───┴┐┌─┴─┐ # q_1: ───────■───────────┼─────────■───┤ T ├───┼──┤ X ├┤ Tdg ├┤ X ├ # ┌───┐┌─┴─┐┌─────┐┌─┴─┐┌───┐┌─┴─┐┌┴───┴┐┌─┴─┐├───┤└┬───┬┘└───┘ # q_2: ┤ H ├┤ X ├┤ Tdg ├┤ X ├┤ T ├┤ X ├┤ Tdg ├┤ X ├┤ T ├─┤ H ├────── # └───┘└───┘└─────┘└───┘└───┘└───┘└─────┘└───┘└───┘ └───┘ q = QuantumRegister(3, "q") qc = QuantumCircuit(q, name=self.name) rules = [ (HGate(), [q[2]], []), (CXGate(), [q[1], q[2]], []), (TdgGate(), [q[2]], []), (CXGate(), [q[0], q[2]], []), (TGate(), [q[2]], []), (CXGate(), [q[1], q[2]], []), (TdgGate(), [q[2]], []), (CXGate(), [q[0], q[2]], []), (TGate(), [q[1]], []), (TGate(), [q[2]], []), (HGate(), [q[2]], []), (CXGate(), [q[0], q[1]], []), (TGate(), [q[0]], []), (TdgGate(), [q[1]], []), (CXGate(), [q[0], q[1]], []), ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def circuit( self, *, euler_basis: Optional[str] = None, simplify=False, atol=DEFAULT_ATOL ) -> QuantumCircuit: """Returns Weyl decomposition in circuit form. simplify, atol arguments are passed to OneQubitEulerDecomposer""" if euler_basis is None: euler_basis = self._default_1q_basis oneq_decompose = OneQubitEulerDecomposer(euler_basis) c1l, c1r, c2l, c2r = ( oneq_decompose(k, simplify=simplify, atol=atol) for k in (self.K1l, self.K1r, self.K2l, self.K2r) ) circ = QuantumCircuit(2, global_phase=self.global_phase) circ.compose(c2r, [0], inplace=True) circ.compose(c2l, [1], inplace=True) self._weyl_gate(simplify, circ, atol) circ.compose(c1r, [0], inplace=True) circ.compose(c1l, [1], inplace=True) return circ