def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Check if this is a CZ
        # Only keep partial CZ gates if allow_partial_czs
        if (isinstance(op, ops.GateOperation)
            and isinstance(op.gate, ops.Rot11Gate)
            and (self.allow_partial_czs or op.gate.half_turns == 1)):
            return op

        # Known matrix?
        mat = self.extensions.try_cast(ops.KnownMatrix, op)
        if mat is not None and len(op.qubits) == 1:
            return op
        if mat is not None and len(op.qubits) == 2:
            return decompositions.two_qubit_matrix_to_operations(
                op.qubits[0],
                op.qubits[1],
                mat.matrix(),
                allow_partial_czs=False)

        # Provides a decomposition?
        composite_op = self.extensions.try_cast(ops.CompositeOperation, op)
        if composite_op is not None:
            return composite_op.default_decompose()

        # Just let it be?
        if self.ignore_failures:
            return op

        raise TypeError("Don't know how to work with {!r}. "
                        "It isn't a 1-qubit KnownMatrix, "
                        "a 2-qubit KnownMatrix, "
                        "or a CompositeOperation.".format(op))
示例#2
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Check if this is a CZ
        # Only keep partial CZ gates if allow_partial_czs
        if (isinstance(op, ops.GateOperation)
                and isinstance(op.gate, ops.CZPowGate)
                and (self.allow_partial_czs or op.gate.exponent == 1)):
            return op

        # Measurement?
        if ops.MeasurementGate.is_measurement(op):
            return op

        # Known matrix?
        mat = protocols.unitary(op, None)
        if mat is not None and len(op.qubits) == 1:
            return op
        if mat is not None and len(op.qubits) == 2:
            return decompositions.two_qubit_matrix_to_operations(
                op.qubits[0], op.qubits[1], mat, allow_partial_czs=False)

        # Provides a decomposition?
        decomposed = protocols.decompose_once(op, None)
        if decomposed is not None:
            return decomposed

        # Just let it be?
        if self.ignore_failures:
            return op

        raise TypeError("Don't know how to work with {!r}. "
                        "It isn't composite or an operation with a "
                        "known unitary effect on 1 or 2 qubits.".format(op))
示例#3
0
 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 decompositions.two_qubit_matrix_to_operations(
                 op.qubits[0],
                 op.qubits[1],
                 mat,
                 allow_partial_czs=self.allow_partial_czs)
     return NotImplemented
示例#4
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Known matrix?
        mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None
        if mat is not None and len(op.qubits) == 1:
            gates = single_qubit_matrix_to_native_gates(mat)
            return [g.on(op.qubits[0]) for g in gates]
        if mat is not None and len(op.qubits) == 2:
            return two_qubit_matrix_to_operations(op.qubits[0],
                                                  op.qubits[1],
                                                  mat,
                                                  allow_partial_czs=True)

        return NotImplemented
示例#5
0
    def optimization_at(self,
                        circuit: Circuit,
                        index: int,
                        op: ops.Operation
    ) -> Optional[optimization_pass.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 = decompositions.two_qubit_matrix_to_operations(
            op.qubits[0],
            op.qubits[1],
            matrix,
            self.allow_partial_czs,
            self.tolerance)
        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 optimization_pass.PointOptimizationSummary(
            clear_span=max(indices) + 1 - index,
            clear_qubits=op.qubits,
            new_operations=new_operations)
示例#6
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))

        # Find a max-3-cz construction.
        new_operations = decompositions.two_qubit_matrix_to_operations(
            op.qubits[0],
            op.qubits[1],
            matrix,
            self.allow_partial_czs,
            self.tolerance)

        old_interaction_count = len([old_op for old_op in old_operations
                                     if len(old_op.qubits) == 2])
        new_interaction_count = len([new_op for new_op in new_operations
                                     if len(new_op.qubits) == 2])
        switch_to_new = False
        switch_to_new |= new_interaction_count < old_interaction_count
        switch_to_new |= any(not xmon_gates.XmonGate.is_xmon_op(old_op)
                             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, xmon_gates.Exp11Gate)
                                 and old_op.gate.half_turns != 1
                                 for old_op in old_operations)
        if not switch_to_new:
            return None

        converter = convert_to_xmon_gates.ConvertToXmonGates()
        new_xmon_operations = [converter.convert(new_op)
                               for new_op in new_operations]

        return circuits.PointOptimizationSummary(
            clear_span=max(indices) + 1 - index,
            clear_qubits=op.qubits,
            new_operations=new_xmon_operations)
示例#7
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Maybe we know how to wrap it?
        if isinstance(op, ops.GateOperation):
            xmon = xmon_gate_ext.try_cast(XmonGate, op.gate)  # type: ignore
            if xmon is not None:
                return xmon.on(*op.qubits)

        # Known matrix?
        mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None
        if mat is not None and len(op.qubits) == 1:
            gates = single_qubit_matrix_to_native_gates(mat)
            return [g.on(op.qubits[0]) for g in gates]
        if mat is not None and len(op.qubits) == 2:
            return two_qubit_matrix_to_operations(op.qubits[0],
                                                  op.qubits[1],
                                                  mat,
                                                  allow_partial_czs=True)

        return NotImplemented
