def _decompose_two_qubit_unitaries(self, op: ops.Operation) -> ops.OP_TREE:
     # Known matrix?
     if len(op.qubits) == 2:
         mat = protocols.unitary(op, None)
         if mat is not None:
             return two_qubit_decompositions.two_qubit_matrix_to_operations(
                 op.qubits[0],
                 op.qubits[1],
                 mat,
                 allow_partial_czs=self.allow_partial_czs)
     return NotImplemented
Пример #2
0
    def optimization_at(self,
                        circuit: circuits.Circuit,
                        index: int,
                        op: ops.Operation
    ) -> Optional[circuits.PointOptimizationSummary]:
        if len(op.qubits) != 2:
            return None

        old_operations, indices, matrix = (
            self._scan_two_qubit_ops_into_matrix(circuit, index, op.qubits))

        old_interaction_count = len([old_op for old_op in old_operations
                                     if len(old_op.qubits) == 2])

        switch_to_new = False
        switch_to_new |= any(len(old_op.qubits) == 2 and
                             not (isinstance(old_op, ops.GateOperation) and
                                  isinstance(old_op.gate, ops.CZPowGate))
                             for old_op in old_operations)
        if not self.allow_partial_czs:
            switch_to_new |= any(isinstance(old_op, ops.GateOperation) and
                                 isinstance(old_op.gate, ops.CZPowGate)
                                 and old_op.gate.exponent != 1
                                 for old_op in old_operations)

        # This point cannot be optimized using this method
        if not switch_to_new and old_interaction_count <= 1:
            return None

        # Find a max-3-cz construction.
        new_operations = (
            two_qubit_decompositions.two_qubit_matrix_to_operations(
                op.qubits[0],
                op.qubits[1],
                matrix,
                self.allow_partial_czs,
                self.tolerance,
                False))
        new_interaction_count = len([new_op for new_op in new_operations
                                     if len(new_op.qubits) == 2])

        switch_to_new |= new_interaction_count < old_interaction_count

        if not switch_to_new:
            return None

        return circuits.PointOptimizationSummary(
            clear_span=max(indices) + 1 - index,
            clear_qubits=op.qubits,
            new_operations=new_operations)
Пример #3
0
    def _two_qubit_matrix_to_operations(
        self,
        q0: 'cirq.Qid',
        q1: 'cirq.Qid',
        mat: np.ndarray,
    ) -> Sequence['cirq.Operation']:
        """Decomposes the merged two-qubit gate unitary into the minimum number
        of CZ gates.

        Args:
            q0: The first qubit being operated on.
            q1: The other qubit being operated on.
            mat: Defines the operation to apply to the pair of qubits.

        Returns:
            A list of operations implementing the matrix.
        """
        return two_qubit_decompositions.two_qubit_matrix_to_operations(
            q0, q1, mat, self.allow_partial_czs, self.tolerance, False)