def _define(self): """ gate swap a,b { cx a,b; cx b,a; cx a,b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .x import CXGate q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) rules = [ (CXGate(), [q[0], q[1]], []), (CXGate(), [q[1], q[0]], []), (CXGate(), [q[0], q[1]], []) ] qc.data = rules self.definition = qc
def _define(self): """ gate tdg a { u1(pi/4) a; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u1 import U1Gate q = QuantumRegister(1, 'q') qc = QuantumCircuit(q, name=self.name) rules = [ (U1Gate(-pi / 4), [q[0]], []) ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
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 _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 _copy_circuit_metadata(source_dag, coupling_map): """Return a copy of source_dag with metadata but empty. Generate only a single qreg in the output DAG, matching the size of the coupling_map. """ target_dag = DAGCircuit() target_dag.name = source_dag.name for creg in source_dag.cregs.values(): target_dag.add_creg(creg) device_qreg = QuantumRegister(len(coupling_map.physical_qubits), 'q') target_dag.add_qreg(device_qreg) return target_dag
def _define(self): """ gate ry(theta) a { r(theta, pi/2) a; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .r import RGate q = QuantumRegister(1, 'q') qc = QuantumCircuit(q, name=self.name) rules = [ (RGate(self.params[0], pi / 2), [q[0]], []) ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def _define(self): """ gate r(θ, φ) a {u3(θ, φ - π/2, -φ + π/2) a;} """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u3 import U3Gate q = QuantumRegister(1, 'q') qc = QuantumCircuit(q, name=self.name) theta = self.params[0] phi = self.params[1] rules = [(U3Gate(theta, phi - pi / 2, -phi + pi / 2), [q[0]], [])] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def __call__(self, target, basis_fidelity=None): """Decompose a two-qubit unitary over fixed basis + SU(2) using the best approximation given that each basis application has a finite fidelity. """ basis_fidelity = basis_fidelity or self.basis_fidelity if hasattr(target, 'to_operator'): # If input is a BaseOperator subclass this attempts to convert # the object to an Operator so that we can extract the underlying # numpy matrix from `Operator.data`. target = target.to_operator().data if hasattr(target, 'to_matrix'): # If input is Gate subclass or some other class object that has # a to_matrix method this will call that method. target = target.to_matrix() # Convert to numpy array incase not already an array target = np.asarray(target, dtype=complex) # Check input is a 2-qubit unitary if target.shape != (4, 4): raise QiskitError( "TwoQubitBasisDecomposer: expected 4x4 matrix for target") if not is_unitary_matrix(target): raise QiskitError( "TwoQubitBasisDecomposer: target matrix is not unitary.") target_decomposed = TwoQubitWeylDecomposition(target) traces = self.traces(target_decomposed) expected_fidelities = [ trace_to_fid(traces[i]) * basis_fidelity**i for i in range(4) ] best_nbasis = np.argmax(expected_fidelities) decomposition = self.decomposition_fns[best_nbasis](target_decomposed) decomposition_angles = [_DECOMPOSER1Q.angles(x) for x in decomposition] q = QuantumRegister(2) return_circuit = QuantumCircuit(q) for i in range(best_nbasis): return_circuit.append(U3Gate(*decomposition_angles[2 * i]), [q[0]]) return_circuit.append(U3Gate(*decomposition_angles[2 * i + 1]), [q[1]]) return_circuit.append(self.gate, [q[0], q[1]]) return_circuit.append(U3Gate(*decomposition_angles[2 * best_nbasis]), [q[0]]) return_circuit.append( U3Gate(*decomposition_angles[2 * best_nbasis + 1]), [q[1]]) return return_circuit
def _define(self): """ gate c3x a,b,c,d { h d; cu1(-pi/4) a,d; h d; cx a,b; h d; cu1(pi/4) b,d; h d; cx a,b; h d; cu1(-pi/4) b,d; h d; cx b,c; h d; cu1(pi/4) c,d; h d; cx a,c; h d; cu1(-pi/4) c,d; h d; cx b,c; h d; cu1(pi/4) c,d; h d; cx a,c; h d; cu1(-pi/4) c,d; h d; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u1 import CU1Gate q = QuantumRegister(4, name='q') rules = [(HGate(), [q[3]], []), (CU1Gate(-self._angle), [q[0], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[0], q[1]], []), (HGate(), [q[3]], []), (CU1Gate(self._angle), [q[1], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[0], q[1]], []), (HGate(), [q[3]], []), (CU1Gate(-self._angle), [q[1], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[1], q[2]], []), (HGate(), [q[3]], []), (CU1Gate(self._angle), [q[2], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[0], q[2]], []), (HGate(), [q[3]], []), (CU1Gate(-self._angle), [q[2], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[1], q[2]], []), (HGate(), [q[3]], []), (CU1Gate(self._angle), [q[2], q[3]], []), (HGate(), [q[3]], []), (CXGate(), [q[0], q[2]], []), (HGate(), [q[3]], []), (CU1Gate(-self._angle), [q[2], q[3]], []), (HGate(), [q[3]], [])] qc = QuantumCircuit(q) qc._data = rules self.definition = qc
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; rc3x a,b,c,d; h e; cu1(pi/4) d,e; h e; rc3x 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]], []), (RC3XGate(), [q[0], q[1], q[2], q[3]], []), (HGate(), [q[4]], []), (CU1Gate(numpy.pi / 2), [q[3], q[4]], []), (HGate(), [q[4]], []), (RC3XGate().inverse(), [q[0], q[1], q[2], q[3]], []), (C3SXGate(), [q[0], q[1], q[2], q[4]], []), ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def _define(self): """ gate cswap a,b,c { cx c,b; ccx a,b,c; cx c,b; } """ from .x import CXGate, CCXGate definition = [] q = QuantumRegister(3, 'q') rule = [(CXGate(), [q[2], q[1]], []), (CCXGate(), [q[0], q[1], q[2]], []), (CXGate(), [q[2], q[1]], [])] for inst in rule: definition.append(inst) self.definition = definition
def _define(self): """ gate rz(phi) a { u1(phi) a; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .u1 import U1Gate q = QuantumRegister(1, 'q') theta = self.params[0] qc = QuantumCircuit(q, name=self.name, global_phase=-theta / 2) rules = [ (U1Gate(theta), [q[0]], []) ] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
def extend_back(self, dag, edge_map=None): """Add `dag` at the end of `self`, using `edge_map`. """ edge_map = edge_map or {} for qreg in dag.qregs.values(): if qreg.name not in self.qregs: self.add_qreg(QuantumRegister(qreg.size, qreg.name)) edge_map.update([(qbit, qbit) for qbit in qreg if qbit not in edge_map]) for creg in dag.cregs.values(): if creg.name not in self.cregs: self.add_creg(ClassicalRegister(creg.size, creg.name)) edge_map.update([(cbit, cbit) for cbit in creg if cbit not in edge_map]) self.compose_back(dag, edge_map)
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 circuit_to_instruction(circuit): """Build an ``Instruction`` object from a ``QuantumCircuit``. The instruction is anonymous (not tied to a named quantum register), and so can be inserted into another circuit. The instruction will have the same string name as the circuit. Args: circuit (QuantumCircuit): the input circuit. Return: Instruction: an instruction equivalent to the action of the input circuit. Upon decomposition, this instruction will yield the components comprising the original circuit. """ instruction = Instruction(name=circuit.name, num_qubits=sum([qreg.size for qreg in circuit.qregs]), num_clbits=sum([creg.size for creg in circuit.cregs]), params=[]) instruction.control = None def find_bit_position(bit): """find the index of a given bit (Register, int) within a flat ordered list of bits of the circuit """ if isinstance(bit[0], QuantumRegister): ordered_regs = circuit.qregs else: ordered_regs = circuit.cregs reg_index = ordered_regs.index(bit[0]) return sum([reg.size for reg in ordered_regs[:reg_index]]) + bit[1] definition = circuit.data.copy() if instruction.num_qubits > 0: q = QuantumRegister(instruction.num_qubits, 'q') if instruction.num_clbits > 0: c = ClassicalRegister(instruction.num_clbits, 'c') definition = list(map(lambda x: (x[0], list(map(lambda y: (q, find_bit_position(y)), x[1])), list(map(lambda y: (c, find_bit_position(y)), x[2]))), definition)) instruction.definition = definition return instruction
def __call__(self, target, basis_fidelity=None, *, _num_basis_uses=None) -> QuantumCircuit: """Decompose a two-qubit unitary over fixed basis + SU(2) using the best approximation given that each basis application has a finite fidelity. You can force a particular approximation by passing _num_basis_uses. """ basis_fidelity = basis_fidelity or self.basis_fidelity target = np.asarray(target, dtype=complex) target_decomposed = TwoQubitWeylDecomposition(target) traces = self.traces(target_decomposed) expected_fidelities = [ trace_to_fid(traces[i]) * basis_fidelity**i for i in range(4) ] best_nbasis = int(np.argmax(expected_fidelities)) if _num_basis_uses is not None: best_nbasis = _num_basis_uses decomposition = self.decomposition_fns[best_nbasis](target_decomposed) decomposition_euler = [ self._decomposer1q._decompose(x) for x in decomposition ] q = QuantumRegister(2) return_circuit = QuantumCircuit(q) return_circuit.global_phase = target_decomposed.global_phase return_circuit.global_phase -= best_nbasis * self.basis.global_phase if best_nbasis == 2: return_circuit.global_phase += np.pi for i in range(best_nbasis): return_circuit.compose(decomposition_euler[2 * i], [q[0]], inplace=True) return_circuit.compose(decomposition_euler[2 * i + 1], [q[1]], inplace=True) return_circuit.append(self.gate, [q[0], q[1]]) return_circuit.compose(decomposition_euler[2 * best_nbasis], [q[0]], inplace=True) return_circuit.compose(decomposition_euler[2 * best_nbasis + 1], [q[1]], inplace=True) return return_circuit
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 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): """ 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 _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(UCGate._rz(np.pi / 2)).dot(HGate().to_matrix()) else: squ = HGate().to_matrix().dot(gate.dot(UCGate._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.diagonal(diag.tolist(), q) return circuit, diag
def _define(self): """ gate rc3x a,b,c,d { u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; cx a,d; u1(pi/4) d; cx b,d; u1(-pi/4) d; u2(0,pi) d; u1(pi/4) d; cx c,d; u1(-pi/4) d; u2(0,pi) d; } """ q = QuantumRegister(4, 'q') definition = [ (U2Gate(0, pi), [q[3]], []), # H gate (U1Gate(pi / 4), [q[3]], []), # T gate (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), # inverse T gate (U2Gate(0, pi), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (CXGate(), [q[0], q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[1], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), (U1Gate(pi / 4), [q[3]], []), (CXGate(), [q[2], q[3]], []), (U1Gate(-pi / 4), [q[3]], []), (U2Gate(0, pi), [q[3]], []), ] self.definition = definition
def _define(self): """ gate rzz(theta) a, b { cx a, b; u1(theta) b; cx a, b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .x import CXGate from .rz import RZGate q = QuantumRegister(2, 'q') theta = self.params[0] qc = QuantumCircuit(q, name=self.name) rules = [(CXGate(), [q[0], q[1]], []), (RZGate(theta), [q[1]], []), (CXGate(), [q[0], q[1]], [])] for instr, qargs, cargs in rules: qc._append(instr, qargs, cargs) self.definition = qc
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 _define(self): """ gate cy a,b { sdg b; cx a,b; s b; } """ # pylint: disable=cyclic-import from qiskit.circuit.quantumcircuit import QuantumCircuit from .s import SGate, SdgGate from .x import CXGate q = QuantumRegister(2, 'q') qc = QuantumCircuit(q, name=self.name) rules = [ (SdgGate(), [q[1]], []), (CXGate(), [q[0], q[1]], []), (SGate(), [q[1]], []) ] qc._data = rules self.definition = qc
def _define(self): """ Gate Ry(theta) to Rz(-pi/2)·Rx(theta)·Rz(pi/2) """ definition = [] q = QuantumRegister(1, 'q') if self.params[0] == 0: rule = [(RZGate(0), [q[0]], [])] elif self.params[0] % (2 * pi) == 0: rule = [(RZGate(0), [q[0]], [])] else: rule = [(RZGate(-pi / 2), [q[0]], []), (RXGate(self.params[0]), [q[0]], []), (RZGate(pi / 2), [q[0]], [])] for inst in rule: definition.append(inst) self.definition = definition
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 = PhaseGate(scaled_lam) definition = _gray_code_chain(q, self.num_ctrl_qubits, bottom_gate) qc.data = definition self.definition = qc
def _define(self): """ gate crz(lambda) a,b { u1(lambda/2) b; cx a,b; u1(-lambda/2) b; cx a,b; } """ from .u1 import U1Gate from .x import CXGate definition = [] q = QuantumRegister(2, 'q') rule = [(U1Gate(self.params[0] / 2), [q[1]], []), (CXGate(), [q[0], q[1]], []), (U1Gate(-self.params[0] / 2), [q[1]], []), (CXGate(), [q[0], q[1]], [])] for inst in rule: definition.append(inst) self.definition = definition
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): # 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 _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