示例#1
0
 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
示例#2
0
    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)
示例#3
0
    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
示例#4
0
    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
示例#5
0
    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