def swap_rzz(theta: float, q0: ops.Qid, q1: ops.Qid) -> ops.OP_TREE:
    """
    An implementation of SWAP * EXP(1j theta ZZ) using three sycamore gates.

    This builds off of the zztheta method.  A sycamore gate following the
    zz-gate is a SWAP EXP(1j (THETA - pi/24) ZZ).

    Args:
        theta: exp(1j * theta )
        q0: First qubit id to operate on
        q1: Second qubit id to operate on
    Returns:
        The circuit that implements ZZ followed by a swap
    """

    # Set interaction part.
    circuit = circuits.Circuit()
    angle_offset = np.pi / 24 - np.pi / 4
    circuit.append(google.SYC(q0, q1))
    circuit.append(rzz(theta - angle_offset, q0, q1))

    # Get the intended circuit.
    intended_circuit = circuits.Circuit(
        ops.SWAP(q0, q1),
        ops.ZZPowGate(exponent=2 * theta / np.pi,
                      global_shift=-0.5).on(q0, q1))

    yield create_corrected_circuit(intended_circuit, circuit, q0, q1)
Exemplo n.º 2
0
    def operation_decomposer(
            self, op: ops.Operation) -> Optional[list[ops.Operation]]:
        # Decomposes CNOT and the CZPowGate family to Valkmusa native gates.
        # All the decompositions below keep track of global phase (required for decomposing controlled gates).

        if isinstance(op.gate, ops.CXPowGate) and op.gate.exponent == 1.0:
            # CNOT is a special case, we decompose it using iSWAPs to be able to commute Z rotations through
            control_qubit = op.qubits[0]
            target_qubit = op.qubits[1]
            s = op.gate.global_shift
            iSWAP = ops.ISwapPowGate(exponent=1, global_shift=(s + 0.25) / 2)
            return [
                Lx.on(target_qubit),
                Lzi.on(control_qubit),
                Lz.on(target_qubit),
                iSWAP.on(*op.qubits),
                Lx.on(control_qubit),
                iSWAP.on(*op.qubits),
                Lz.on(target_qubit),
            ]
        if isinstance(op.gate, ops.CZPowGate):
            # decompose CZPowGate using ZZPowGate
            t = op.gate.exponent
            s = op.gate.global_shift
            L = ops.rz(t / 2 * PI)
            return [
                ops.ZZPowGate(exponent=-0.5 * t,
                              global_shift=-2 * s - 1).on(*op.qubits),
                L.on(op.qubits[0]),
                L.on(op.qubits[1]),
            ]
        if isinstance(op.gate, ops.ZZPowGate):
            # ZZPowGate is decomposed using two applications of the XY interaction
            t = op.gate.exponent
            s = op.gate.global_shift
            XY = ops.ISwapPowGate(exponent=-t, global_shift=-(s + 0.5) / 2)
            return [
                Lyi.on(op.qubits[0]),
                Lyi.on(op.qubits[1]),
                XY.on(*op.qubits),
                ops.XPowGate(exponent=-1, global_shift=-0.5).on(op.qubits[0]),
                XY.on(*op.qubits),
                ops.XPowGate(exponent=1, global_shift=-0.5).on(op.qubits[0]),
                Ly.on(op.qubits[0]),
                Ly.on(op.qubits[1]),
            ]
        if isinstance(op.gate, ops.ZPowGate):
            # Rz using Rx, Ry
            q = op.qubits[0]
            return [
                ops.XPowGate(exponent=-0.5).on(q),
                ops.YPowGate(exponent=op.gate.exponent).on(q),
                ops.XPowGate(exponent=0.5).on(q),
            ]
        return None
Exemplo n.º 3
0
def _translate_two_qubit_braket_instruction_to_cirq_operation(
    instr: Instruction, ) -> List["cirq.Operation"]:
    """Converts the two-qubit braket instruction to Cirq.

    Args:
        instr: Two-qubit Braket instruction to convert.

    Raises:
        ValueError: If the instruction cannot be converted to Cirq.
    """
    qubits = [LineQubit(int(qubit)) for qubit in instr.target]
    gate = instr.operator

    # Two-qubit non-parameterized gates.
    if isinstance(gate, braket_gates.CNot):
        return [cirq_ops.CNOT.on(*qubits)]

    elif isinstance(gate, braket_gates.Swap):
        return [cirq_ops.SWAP.on(*qubits)]
    elif isinstance(gate, braket_gates.ISwap):
        return [cirq_ops.ISWAP.on(*qubits)]
    elif isinstance(gate, braket_gates.CZ):
        return [cirq_ops.CZ.on(*qubits)]
    elif isinstance(gate, braket_gates.CY):
        return [
            cirq_ops.S.on(qubits[1])**-1,
            cirq_ops.CNOT.on(*qubits),
            cirq_ops.S.on(qubits[1]),
        ]

    # Two-qubit parameterized gates.
    elif isinstance(gate, braket_gates.PSwap):
        raise ValueError  # TODO.
    elif isinstance(gate, braket_gates.CPhaseShift):
        return [cirq_ops.CZ.on(*qubits)**(gate.angle / np.pi)]
    elif isinstance(gate, braket_gates.CPhaseShift00):
        raise ValueError  # TODO.
    elif isinstance(gate, braket_gates.CPhaseShift01):
        raise ValueError  # TODO.
    elif isinstance(gate, braket_gates.CPhaseShift10):
        raise ValueError  # TODO.
    elif isinstance(gate, braket_gates.XX):
        return [
            cirq_ops.XXPowGate(exponent=gate.angle / np.pi,
                               global_shift=-0.5).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.YY):
        return [
            cirq_ops.YYPowGate(exponent=gate.angle / np.pi,
                               global_shift=-0.5).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.ZZ):
        return [
            cirq_ops.ZZPowGate(exponent=gate.angle / np.pi,
                               global_shift=-0.5).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.XY):
        return [cirq_ops.ISwapPowGate(exponent=gate.angle / np.pi).on(*qubits)]

    else:
        raise ValueError(
            f"Unable to convert the instruction {instr} to Cirq. If you think "
            "this is a bug, you can open an issue on the Mitiq GitHub at "
            "https://github.com/unitaryfund/mitiq.")