示例#8
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))

        # Find a max-3-cz construction.
        new_operations = decompositions.two_qubit_matrix_to_operations(
            op.qubits[0], op.qubits[1], matrix, self.allow_partial_czs,
            self.tolerance)

        old_interaction_count = len(
            [old_op for old_op in old_operations if len(old_op.qubits) == 2])
        new_interaction_count = len(
            [new_op for new_op in new_operations if len(new_op.qubits) == 2])
        switch_to_new = False
        switch_to_new |= new_interaction_count < old_interaction_count
        switch_to_new |= any(not xmon_gates.XmonGate.is_xmon_op(old_op)
                             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, xmon_gates.Exp11Gate)
                and old_op.gate.half_turns != 1 for old_op in old_operations)
        if not switch_to_new:
            return None

        converter = convert_to_xmon_gates.ConvertToXmonGates()
        new_xmon_operations = [
            converter.convert(new_op) for new_op in new_operations
        ]

        return circuits.PointOptimizationSummary(
            clear_span=max(indices) + 1 - index,
            clear_qubits=op.qubits,
            new_operations=new_xmon_operations)
示例#9
0
    def intercept_decompose_func(self,
                                 op: Union[ops.Operation, circuits.Circuit]
                                 ) -> ops.OP_TREE:
        if not isinstance(op, ops.Operation):
            return NotImplemented

        # Drop measurements.
        if ops.MeasurementGate.is_measurement(op):
            return []

        # Immediately completely decompose two qubit unitary operations.
        if len(op.qubits) == 2:
            m = protocols.unitary(op, None)
            if m is not None:
                return decompositions.two_qubit_matrix_to_operations(
                    op.qubits[0],
                    op.qubits[1],
                    mat=m,
                    allow_partial_czs=False
                )

        # Fallback to default.
        return NotImplemented
示例#10
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Already supported?
        if isinstance(op, ops.GateOperation) and isinstance(op.gate, XmonGate):
            return op

        # Maybe we know how to wrap it?
        if isinstance(op, ops.GateOperation):
            xmon = self.extensions.try_cast(XmonGate, op.gate)
            if xmon is not None:
                return xmon.on(*op.qubits)

        # Known matrix?
        mat = self.extensions.try_cast(ops.KnownMatrix, op)
        if mat is not None and len(op.qubits) == 1:
            gates = single_qubit_matrix_to_native_gates(mat.matrix())
            return [g.on(op.qubits[0]) for g in gates]
        if mat is not None and len(op.qubits) == 2:
            return two_qubit_matrix_to_operations(
                op.qubits[0],
                op.qubits[1],
                mat.matrix(),
                allow_partial_czs=True)

        # Provides a decomposition?
        composite_op = self.extensions.try_cast(ops.CompositeOperation, op)
        if composite_op is not None:
            return composite_op.default_decompose()

        # Just let it be?
        if self.ignore_failures:
            return op

        raise TypeError("Don't know how to work with {!r}. "
                        "It isn't a GateOperation with an XmonGate, "
                        "a 1-qubit KnownMatrix, "
                        "a 2-qubit KnownMatrix, "
                        "or a CompositeOperation.".format(op))
示例#11
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Already supported?
        if isinstance(op, ops.GateOperation) and isinstance(op.gate, XmonGate):
            return op

        # Maybe we know how to wrap it?
        if isinstance(op, ops.GateOperation):
            xmon = self.extensions.try_cast(XmonGate, op.gate)
            if xmon is not None:
                return xmon.on(*op.qubits)

        # Known matrix?
        mat = self.extensions.try_cast(ops.KnownMatrix, op)
        if mat is not None and len(op.qubits) == 1:
            gates = single_qubit_matrix_to_native_gates(mat.matrix())
            return [g.on(op.qubits[0]) for g in gates]
        if mat is not None and len(op.qubits) == 2:
            return two_qubit_matrix_to_operations(op.qubits[0],
                                                  op.qubits[1],
                                                  mat.matrix(),
                                                  allow_partial_czs=True)

        # Provides a decomposition?
        composite_op = self.extensions.try_cast(ops.CompositeOperation, op)
        if composite_op is not None:
            return composite_op.default_decompose()

        # Just let it be?
        if self.ignore_failures:
            return op

        raise TypeError("Don't know how to work with {!r}. "
                        "It isn't a GateOperation with an XmonGate, "
                        "a 1-qubit KnownMatrix, "
                        "a 2-qubit KnownMatrix, "
                        "or a CompositeOperation.".format(op))
示例#12
0
    def _convert_one(self, op: ops.Operation) -> ops.OP_TREE:
        # Already supported?
        if XmonGate.is_supported_op(op):
            return op

        # Maybe we know how to wrap it?
        if isinstance(op, ops.GateOperation):
            xmon = xmon_gate_ext.try_cast(XmonGate, op.gate)  # type: ignore
            if xmon is not None:
                return xmon.on(*op.qubits)

        # Known matrix?
        mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None
        if mat is not None and len(op.qubits) == 1:
            gates = single_qubit_matrix_to_native_gates(mat)
            return [g.on(op.qubits[0]) for g in gates]
        if mat is not None and len(op.qubits) == 2:
            return two_qubit_matrix_to_operations(op.qubits[0],
                                                  op.qubits[1],
                                                  mat,
                                                  allow_partial_czs=True)

        # Provides a decomposition?
        composite_op = xmon_gate_ext.try_cast(  # type: ignore
            ops.CompositeOperation, op)
        if composite_op is not None:
            return composite_op.default_decompose()

        # Just let it be?
        if self.ignore_failures:
            return op

        raise TypeError("Don't know how to work with {!r}. "
                        "It isn't a GateOperation with an XmonGate, "
                        "a 1 or 2 qubit gate with a known unitary, "
                        "or a CompositeOperation.".format(op))