def _define(self): """Calculate a subcircuit that implements this unitary.""" if self.num_qubits == 1: q = QuantumRegister(1, "q") qc = QuantumCircuit(q, name=self.name) theta, phi, lam, global_phase = _DECOMPOSER1Q.angles_and_phase( self.to_matrix()) qc._append(U3Gate(theta, phi, lam), [q[0]], []) qc.global_phase = global_phase self.definition = qc elif self.num_qubits == 2: self.definition = two_qubit_cnot_decompose(self.to_matrix()) else: q = QuantumRegister(self.num_qubits, "q") qc = QuantumCircuit(q, name=self.name) qc.append(isometry.Isometry(self.to_matrix(), 0, 0), qargs=q[:]) self.definition = qc
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: invalid ctrl_state """ cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits) iso = isometry.Isometry(cmat, 0, 0) return ControlledGate('c-unitary', self.num_qubits + num_ctrl_qubits, cmat, definition=iso.definition, label=label)
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): r"""Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: Invalid ctrl_state. ExtensionError: Non-unitary controlled unitary. """ cmat = _compute_control_matrix(self.to_matrix(), num_ctrl_qubits, ctrl_state=ctrl_state) iso = isometry.Isometry(cmat, 0, 0) cunitary = ControlledGate('c-unitary', num_qubits=self.num_qubits + num_ctrl_qubits, params=[cmat], label=label, num_ctrl_qubits=num_ctrl_qubits, definition=iso.definition, ctrl_state=ctrl_state) from qiskit.quantum_info import Operator # hack to correct global phase; should fix to prevent need for correction here pmat = (Operator(iso.inverse()).data @ cmat) diag = numpy.diag(pmat) if not numpy.allclose(diag, diag[0]): raise ExtensionError('controlled unitary generation failed') phase = numpy.angle(diag[0]) if phase: qreg = cunitary.definition.qregs[0] cunitary.definition.u3(numpy.pi, phase, phase - numpy.pi, qreg[0]) cunitary.definition.u3(numpy.pi, 0, numpy.pi, qreg[0]) cunitary.base_gate = self.copy() cunitary.base_gate.label = self.label return cunitary
def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None): """Return controlled version of gate Args: num_ctrl_qubits (int): number of controls to add to gate (default=1) label (str): optional gate label ctrl_state (int or str or None): The control state in decimal or as a bit string (e.g. '1011'). If None, use 2**num_ctrl_qubits-1. Returns: UnitaryGate: controlled version of gate. Raises: QiskitError: Invalid ctrl_state. ExtensionError: Non-unitary controlled unitary. """ mat = self.to_matrix() cmat = _compute_control_matrix(mat, num_ctrl_qubits, ctrl_state=None) iso = isometry.Isometry(cmat, 0, 0) cunitary = ControlledGate( "c-unitary", num_qubits=self.num_qubits + num_ctrl_qubits, params=[mat], label=label, num_ctrl_qubits=num_ctrl_qubits, definition=iso.definition, ctrl_state=ctrl_state, base_gate=self.copy(), ) from qiskit.quantum_info import Operator # hack to correct global phase; should fix to prevent need for correction here pmat = Operator(iso.inverse()).data @ cmat diag = numpy.diag(pmat) if not numpy.allclose(diag, diag[0]): raise ExtensionError("controlled unitary generation failed") phase = numpy.angle(diag[0]) if phase: # need to apply to _definition since open controls creates temporary definition cunitary._definition.global_phase = phase return cunitary
def run(self, dag: DAGCircuit) -> DAGCircuit: """Run the UnitarySynthesis pass on `dag`. Args: dag: input dag. Returns: Output dag with UnitaryGates synthesized to target basis. """ euler_basis = _choose_euler_basis(self._basis_gates) kak_gate = _choose_kak_gate(self._basis_gates) decomposer1q, decomposer2q = None, None if euler_basis is not None: decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer( euler_basis) if kak_gate is not None: decomposer2q = TwoQubitBasisDecomposer(kak_gate, euler_basis=euler_basis) for node in dag.named_nodes("unitary"): synth_dag = None if len(node.qargs) == 1: if decomposer1q is None: continue synth_dag = circuit_to_dag( decomposer1q._decompose(node.op.to_matrix())) elif len(node.qargs) == 2: if decomposer2q is None: continue synth_dag = circuit_to_dag( decomposer2q(node.op.to_matrix(), basis_fidelity=self._approximation_degree)) else: synth_dag = circuit_to_dag( isometry.Isometry(node.op.to_matrix(), 0, 0).definition) dag.substitute_node_with_dag(node, synth_dag) return dag