Exemplo n.º 4
0
    testing.assert_allclose_up_to_global_phase(
        protocols.unitary(test_circuit),
        protocols.unitary(cirq_circuit),
        atol=1e-7,
    )


@pytest.mark.parametrize(
    "common_gate",
    [
        ops.CNOT,
        ops.CZ,
        ops.ISWAP,
        ops.XXPowGate(exponent=-0.2),
        ops.YYPowGate(exponent=0.3),
        ops.ZZPowGate(exponent=-0.1),
    ],
)
def test_to_from_braket_common_two_qubit_gates(common_gate):
    """These gates should stay the same (i.e., not get decomposed) when
    converting Cirq -> Braket -> Cirq.
    """
    cirq_circuit = Circuit(common_gate.on(*LineQubit.range(2)))
    test_circuit = from_braket(to_braket(cirq_circuit))
    testing.assert_allclose_up_to_global_phase(
        protocols.unitary(test_circuit),
        protocols.unitary(cirq_circuit),
        atol=1e-7,
    )

    # Cirq AAPowGate has a different global phase than braket AA which gets
Exemplo n.º 5
0
def _translate_two_qubit_braket_instruction_to_cirq_operation(
    instr: Instruction,
) -> List["cirq.Operation"]:
    """Converts the two-qubit braket instruction to Cirq.

    Args:
        instr: Two-qubit Braket instruction to convert.

    Raises:
        ValueError: If the instruction cannot be converted to Cirq.
    """
    qubits = [LineQubit(int(qubit)) for qubit in instr.target]
    gate = instr.operator

    # Two-qubit non-parameterized gates.
    if isinstance(gate, braket_gates.CNot):
        return [cirq_ops.CNOT.on(*qubits)]

    elif isinstance(gate, braket_gates.Swap):
        return [cirq_ops.SWAP.on(*qubits)]
    elif isinstance(gate, braket_gates.ISwap):
        return [cirq_ops.ISWAP.on(*qubits)]
    elif isinstance(gate, braket_gates.CZ):
        return [cirq_ops.CZ.on(*qubits)]
    elif isinstance(gate, braket_gates.CY):
        return [
            cirq_ops.S.on(qubits[1]) ** -1,
            cirq_ops.CNOT.on(*qubits),
            cirq_ops.S.on(qubits[1]),
        ]

    # Two-qubit parameterized gates.
    elif isinstance(gate, braket_gates.CPhaseShift):
        return [cirq_ops.CZ.on(*qubits) ** (gate.angle / np.pi)]
    elif isinstance(gate, braket_gates.CPhaseShift00):
        return [
            cirq_ops.XX(*qubits),
            cirq_ops.CZ.on(*qubits) ** (gate.angle / np.pi),
            cirq_ops.XX(*qubits),
        ]
    elif isinstance(gate, braket_gates.CPhaseShift01):
        return [
            cirq_ops.X(qubits[0]),
            cirq_ops.CZ.on(*qubits) ** (gate.angle / np.pi),
            cirq_ops.X(qubits[0]),
        ]
    elif isinstance(gate, braket_gates.CPhaseShift10):
        return [
            cirq_ops.X(qubits[1]),
            cirq_ops.CZ.on(*qubits) ** (gate.angle / np.pi),
            cirq_ops.X(qubits[1]),
        ]
    elif isinstance(gate, braket_gates.PSwap):
        return [
            cirq_ops.SWAP.on(*qubits),
            cirq_ops.CNOT.on(*qubits),
            cirq_ops.Z.on(qubits[1]) ** (gate.angle / np.pi),
            cirq_ops.CNOT.on(*qubits),
        ]
    elif isinstance(gate, braket_gates.XX):
        return [
            cirq_ops.XXPowGate(
                exponent=gate.angle / np.pi, global_shift=-0.5
            ).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.YY):
        return [
            cirq_ops.YYPowGate(
                exponent=gate.angle / np.pi, global_shift=-0.5
            ).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.ZZ):
        return [
            cirq_ops.ZZPowGate(
                exponent=gate.angle / np.pi, global_shift=-0.5
            ).on(*qubits)
        ]
    elif isinstance(gate, braket_gates.XY):
        return [cirq_ops.ISwapPowGate(exponent=gate.angle / np.pi).on(*qubits)]

    else:
        _raise_braket_to_cirq_error(instr)