Exemple #1
0
def quantum_solve(dim: int,
                  h: float,
                  j: float = 1,
                  epochs: int = 350,
                  lr=1e-2) -> float:
    """Variational Quantum Eigensolver.

    Args:
        dim (int): dimension of problem.
        h (float): TFI parameter.
        j (float, optional): TFI parameter. Defaults to 1.
        epochs (int, optional): number of epochs. Defaults to 350.
        lr ([type], optional): learning rate. Defaults to 1e-2.

    Returns:
        float: estimation of minimal eigenvalue
    """
    qubits = cirq.GridQubit.rect(dim, 1)
    params_x = sympy.symbols(f"x0:{dim}")
    params_y = sympy.symbols(f"y0:{dim}")
    params_z = sympy.symbols(f"z0:{dim}")
    cirquit = cirq.Circuit()

    for i in range(dim):
        cirquit.append(cirq.rx(params_x[i])(qubits[i]))
        cirquit.append(cirq.ry(params_y[i])(qubits[i]))
        cirquit.append(cirq.rz(params_z[i])(qubits[i]))

    with open("circuit.svg", "w") as file:
        svg_str = tdd_to_svg(
            cirquit.to_text_diagram_drawer(transpose=False),
            ref_boxheight=40,
            ref_boxwidth=120,
        )
        file.write(svg_str)

    op = get_ising_operator(qubits, j, h)
    model = tfq.layers.SampledExpectation()

    thetas = tf.Variable(np.random.random((1, 3 * dim)), dtype=tf.float32)

    exact_sol = linalg.eigs(sparse.csc_matrix(op.matrix()),
                            k=1,
                            which="SR",
                            return_eigenvectors=False)[0]
    print(f"Exact solution: {np.real(exact_sol):.4f}")

    start_val = model(
        cirquit,
        symbol_names=params_x + params_y + params_z,
        symbol_values=thetas,
        operators=op,
        repetitions=5000,
    )

    print(f"Initialized energy: {start_val.numpy()[0][0]:.4f}")

    log_writer = tf.summary.create_file_writer("train")

    for epoch in tqdm(range(epochs)):
        with tf.GradientTape() as gt:
            out = model(
                cirquit,
                symbol_names=params_x + params_y + params_z,
                symbol_values=thetas,
                operators=op,
                repetitions=5000,
            )

        grad = gt.gradient(out, thetas)
        thetas.assign_sub(lr * grad)

        with log_writer.as_default():
            tf.summary.scalar("Eigen Val", out[0, 0], step=epoch)
            tf.summary.histogram("Gradients", grad, step=epoch)

    solution = model(
        cirquit,
        symbol_names=params_x + params_y + params_z,
        symbol_values=thetas,
        operators=op,
        repetitions=10000,
    )

    print(f"VQE solution: {solution.numpy()[0][0]:.4f}")

    return solution.numpy()[0][0]
Exemple #2
0
def test_axis_angle():
    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.ry(1e-10))),
        cirq.AxisAngleDecomposition(angle=0, axis=(1, 0, 0), global_phase=1),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.rx(np.pi))),
        cirq.AxisAngleDecomposition(angle=np.pi,
                                    axis=(1, 0, 0),
                                    global_phase=1),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.X)),
        cirq.AxisAngleDecomposition(angle=np.pi,
                                    axis=(1, 0, 0),
                                    global_phase=1j),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.X**0.5)),
        cirq.AxisAngleDecomposition(angle=np.pi / 2,
                                    axis=(1, 0, 0),
                                    global_phase=np.exp(1j * np.pi / 4)),
        atol=1e-8,
    )
    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.X**-0.5)),
        cirq.AxisAngleDecomposition(angle=-np.pi / 2,
                                    axis=(1, 0, 0),
                                    global_phase=np.exp(-1j * np.pi / 4)),
    )

    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.Y)),
        cirq.AxisAngleDecomposition(angle=np.pi,
                                    axis=(0, 1, 0),
                                    global_phase=1j),
        atol=1e-8,
    )

    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.Z)),
        cirq.AxisAngleDecomposition(angle=np.pi,
                                    axis=(0, 0, 1),
                                    global_phase=1j),
        atol=1e-8,
    )

    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.H)),
        cirq.AxisAngleDecomposition(angle=np.pi,
                                    axis=(np.sqrt(0.5), 0, np.sqrt(0.5)),
                                    global_phase=1j),
        atol=1e-8,
    )

    assert cirq.approx_eq(
        cirq.axis_angle(cirq.unitary(cirq.H**0.5)),
        cirq.AxisAngleDecomposition(
            angle=np.pi / 2,
            axis=(np.sqrt(0.5), 0, np.sqrt(0.5)),
            global_phase=np.exp(1j * np.pi / 4),
        ),
        atol=1e-8,
    )
Exemple #3
0
def _get_circuit_proto_pairs():
    q0 = cirq.GridQubit(0, 0)
    q1 = cirq.GridQubit(0, 1)

    pairs = [
        # HPOW and aliases.
        (cirq.Circuit(cirq.HPowGate(exponent=0.3)(q0)),
         _build_op_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.HPowGate(exponent=sympy.Symbol('alpha'))(q0)),
         _build_op_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.HPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)),
         _build_op_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.H(q0)),
         _build_op_proto("HP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0'])),

        # XPOW and aliases.
        (cirq.Circuit(cirq.XPowGate(exponent=0.3)(q0)),
         _build_op_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.XPowGate(exponent=sympy.Symbol('alpha'))(q0)),
         _build_op_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.XPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)),
         _build_op_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.X(q0)),
         _build_op_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0'])),

        # YPOW and aliases
        (cirq.Circuit(cirq.YPowGate(exponent=0.3)(q0)),
         _build_op_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.YPowGate(exponent=sympy.Symbol('alpha'))(q0)),
         _build_op_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.YPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)),
         _build_op_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.Y(q0)),
         _build_op_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0'])),

        # ZPOW and aliases.
        (cirq.Circuit(cirq.ZPowGate(exponent=0.3)(q0)),
         _build_op_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.ZPowGate(exponent=sympy.Symbol('alpha'))(q0)),
         _build_op_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.ZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0)),
         _build_op_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0'])),
        (cirq.Circuit(cirq.Z(q0)),
         _build_op_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0'])),

        # XXPow and aliases
        (cirq.Circuit(cirq.XXPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.XXPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.XXPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.XX(q0, q1)),
         _build_op_proto("XXP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # YYPow and aliases
        (cirq.Circuit(cirq.YYPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.YYPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.YYPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.YY(q0, q1)),
         _build_op_proto("YYP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # ZZPow and aliases
        (cirq.Circuit(cirq.ZZPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.ZZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.ZZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.ZZ(q0, q1)),
         _build_op_proto("ZZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # CZPow and aliases
        (cirq.Circuit(cirq.CZPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.CZPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.CZPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.CZ(q0, q1)),
         _build_op_proto("CZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # CNOTPow and aliases
        (cirq.Circuit(cirq.CNotPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.CNotPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.CNotPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.CNOT(q0, q1)),
         _build_op_proto("CNP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # SWAPPow and aliases
        (cirq.Circuit(cirq.SwapPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.SwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.SwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.SWAP(q0, q1)),
         _build_op_proto("SP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # ISWAPPow and aliases
        (cirq.Circuit(cirq.ISwapPowGate(exponent=0.3)(q0, q1)),
         _build_op_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [0.3, 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.ISwapPowGate(exponent=sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 1.0, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.ISwapPowGate(exponent=3.1 * sympy.Symbol('alpha'))(q0, q1)),
         _build_op_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'],
                         ['alpha', 3.1, 0.0], ['0_0', '0_1'])),
        (cirq.Circuit(cirq.ISWAP(q0, q1)),
         _build_op_proto("ISP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, 0.0], ['0_0', '0_1'])),

        # PhasedXPow and aliases
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=0.9,
                                exponent=0.3,
                                global_shift=0.2)(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], [0.9, 1.0, 0.3, 1.0, 0.2], ['0_0'])),
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=sympy.Symbol('alpha'),
                                exponent=0.3)(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], ['alpha', 1.0, 0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'),
                                exponent=0.3)(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], ['alpha', 3.1, 0.3, 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=0.9,
                                exponent=sympy.Symbol('beta'))(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], [0.9, 1.0, 'beta', 1.0, 0.0], ['0_0'])),
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=0.9,
                                exponent=5.1 * sympy.Symbol('beta'))(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], [0.9, 1.0, 'beta', 5.1, 0.0], ['0_0'])),
        (cirq.Circuit(
            cirq.PhasedXPowGate(phase_exponent=3.1 * sympy.Symbol('alpha'),
                                exponent=5.1 * sympy.Symbol('beta'))(q0)),
         _build_op_proto("PXP", [
             'phase_exponent', 'phase_exponent_scalar', 'exponent',
             'exponent_scalar', 'global_shift'
         ], ['alpha', 3.1, 'beta', 5.1, 0.0], ['0_0'])),

        # RX, RY, RZ with symbolization is tested in special cases as the
        # string comparison of the float converted sympy.pi does not happen
        # smoothly. See: test_serialize_deserialize_special_case_one_qubit
        (cirq.Circuit(cirq.rx(np.pi)(q0)),
         _build_op_proto("XP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, -0.5], ['0_0'])),
        (cirq.Circuit(cirq.ry(np.pi)(q0)),
         _build_op_proto("YP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, -0.5], ['0_0'])),
        (cirq.Circuit(cirq.rz(np.pi)(q0)),
         _build_op_proto("ZP", ['exponent', 'exponent_scalar', 'global_shift'],
                         [1.0, 1.0, -0.5], ['0_0'])),

        # Identity
        (cirq.Circuit(cirq.I(q0)),
         _build_op_proto("I", ['unused'], [True], ['0_0'])),

        # FSimGate
        (cirq.Circuit(cirq.FSimGate(theta=0.1, phi=0.2)(q0, q1)),
         _build_op_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'],
                         [0.1, 1.0, 0.2, 1.0], ['0_0', '0_1'])),
        (cirq.Circuit(
            cirq.FSimGate(theta=2.1 * sympy.Symbol("alpha"),
                          phi=1.3 * sympy.Symbol("beta"))(q0, q1)),
         _build_op_proto("FSIM", ['theta', 'theta_scalar', 'phi', 'phi_scalar'],
                         ['alpha', 2.1, 'beta', 1.3], ['0_0', '0_1'])),
    ]

    return pairs
#%matplotlib inline
import matplotlib
matplotlib.use('TkAgg')

import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit

a, b = sympy.symbols('a b')

# Create two qubits
q0, q1 = cirq.GridQubit.rect(1, 2)

# Create a circuit on these qubits using the parameters you created above.
circuit = cirq.Circuit(
    cirq.rx(a).on(q0),
    cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))

SVGCircuit(circuit)

# Calculate a state vector with a=0.5 and b=-0.5.
resolver = cirq.ParamResolver({a: 0.5, b: -0.5})
output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state_vector
output_state_vector

z0 = cirq.Z(q0)

qubit_map={q0: 0, q1: 1}

z0.expectation_from_state_vector(output_state_vector, qubit_map).real

z0x1 = 0.5 * z0 + cirq.X(q1)
    op = cirq.YPowGate(exponent=0.5)(q)
    assert HALF_PI_GATE_SET.serialize_op(op) == proto
    cirq.testing.assert_allclose_up_to_global_phase(cirq.unitary(
        HALF_PI_GATE_SET.deserialize_op(proto)),
                                                    cirq.unitary(op),
                                                    atol=1e-6)


@pytest.mark.parametrize(('gate', 'axis_half_turns', 'half_turns'), [
    (cirq.X**0.25, 0.0, 0.25),
    (cirq.Y**0.25, 0.5, 0.25),
    (cirq.XPowGate(exponent=0.125), 0.0, 0.125),
    (cirq.YPowGate(exponent=0.125), 0.5, 0.125),
    (cirq.PhasedXPowGate(exponent=0.125, phase_exponent=0.25), 0.25, 0.125),
    (cirq.rx(0.125 * np.pi), 0.0, 0.125),
    (cirq.ry(0.25 * np.pi), 0.5, 0.25),
])
def test_serialize_deserialize_arbitrary_xy(gate, axis_half_turns, half_turns):
    op = gate.on(cirq.GridQubit(1, 2))
    expected = op_proto({
        'gate': {
            'id': 'xy'
        },
        'args': {
            'axis_half_turns': {
                'arg_value': {
                    'float_value': axis_half_turns
                }
            },
            'half_turns': {
                'arg_value': {
            (Note that the gate should already be targeting the qubit)
    """
    circuit = cirq.Circuit()
    circuit.append(initial_rotation)
    circuit.append(prep)
    circuit.append(evolve)
    circuit.append(cirq.inverse(prep))
    circuit.append(final_rotation)
    circuit.append(cirq.measure(*qubits, key='msmt'))
    return circuit


# Turning off yapf here as its formatting suggestion is bad.
# yapf: disable
standard_vpe_rotation_set = [
    [0.25, cirq.ry(numpy.pi / 2), cirq.ry(-numpy.pi / 2)],
    [-0.25, cirq.ry(numpy.pi / 2), cirq.ry(numpy.pi / 2)],
    [-0.25j, cirq.ry(numpy.pi / 2), cirq.rx(-numpy.pi / 2)],
    [0.25j, cirq.ry(numpy.pi / 2), cirq.rx(numpy.pi / 2)],
    [0.25, cirq.rx(numpy.pi / 2), cirq.rx(-numpy.pi / 2)],
    [-0.25, cirq.rx(numpy.pi / 2), cirq.rx(numpy.pi / 2)],
    [0.25j, cirq.rx(numpy.pi / 2), cirq.ry(-numpy.pi / 2)],
    [-0.25j, cirq.rx(numpy.pi / 2), cirq.ry(numpy.pi / 2)],
]
# yapf: enable


def vpe_circuits_single_timestep(qubits: Sequence[cirq.Qid],
                                 prep: cirq.Circuit,
                                 evolve: cirq.Circuit,
                                 target_qubit: cirq.Qid,
    })),
    (HasUnitary(np.eye(2)), cirq.LinearDict({'I': 1})),
    (HasUnitary(np.array([[1, -1j], [1j, -1]
                          ])), cirq.LinearDict({
                              'Y': 1,
                              'Z': 1
                          })),
    (HasUnitary(np.array([[0., 1.], [0., 0.]
                          ])), cirq.LinearDict({
                              'X': 0.5,
                              'Y': 0.5j
                          })),
    (HasUnitary(np.eye(16)), cirq.LinearDict({'IIII': 1.0})),
    (cirq.H, cirq.LinearDict({
        'X': np.sqrt(0.5),
        'Z': np.sqrt(0.5)
    })),
    (cirq.ry(np.pi / 2),
     cirq.LinearDict({
         'I': np.cos(np.pi / 4),
         'Y': -1j * np.sin(np.pi / 4)
     })),
))
def test_pauli_expansion(val, expected_expansion):
    actual_expansion = cirq.pauli_expansion(val)
    assert cirq.approx_eq(actual_expansion, expected_expansion, atol=1e-12)
    assert set(actual_expansion.keys()) == set(expected_expansion.keys())
    for name in actual_expansion.keys():
        assert np.abs(actual_expansion[name] -
                      expected_expansion[name]) < 1e-12
    def test_get_gradient_circuits(self):
        """Test that the correct objects are returned."""

        # Minimal linear combination.
        input_weights = [1.0, -0.5]
        input_perturbations = [1.0, -1.5]
        diff = linear_combination.LinearCombination(input_weights,
                                                    input_perturbations)

        # Circuits to differentiate.
        symbols = [sympy.Symbol("s0"), sympy.Symbol("s1")]
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(1, 2)
        input_programs = util.convert_to_tensor([
            cirq.Circuit(cirq.X(q0)**symbols[0],
                         cirq.ry(symbols[1])(q1)),
            cirq.Circuit(cirq.rx(symbols[0])(q0),
                         cirq.Y(q1)**symbols[1]),
        ])
        input_symbol_names = tf.constant([str(s) for s in symbols])
        input_symbol_values = tf.constant([[1.5, -2.7], [-0.3, 0.9]])

        # For each program in the input batch: LinearCombination creates a copy
        # of that program for each symbol in the batch; then for each symbol,
        # the program is copied for each non-zero perturbation; finally, a
        # single copy is added for the zero perturbation (no zero pert here).
        expected_batch_programs = tf.stack([[input_programs[0]] * 4,
                                            [input_programs[1]] * 4])
        expected_new_symbol_names = input_symbol_names

        # For each program in the input batch: first, the input symbol_values
        # for the program are tiled to the number of copies in the output.
        tiled_symbol_values = tf.stack([[input_symbol_values[0]] * 4,
                                        [input_symbol_values[1]] * 4])
        # Then we create the tensor of perturbations to apply to these symbol
        # values: for each symbol we tile out the non-zero perturbations at that
        # symbol's index, keeping all the other symbol perturbations at zero.
        # Perturbations are the same for each program.
        single_program_perturbations = tf.stack([[input_perturbations[0], 0.0],
                                                 [input_perturbations[1], 0.0],
                                                 [0.0, input_perturbations[0]],
                                                 [0.0,
                                                  input_perturbations[1]]])
        tiled_perturbations = tf.stack(
            [single_program_perturbations, single_program_perturbations])
        # Finally we add the perturbations to the original symbol values.
        expected_batch_symbol_values = tiled_symbol_values + tiled_perturbations

        # The map for LinearCombination is the same for every program.
        individual_batch_mapper = tf.stack(
            [[input_weights[0], input_weights[1], 0.0, 0.0],
             [0.0, 0.0, input_weights[0], input_weights[1]]])
        expected_batch_mapper = tf.stack(
            [individual_batch_mapper, individual_batch_mapper])

        (test_batch_programs, test_new_symbol_names, test_batch_symbol_values,
         test_batch_mapper) = diff.get_gradient_circuits(
             input_programs, input_symbol_names, input_symbol_values)
        self.assertAllEqual(expected_batch_programs, test_batch_programs)
        self.assertAllEqual(expected_new_symbol_names, test_new_symbol_names)
        self.assertAllClose(expected_batch_symbol_values,
                            test_batch_symbol_values,
                            atol=1e-6)
        self.assertAllClose(expected_batch_mapper,
                            test_batch_mapper,
                            atol=1e-6)
YY = AbstractGate("YY", [], arity=2, matrix_generator=gen_YY)
ZZ = AbstractGate("ZZ", [], arity=2, matrix_generator=gen_ZZ)

RXX = AbstractGate("RXX", [float], arity=2, matrix_generator=gen_RXX)
RYY = AbstractGate("RYY", [float], arity=2, matrix_generator=gen_RYY)
RZZ = AbstractGate("RZZ", [float], arity=2, matrix_generator=gen_RZZ)

gates_1qb = [
    cirq.X,
    cirq.Y,
    cirq.Z,
    cirq.S,
    cirq.T,
    cirq.H,
    cirq.rx(3.14),
    cirq.ry(3.14),
    cirq.rz(3.14),
]
gates_2qb = [
    ControlledGate(cirq.H),
    cirq.CNOT,
    ControlledGate(cirq.rz(3.14)),
    cirq.SWAP,
    cirq.ISWAP,
    cirq.XX,
    cirq.YY,
    cirq.ZZ,
    cirq.CZ,
]

pygates_1qb = [X, Y, Z, S, T, H, RX(3.14), RY(3.14), RZ(3.14)]
def anzatz(circuit, qubits, parameters):
    for i in range(len(qubits)):
        circuit.append([cirq.ry(parameters[0]).on(qubits[i])])
    return circuit
Exemple #11
0
    def test_get_gradient_circuits(self):
        """Test that the correct objects are returned."""

        diff = parameter_shift.ParameterShift()

        # Circuits to differentiate.
        symbols = [sympy.Symbol("s0"), sympy.Symbol("s1")]
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(1, 2)
        input_programs = util.convert_to_tensor([
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(cirq.Y(q1)**symbols[1]),
        ])
        input_symbol_names = tf.constant([str(s) for s in symbols])
        input_symbol_values = tf.constant([[1.5, -2.7], [-0.3, 0.9]])

        # First, for each symbol `s`, check how many times `s` appears in each
        # program `p`, `n_ps`. Let `n_param_gates` be the maximum of `n_ps` over
        # all symbols and programs. Then, the shape of `batch_programs` will be
        # [n_programs, n_symbols * n_param_gates * n_shifts], where `n_shifts`
        # is 2 because we decompose into gates with 2 eigenvalues. For row index
        # `p` we have for column indices between `i * n_param_gates * n_shifts`
        # and `(i + 1) * n_param_gates * n_shifts`, the first `n_pi * 2`
        # programs are parameter shifted versions of `input_programs[p]` and the
        # remaining programs are empty.
        # Here, `n_param_gates` is 2.
        impurity_symbol_name = "_impurity_for_param_shift"
        impurity_symbol = sympy.Symbol(impurity_symbol_name)
        expected_batch_programs_0 = util.convert_to_tensor([
            cirq.Circuit(
                cirq.X(q0)**impurity_symbol,
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**impurity_symbol,
                cirq.Y(q0)**symbols[0],
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**impurity_symbol,
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**impurity_symbol,
                cirq.ry(symbols[1])(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(impurity_symbol)(q1)),
            cirq.Circuit(
                cirq.X(q0)**symbols[0],
                cirq.Y(q0)**symbols[0],
                cirq.ry(impurity_symbol)(q1)),
            cirq.Circuit(),
            cirq.Circuit()
        ])
        expected_batch_programs_1 = util.convert_to_tensor([
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(),
            cirq.Circuit(cirq.Y(q1)**impurity_symbol),
            cirq.Circuit(cirq.Y(q1)**impurity_symbol),
            cirq.Circuit(),
            cirq.Circuit()
        ])
        expected_batch_programs = tf.stack(
            [expected_batch_programs_0, expected_batch_programs_1])

        # The new symbols are the old ones, with an extra used for shifting.
        expected_new_symbol_names = tf.concat(
            [input_symbol_names,
             tf.constant([impurity_symbol_name])], 0)

        # The batch symbol values are the input symbol values, tiled and with
        # shifted values appended. Locations that have empty programs should
        # also have zero for the shift.
        # The shifted values are the original value plus 1/2 divided by the
        # `exponent_scalar` of the gate.
        expected_batch_symbol_values = tf.constant(
            [[[1.5, -2.7, 1.5 + 0.5], [1.5, -2.7, 1.5 - 0.5],
              [1.5, -2.7, 1.5 + 0.5], [1.5, -2.7, 1.5 - 0.5],
              [1.5, -2.7, -2.7 + np.pi / 2], [1.5, -2.7, -2.7 - np.pi / 2],
              [1.5, -2.7, -2.7], [1.5, -2.7, -2.7]],
             [[-0.3, 0.9, -0.3], [-0.3, 0.9, -0.3], [-0.3, 0.9, -0.3],
              [-0.3, 0.9, -0.3], [-0.3, 0.9, 0.9 + 0.5],
              [-0.3, 0.9, 0.9 - 0.5], [-0.3, 0.9, 0.9], [-0.3, 0.9, 0.9]]])

        # Empty program locations are given zero weight.
        expected_batch_weights = tf.constant(
            [[[np.pi / 2, -np.pi / 2, np.pi / 2, -np.pi / 2],
              [0.5, -0.5, 0.0, 0.0]],
             [[0.0, 0.0, 0.0, 0.0], [np.pi / 2, -np.pi / 2, 0.0, 0.0]]])

        expected_batch_mapper = tf.constant([[[0, 1, 2, 3], [4, 5, 6, 7]],
                                             [[0, 1, 2, 3], [4, 5, 6, 7]]])

        (test_batch_programs, test_new_symbol_names, test_batch_symbol_values,
         test_batch_weights, test_batch_mapper) = diff.get_gradient_circuits(
             input_programs, input_symbol_names, input_symbol_values)
        for i in range(tf.shape(input_programs)[0]):
            self.assertAllEqual(util.from_tensor(expected_batch_programs[i]),
                                util.from_tensor(test_batch_programs[i]))
        self.assertAllEqual(expected_new_symbol_names, test_new_symbol_names)
        self.assertAllClose(expected_batch_symbol_values,
                            test_batch_symbol_values,
                            atol=1e-5)
        self.assertAllClose(expected_batch_weights,
                            test_batch_weights,
                            atol=1e-5)
        self.assertAllEqual(expected_batch_mapper, test_batch_mapper)
Exemple #12
0
    def _decompose_(self, qubits):
        control, target = qubits

        if np.all(cirq.unitary(self.sub_gate) == cirq.unitary(cirq.X)):
            yield cirq.CNOT(control=control, target=target)
            return

        elif np.all(cirq.unitary(self.sub_gate) == cirq.unitary(cirq.I)):
            return

        _matrix = cirq.unitary(self.sub_gate)
        [a, b], [c, d] = _matrix

        alpha = beta = delta = gamma = 0.0

        if b == c == 0.0:
            gamma = delta = 0.0
            alpha = np.angle(a * d) / 2.0
            beta = np.angle(d / a)

        elif a == d == 0.0:
            gamma = np.pi
            delta = 0.0
            alpha = np.angle(-b * c) / 2.0
            beta = np.angle(-c / b)

        else:  # a * b * c * d != 0.0
            alpha = np.angle(-b * c) / 2.0
            beta = -np.angle(a / c)
            gamma = 2 * np.arccos(np.abs(a))
            delta = -np.angle(-a / b)

        if a != 0.0:
            a_evaluated = (np.exp(1.0j * (alpha - beta / 2.0 - delta / 2.0)) *
                           np.cos(gamma / 2.0))
            # if there is a difference in the complex angle
            if is_complex_close(
                    a, -a_evaluated,
                    atol=1e-10):  # atol is required for near zero values
                alpha = alpha + np.pi if alpha < 0 else alpha - np.pi
            # else:
            #     assert is_complex_close(a, a_evaluated, atol=1e-9)

        else:
            b_evaluated = (-np.exp(1.0j * (alpha - beta / 2.0 + delta / 2.0)) *
                           np.sin(gamma / 2.0))
            # if there is a difference in the complex angle
            if is_complex_close(b, -b_evaluated, atol=1e-10):
                alpha = alpha + np.pi if alpha < 0 else alpha - np.pi
            # else:
            #     assert is_complex_close(b, b_evaluated, atol=1e-9)

        # Gate C
        yield cirq.rz((delta - beta) / 2.0).on(target)

        # Gate CNOT
        yield cirq.CNOT(control=control, target=target)

        # Gate B
        yield cirq.rz(-(delta + beta) / 2.0).on(target)
        yield cirq.ry(-gamma / 2.0).on(target)

        # Gate CNOT
        yield cirq.CNOT(control=control, target=target)

        # Gate A
        yield cirq.ry(gamma / 2.0).on(target)
        yield cirq.rz(beta).on(target)

        # Gate Phase
        yield cirq.rz(alpha).on(control)
        yield GlobalPhaseGate(alpha / (2.0 * np.pi)).on(control)
Exemple #13
0
 def __init__(self, rads):
     self.rads = rads
     super().__init__(sub_gate=cirq.ry(rads), num_controls=1)
import numpy as np

# visualization tools
%matplotlib inline
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit

a, b = sympy.symbols('a b')

# 2qubits circuit
q0, q1 = cirq.GridQubit.rect(1, 2)

# rx gate on q0 with parameter a, and ry gate on q1 with parameter b
circuit = cirq.Circuit(
    cirq.rx(a).on(q0),
    cirq.ry(b).on(q1), cirq.CNOT(control=q0, target=q1))

SVGCircuit(circuit)


# state vector at a=0.5, b=-0.5
resolver = cirq.ParamResolver({a: 0.5, b: -0.5})
output_state_vector = cirq.Simulator().simulate(circuit, resolver).final_state
output_state_vector


#gets an array([ 0.9387913 +0.j        , -0.23971277+0.j        , 0.        +0.06120872j,  0.        -0.23971277j], dtype=complex64)

z0 = cirq.Z(q0)

qubit_map={q0: 0, q1: 1}
Exemple #15
0
 def _ancilla_rotation(self, k):
     if k == 0:
         k = self.N
     theta = 2 * math.asin(self.C * self.N * self.t / (2 * math.pi * k))
     return cirq.ry(theta)
Exemple #16
0
def test_deprecated_rxyz_rotations(rads):
    assert np.all(cirq.unitary(cirq.Rx(rads)) == cirq.unitary(cirq.rx(rads)))
    assert np.all(cirq.unitary(cirq.Ry(rads)) == cirq.unitary(cirq.ry(rads)))
    assert np.all(cirq.unitary(cirq.Rz(rads)) == cirq.unitary(cirq.rz(rads)))
Exemple #17
0
    def to_cirq(self, input_cirq_qubits=None):
        """Convert to a cirq gate.

        Args:
            input_cirq_qubits: list[cirq.LineQubit]
                (optional) a list of cirq Qubits that the gate can act on. If not provided
                the function will generate new cirq.LineQubit objects.
        Returns:
        A cirq Circuit object that corresponds to the specification of the quantum gate.
            In the special case the gate itself was natively generated from cirq, the function
            will faithfully reproduce the original GateOperation object, taking into account
            whether the gate acts on GridQubit objects or LineQubit objects.
            In the other cases the resulting cirq gate simply assumes that the qubits are
            LineQubit objects.
        """

        if self.name not in ALL_GATES:
            sys.exit("Gate {} currently not supported.".format(self.name))

        q_inds = []
        q_inds.append(self.qubits[0].index)
        if len(self.qubits) >= 2:
            q_inds.append(self.qubits[1].index)
        if len(self.qubits) >= 3:
            q_inds.append(self.qubits[2].index)

        cirq_qubits = []
        if input_cirq_qubits == None:
            for q in self.qubits:
                if q.info["label"] == "cirq":
                    qkey = q.info["QubitKey"]
                    if q.info["QubitType"] == "GridQubit":
                        cirq_qubits.append(cirq.GridQubit(qkey[0], qkey[1]))
                    if q.info["QubitType"] == "LineQubit":
                        cirq_qubits.append(cirq.LineQubit(qkey))
                else:
                    cirq_qubits.append(cirq.LineQubit(q.index))
        else:
            cirq_qubits = [
                input_cirq_qubits[x] for x in [q.index for q in self.qubits]
            ]

        if len(self.params) > 0:
            params = self.params

        # single-qubit gates
        if self.name == "I":  # Identity
            return cirq.I(cirq_qubits[0])
        if self.name == "X":  # Pauli X
            return cirq.X(cirq_qubits[0])
        if self.name == "Y":  # Pauli Y
            return cirq.Y(cirq_qubits[0])
        if self.name == "Z":  # Pauli Z
            return cirq.Z(cirq_qubits[0])
        if self.name == "H":  # Hadamard
            return cirq.H(cirq_qubits[0])
        if self.name == "S":  # S gate
            return cirq.S(cirq_qubits[0])
        if self.name == "T":  # T gate
            return cirq.T(cirq_qubits[0])
        if self.name == "Rx":  # Single-qubit X rotation
            return cirq.rx(params[0])(cirq_qubits[0])
        if self.name == "Ry":  # Single-qubit Y rotation
            return cirq.ry(params[0])(cirq_qubits[0])
        if self.name == "Rz":  # Single-qubit Z rotation
            return cirq.rz(params[0])(cirq_qubits[0])
        if self.name == "PHASE":  # Phase gate
            return cirq.Z(cirq_qubits[0])**(params[0] / pi)
        if self.name == "ZXZ":  # PhasedXPowGate gate
            g = cirq.PhasedXPowGate(phase_exponent=params[0] / pi,
                                    exponent=params[1] / pi)
            return g(cirq_qubits[0])
        if self.name == "RH":  # HPowGate
            g = cirq.H**(params[0] / pi)
            return g(cirq_qubits[0])
        if self.name == "U3":  # HPowGate
            g = cirq.circuits.qasm_output.QasmUGate(params[0] / pi,
                                                    params[1] / pi,
                                                    params[2] / pi)
            return g(cirq_qubits[0])
        if self.name == "Da":  # Damping alpha gate
            g = DampingAlpha(params[0])
            return g(cirq_qubits[0])
        if self.name == "Db":  # Damping beta gate
            g = DampingBeta(params[0])
            return g(cirq_qubits[0])

        # two-qubit gates
        if self.name == "CNOT":
            return cirq.CNOT(cirq_qubits[0], cirq_qubits[1])
        if self.name == "CZ":
            return cirq.CZ(cirq_qubits[0], cirq_qubits[1])
        if self.name == "CPHASE":
            return cirq.CZPowGate(exponent=params[0] / pi)(cirq_qubits[0],
                                                           cirq_qubits[1])
        if self.name == "SWAP":
            return cirq.SWAP(cirq_qubits[0], cirq_qubits[1])
        if self.name == "ISWAP":
            return cirq.ISWAP(cirq_qubits[0], cirq_qubits[1])
        if self.name == "XX":
            return cirq.XXPowGate(exponent=(params[0] * 2 / pi),
                                  global_shift=-1 / 2)(cirq_qubits[0],
                                                       cirq_qubits[1])
        if self.name == "YY":
            return cirq.YYPowGate(exponent=(params[0] * 2 / pi),
                                  global_shift=-1 / 2)(cirq_qubits[0],
                                                       cirq_qubits[1])
        if self.name == "ZZ":
            return cirq.ZZPowGate(exponent=(params[0] * 2 / pi),
                                  global_shift=-1 / 2)(cirq_qubits[0],
                                                       cirq_qubits[1])
        if self.name == "XY":
            return cirq.ISwapPowGate(exponent=(-params[0] * 4 / pi))(
                cirq_qubits[0], cirq_qubits[1])
Exemple #18
0
def test_circuit_0():
    qusetta_circuit = [
        "H(0)", "H(1)", "CX(0, 1)", "CX(1, 0)", "CZ(2, 0)", "I(1)",
        "SWAP(0, 3)", "RY(PI)(1)", "X(2)", "S(0)", "Z(2)", "Y(3)",
        "RX(0.4*PI)(0)", "T(2)", "RZ(-0.3*PI)(2)", "CCX(0, 1, 2)"
    ]

    cirq_circuit = cirq.Circuit()
    q = [cirq.LineQubit(i) for i in range(4)]
    cirq_circuit.append(cirq.H(q[0]))
    cirq_circuit.append(cirq.H(q[1]))
    cirq_circuit.append(cirq.CX(q[0], q[1]))
    cirq_circuit.append(cirq.CX(q[1], q[0]))
    cirq_circuit.append(cirq.CZ(q[2], q[0]))
    cirq_circuit.append(cirq.I(q[1]))
    cirq_circuit.append(cirq.SWAP(q[0], q[3]))
    cirq_circuit.append(cirq.ry(pi)(q[1]))
    cirq_circuit.append(cirq.X(q[2]))
    cirq_circuit.append(cirq.S(q[0]))
    cirq_circuit.append(cirq.Z(q[2]))
    cirq_circuit.append(cirq.Y(q[3]))
    cirq_circuit.append(cirq.rx(.4 * pi)(q[0]))
    cirq_circuit.append(cirq.T(q[2]))
    cirq_circuit.append(cirq.rz(-.3 * pi)(q[2]))
    cirq_circuit.append(cirq.CCX(q[0], q[1], q[2]))

    # ibm is weird so we flip all of the qubits here
    qiskit_circuit = qiskit.QuantumCircuit(4)
    qiskit_circuit.h(3 - 0)
    qiskit_circuit.h(3 - 1)
    qiskit_circuit.cx(3 - 0, 3 - 1)
    qiskit_circuit.cx(3 - 1, 3 - 0)
    qiskit_circuit.cz(3 - 2, 3 - 0)
    qiskit_circuit.i(3 - 1)
    qiskit_circuit.swap(3 - 0, 3 - 3)
    qiskit_circuit.ry(pi, 3 - 1)
    qiskit_circuit.x(3 - 2)
    qiskit_circuit.s(3 - 0)
    qiskit_circuit.z(3 - 2)
    qiskit_circuit.y(3 - 3)
    qiskit_circuit.rx(.4 * pi, 3 - 0)
    qiskit_circuit.t(3 - 2)
    qiskit_circuit.rz(-.3 * pi, 3 - 2)
    qiskit_circuit.ccx(3 - 0, 3 - 1, 3 - 2)

    quasar_circuit = quasar.Circuit()
    quasar_circuit.H(0)
    quasar_circuit.H(1)
    quasar_circuit.CX(0, 1)
    quasar_circuit.CX(1, 0)
    quasar_circuit.CZ(2, 0)
    quasar_circuit.I(1)
    quasar_circuit.SWAP(0, 3)
    quasar_circuit.Ry(1, pi)
    quasar_circuit.X(2)
    quasar_circuit.S(0)
    quasar_circuit.Z(2)
    quasar_circuit.Y(3)
    quasar_circuit.Rx(0, .2 * pi)
    quasar_circuit.T(2)
    quasar_circuit.Rz(2, -.15 * pi)
    quasar_circuit.CCX(0, 1, 2)

    # tests
    all_tests(qusetta_circuit, cirq_circuit, qiskit_circuit, quasar_circuit)
nl = 2
q = cirq.GridQubit.rect(1, nq)  # Define qubit grid. In this case

symb = sympy.symbols('theta0:' + str(4 + 3 * nq * nl))
W = np.array(symb[4:]).reshape(nl, nq, 3)
circuit = cirq.Circuit()
for i in range(4):
    circuit += cirq.rx(symb[i])(q[i])
    circuit += cirq.rz(symb[i])(q[i])
for l in range(nl):
    for i in range(3):
        circuit.append(cirq.CNOT(q[i], q[i + 1]))
    for i in range(4):
        print(W[l][i][0])
        circuit += cirq.rz(W[l][i][0])(q[i])
        circuit += cirq.ry(W[l][i][1])(q[i])
        circuit += cirq.rz(W[l][i][2])(q[i])

op = cirq.Z(q[0]), cirq.Z(q[1]), cirq.Z(q[2]), cirq.Z(q[3])

print(SVGCircuit(circuit))


class VQC(Model):
    def __init__(self):
        super(VQC, self).__init__()
        self.step = 0
        self.TARGET_UPDATE = 20
        self.optimizer = tf.keras.optimizers.SGD(lr=0.5)
        self.W = tf.Variable(np.random.rand(3 * nq * nl))
        self.bias = tf.Variable(np.zeros(4), dtype='float32')
Exemple #20
0
 def __call__(self, qubits, **kwargs):
     q0 = qubits[0]
     yield ry(c * rad).on(q0)
     yield IdentityGate(1).on(q1)
Exemple #21
0
# limitations under the License.

import pytest

import cirq
import cirq_ionq as ionq

VALID_GATES = (
    cirq.X,
    cirq.Y,
    cirq.Z,
    cirq.X**0.5,
    cirq.Y**0.5,
    cirq.Z**0.5,
    cirq.rx(0.1),
    cirq.ry(0.1),
    cirq.rz(0.1),
    cirq.H,
    cirq.T,
    cirq.S,
    cirq.CNOT,
    cirq.XX,
    cirq.YY,
    cirq.ZZ,
    cirq.XX**0.5,
    cirq.YY**0.5,
    cirq.ZZ**0.5,
    cirq.SWAP,
    cirq.MeasurementGate(num_qubits=1),
    cirq.MeasurementGate(num_qubits=2),
    cirq.MeasurementGate(num_qubits=10),
Exemple #22
0
    def test_cirq_qsim_all_supported_gates(self):
        q0 = cirq.GridQubit(1, 1)
        q1 = cirq.GridQubit(1, 0)
        q2 = cirq.GridQubit(0, 1)
        q3 = cirq.GridQubit(0, 0)

        circuit = cirq.Circuit(
            cirq.Moment([
                cirq.H(q0),
                cirq.H(q1),
                cirq.H(q2),
                cirq.H(q3),
            ]),
            cirq.Moment([
                cirq.T(q0),
                cirq.T(q1),
                cirq.T(q2),
                cirq.T(q3),
            ]),
            cirq.Moment([
                cirq.CZPowGate(exponent=0.7, global_shift=0.2)(q0, q1),
                cirq.CXPowGate(exponent=1.2, global_shift=0.4)(q2, q3),
            ]),
            cirq.Moment([
                cirq.XPowGate(exponent=0.3, global_shift=1.1)(q0),
                cirq.YPowGate(exponent=0.4, global_shift=1)(q1),
                cirq.ZPowGate(exponent=0.5, global_shift=0.9)(q2),
                cirq.HPowGate(exponent=0.6, global_shift=0.8)(q3),
            ]),
            cirq.Moment([
                cirq.CX(q0, q2),
                cirq.CZ(q1, q3),
            ]),
            cirq.Moment([
                cirq.X(q0),
                cirq.Y(q1),
                cirq.Z(q2),
                cirq.S(q3),
            ]),
            cirq.Moment([
                cirq.XXPowGate(exponent=0.4, global_shift=0.7)(q0, q1),
                cirq.YYPowGate(exponent=0.8, global_shift=0.5)(q2, q3),
            ]),
            cirq.Moment([cirq.I(q0),
                         cirq.I(q1),
                         cirq.IdentityGate(2)(q2, q3)]),
            cirq.Moment([
                cirq.rx(0.7)(q0),
                cirq.ry(0.2)(q1),
                cirq.rz(0.4)(q2),
                cirq.PhasedXPowGate(phase_exponent=0.8,
                                    exponent=0.6,
                                    global_shift=0.3)(q3),
            ]),
            cirq.Moment([
                cirq.ZZPowGate(exponent=0.3, global_shift=1.3)(q0, q2),
                cirq.ISwapPowGate(exponent=0.6, global_shift=1.2)(q1, q3),
            ]),
            cirq.Moment([
                cirq.XPowGate(exponent=0.1, global_shift=0.9)(q0),
                cirq.YPowGate(exponent=0.2, global_shift=1)(q1),
                cirq.ZPowGate(exponent=0.3, global_shift=1.1)(q2),
                cirq.HPowGate(exponent=0.4, global_shift=1.2)(q3),
            ]),
            cirq.Moment([
                cirq.SwapPowGate(exponent=0.2, global_shift=0.9)(q0, q1),
                cirq.PhasedISwapPowGate(phase_exponent=0.8, exponent=0.6)(q2,
                                                                          q3),
            ]),
            cirq.Moment([
                cirq.PhasedXZGate(x_exponent=0.2,
                                  z_exponent=0.3,
                                  axis_phase_exponent=1.4)(q0),
                cirq.T(q1),
                cirq.H(q2),
                cirq.S(q3),
            ]),
            cirq.Moment([
                cirq.SWAP(q0, q2),
                cirq.XX(q1, q3),
            ]),
            cirq.Moment([
                cirq.rx(0.8)(q0),
                cirq.ry(0.9)(q1),
                cirq.rz(1.2)(q2),
                cirq.T(q3),
            ]),
            cirq.Moment([
                cirq.YY(q0, q1),
                cirq.ISWAP(q2, q3),
            ]),
            cirq.Moment([
                cirq.T(q0),
                cirq.Z(q1),
                cirq.Y(q2),
                cirq.X(q3),
            ]),
            cirq.Moment([
                cirq.FSimGate(0.3, 1.7)(q0, q2),
                cirq.ZZ(q1, q3),
            ]),
            cirq.Moment([
                cirq.ry(1.3)(q0),
                cirq.rz(0.4)(q1),
                cirq.rx(0.7)(q2),
                cirq.S(q3),
            ]),
            cirq.Moment([
                cirq.IdentityGate(4).on(q0, q1, q2, q3),
            ]),
            cirq.Moment([
                cirq.CCZPowGate(exponent=0.7, global_shift=0.3)(q2, q0, q1),
            ]),
            cirq.Moment([
                cirq.CCXPowGate(exponent=0.4, global_shift=0.6)(
                    q3, q1, q0).controlled_by(q2, control_values=[0]),
            ]),
            cirq.Moment([
                cirq.rx(0.3)(q0),
                cirq.ry(0.5)(q1),
                cirq.rz(0.7)(q2),
                cirq.rx(0.9)(q3),
            ]),
            cirq.Moment([
                cirq.TwoQubitDiagonalGate([0.1, 0.2, 0.3, 0.4])(q0, q1),
            ]),
            cirq.Moment([
                cirq.ThreeQubitDiagonalGate(
                    [0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.3])(q1, q2, q3),
            ]),
            cirq.Moment([
                cirq.CSwapGate()(q0, q3, q1),
            ]),
            cirq.Moment([
                cirq.rz(0.6)(q0),
                cirq.rx(0.7)(q1),
                cirq.ry(0.8)(q2),
                cirq.rz(0.9)(q3),
            ]),
            cirq.Moment([
                cirq.TOFFOLI(q3, q2, q0),
            ]),
            cirq.Moment([
                cirq.FREDKIN(q1, q3, q2),
            ]),
            cirq.Moment([
                cirq.MatrixGate(
                    np.array([[0, -0.5 - 0.5j, -0.5 - 0.5j, 0],
                              [0.5 - 0.5j, 0, 0, -0.5 + 0.5j],
                              [0.5 - 0.5j, 0, 0, 0.5 - 0.5j],
                              [0, -0.5 - 0.5j, 0.5 + 0.5j, 0]]))(q0, q1),
                cirq.MatrixGate(
                    np.array([[0.5 - 0.5j, 0, 0, -0.5 + 0.5j],
                              [0, 0.5 - 0.5j, -0.5 + 0.5j, 0],
                              [0, -0.5 + 0.5j, -0.5 + 0.5j, 0],
                              [0.5 - 0.5j, 0, 0, 0.5 - 0.5j]]))(q2, q3),
            ]),
            cirq.Moment([
                cirq.MatrixGate(np.array([[1, 0], [0, 1j]]))(q0),
                cirq.MatrixGate(np.array([[0, -1j], [1j, 0]]))(q1),
                cirq.MatrixGate(np.array([[0, 1], [1, 0]]))(q2),
                cirq.MatrixGate(np.array([[1, 0], [0, -1]]))(q3),
            ]),
            cirq.Moment([
                cirq.riswap(0.7)(q0, q1),
                cirq.givens(1.2)(q2, q3),
            ]),
            cirq.Moment([
                cirq.H(q0),
                cirq.H(q1),
                cirq.H(q2),
                cirq.H(q3),
            ]),
        )

        simulator = cirq.Simulator()
        cirq_result = simulator.simulate(circuit)

        qsim_simulator = qsimcirq.QSimSimulator()
        qsim_result = qsim_simulator.simulate(circuit)

        assert cirq.linalg.allclose_up_to_global_phase(
            qsim_result.state_vector(), cirq_result.state_vector())
import matplotlib.pyplot as plt
from cirq.contrib.svg import SVGCircuit






# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')

# Create the parameterized circuit.
qubit = cirq.GridQubit(0, 0)
model_circuit = cirq.Circuit(
    cirq.rz(control_params[0])(qubit),
    cirq.ry(control_params[1])(qubit),
    cirq.rx(control_params[2])(qubit))

SVGCircuit(model_circuit)

# The classical neural network layers.
controller = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='elu'),
    tf.keras.layers.Dense(3)
])


# This input is the simulated miscalibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
                                # The circuit-tensor has dtype `tf.string` 
                                dtype=tf.string,
Exemple #24
0
class TestOperations:
    """Tests that the CirqDevice correctly handles the requested operations."""

    def test_reset_on_empty_circuit(self, cirq_device_1_wire):
        """Tests that reset resets the internal circuit when it is not initialized."""

        assert cirq_device_1_wire.circuit is None

        cirq_device_1_wire.reset()

        # Check if circuit is an empty cirq.Circuit
        assert cirq_device_1_wire.circuit == cirq.Circuit()

    def test_reset_on_full_circuit(self, cirq_device_1_wire):
        """Tests that reset resets the internal circuit when it is filled."""

        cirq_device_1_wire.reset()
        cirq_device_1_wire.apply([qml.PauliX(0)])

        # Assert that the queue is filled
        assert list(cirq_device_1_wire.circuit.all_operations())

        cirq_device_1_wire.reset()

        # Assert that the queue is empty
        assert not list(cirq_device_1_wire.circuit.all_operations())

    @pytest.mark.parametrize(
        "gate,expected_cirq_gates",
        [
            (qml.PauliX(wires=[0]), [cirq.X]),
            (qml.PauliY(wires=[0]), [cirq.Y]),
            (qml.PauliZ(wires=[0]), [cirq.Z]),
            (qml.PauliX(wires=[0]).inv(), [cirq.X ** -1]),
            (qml.PauliY(wires=[0]).inv(), [cirq.Y ** -1]),
            (qml.PauliZ(wires=[0]).inv(), [cirq.Z ** -1]),
            (qml.Hadamard(wires=[0]), [cirq.H]),
            (qml.Hadamard(wires=[0]).inv(), [cirq.H ** -1]),
            (qml.S(wires=[0]), [cirq.S]),
            (qml.S(wires=[0]).inv(), [cirq.S ** -1]),
            (qml.PhaseShift(1.4, wires=[0]), [cirq.ZPowGate(exponent=1.4 / np.pi)]),
            (qml.PhaseShift(-1.2, wires=[0]), [cirq.ZPowGate(exponent=-1.2 / np.pi)]),
            (qml.PhaseShift(2, wires=[0]), [cirq.ZPowGate(exponent=2 / np.pi)]),
            (
                qml.PhaseShift(1.4, wires=[0]).inv(),
                [cirq.ZPowGate(exponent=-1.4 / np.pi)],
            ),
            (
                qml.PhaseShift(-1.2, wires=[0]).inv(),
                [cirq.ZPowGate(exponent=1.2 / np.pi)],
            ),
            (qml.PhaseShift(2, wires=[0]).inv(), [cirq.ZPowGate(exponent=-2 / np.pi)]),
            (qml.RX(1.4, wires=[0]), [cirq.rx(1.4)]),
            (qml.RX(-1.2, wires=[0]), [cirq.rx(-1.2)]),
            (qml.RX(2, wires=[0]), [cirq.rx(2)]),
            (qml.RX(1.4, wires=[0]).inv(), [cirq.rx(-1.4)]),
            (qml.RX(-1.2, wires=[0]).inv(), [cirq.rx(1.2)]),
            (qml.RX(2, wires=[0]).inv(), [cirq.rx(-2)]),
            (qml.RY(1.4, wires=[0]), [cirq.ry(1.4)]),
            (qml.RY(0, wires=[0]), [cirq.ry(0)]),
            (qml.RY(-1.3, wires=[0]), [cirq.ry(-1.3)]),
            (qml.RY(1.4, wires=[0]).inv(), [cirq.ry(-1.4)]),
            (qml.RY(0, wires=[0]).inv(), [cirq.ry(0)]),
            (qml.RY(-1.3, wires=[0]).inv(), [cirq.ry(+1.3)]),
            (qml.RZ(1.4, wires=[0]), [cirq.rz(1.4)]),
            (qml.RZ(-1.1, wires=[0]), [cirq.rz(-1.1)]),
            (qml.RZ(1, wires=[0]), [cirq.rz(1)]),
            (qml.RZ(1.4, wires=[0]).inv(), [cirq.rz(-1.4)]),
            (qml.RZ(-1.1, wires=[0]).inv(), [cirq.rz(1.1)]),
            (qml.RZ(1, wires=[0]).inv(), [cirq.rz(-1)]),
            (
                qml.Rot(1.4, 2.3, -1.2, wires=[0]),
                [cirq.rz(1.4), cirq.ry(2.3), cirq.rz(-1.2)],
            ),
            (qml.Rot(1, 2, -1, wires=[0]), [cirq.rz(1), cirq.ry(2), cirq.rz(-1)]),
            (
                qml.Rot(-1.1, 0.2, -1, wires=[0]),
                [cirq.rz(-1.1), cirq.ry(0.2), cirq.rz(-1)],
            ),
            (
                qml.Rot(1.4, 2.3, -1.2, wires=[0]).inv(),
                [cirq.rz(1.2), cirq.ry(-2.3), cirq.rz(-1.4)],
            ),
            (
                qml.Rot(1, 2, -1, wires=[0]).inv(),
                [cirq.rz(1), cirq.ry(-2), cirq.rz(-1)],
            ),
            (
                qml.Rot(-1.1, 0.2, -1, wires=[0]).inv(),
                [cirq.rz(1), cirq.ry(-0.2), cirq.rz(1.1)],
            ),
            (
                qml.QubitUnitary(np.array([[1, 0], [0, 1]]), wires=[0]),
                [cirq.MatrixGate(np.array([[1, 0], [0, 1]]))],
            ),
            (
                qml.QubitUnitary(np.array([[1, 0], [0, -1]]), wires=[0]),
                [cirq.MatrixGate(np.array([[1, 0], [0, -1]]))],
            ),
            (
                qml.QubitUnitary(np.array([[-1, 1], [1, 1]]) / math.sqrt(2), wires=[0]),
                [cirq.MatrixGate(np.array([[-1, 1], [1, 1]]) / math.sqrt(2))],
            ),
            (
                qml.QubitUnitary(np.array([[1, 0], [0, 1]]), wires=[0]).inv(),
                [cirq.MatrixGate(np.array([[1, 0], [0, 1]])) ** -1],
            ),
            (
                qml.QubitUnitary(np.array([[1, 0], [0, -1]]), wires=[0]).inv(),
                [cirq.MatrixGate(np.array([[1, 0], [0, -1]])) ** -1],
            ),
            (
                qml.QubitUnitary(np.array([[-1, 1], [1, 1]]) / math.sqrt(2), wires=[0]).inv(),
                [cirq.MatrixGate(np.array([[-1, 1], [1, 1]]) / math.sqrt(2)) ** -1],
            ),
        ],
    )
    def test_apply_single_wire(self, cirq_device_1_wire, gate, expected_cirq_gates):
        """Tests that apply adds the correct gates to the circuit for single-qubit gates."""

        cirq_device_1_wire.reset()

        cirq_device_1_wire.apply([gate])

        ops = list(cirq_device_1_wire.circuit.all_operations())

        assert len(ops) == len(expected_cirq_gates)

        for i in range(len(ops)):
            assert ops[i]._gate == expected_cirq_gates[i]

    @pytest.mark.parametrize(
        "gate,expected_cirq_gates",
        [
            (qml.CNOT(wires=[0, 1]), [cirq.CNOT]),
            (qml.CNOT(wires=[0, 1]).inv(), [cirq.CNOT ** -1]),
            (qml.SWAP(wires=[0, 1]), [cirq.SWAP]),
            (qml.SWAP(wires=[0, 1]).inv(), [cirq.SWAP ** -1]),
            (qml.CZ(wires=[0, 1]), [cirq.CZ]),
            (qml.CZ(wires=[0, 1]).inv(), [cirq.CZ ** -1]),
            (qml.CRX(1.4, wires=[0, 1]), [cirq.ControlledGate(cirq.rx(1.4))]),
            (qml.CRX(-1.2, wires=[0, 1]), [cirq.ControlledGate(cirq.rx(-1.2))]),
            (qml.CRX(2, wires=[0, 1]), [cirq.ControlledGate(cirq.rx(2))]),
            (qml.CRX(1.4, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rx(-1.4))]),
            (qml.CRX(-1.2, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rx(1.2))]),
            (qml.CRX(2, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rx(-2))]),
            (qml.CRY(1.4, wires=[0, 1]), [cirq.ControlledGate(cirq.ry(1.4))]),
            (qml.CRY(0, wires=[0, 1]), [cirq.ControlledGate(cirq.ry(0))]),
            (qml.CRY(-1.3, wires=[0, 1]), [cirq.ControlledGate(cirq.ry(-1.3))]),
            (qml.CRY(1.4, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.ry(-1.4))]),
            (qml.CRY(0, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.ry(0))]),
            (qml.CRY(-1.3, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.ry(1.3))]),
            (qml.CRZ(1.4, wires=[0, 1]), [cirq.ControlledGate(cirq.rz(1.4))]),
            (qml.CRZ(-1.1, wires=[0, 1]), [cirq.ControlledGate(cirq.rz(-1.1))]),
            (qml.CRZ(1, wires=[0, 1]), [cirq.ControlledGate(cirq.rz(1))]),
            (qml.CRZ(1.4, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rz(-1.4))]),
            (qml.CRZ(-1.1, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rz(1.1))]),
            (qml.CRZ(1, wires=[0, 1]).inv(), [cirq.ControlledGate(cirq.rz(-1))]),
            (
                qml.CRot(1.4, 2.3, -1.2, wires=[0, 1]),
                [
                    cirq.ControlledGate(cirq.rz(1.4)),
                    cirq.ControlledGate(cirq.ry(2.3)),
                    cirq.ControlledGate(cirq.rz(-1.2)),
                ],
            ),
            (
                qml.CRot(1, 2, -1, wires=[0, 1]),
                [
                    cirq.ControlledGate(cirq.rz(1)),
                    cirq.ControlledGate(cirq.ry(2)),
                    cirq.ControlledGate(cirq.rz(-1)),
                ],
            ),
            (
                qml.CRot(-1.1, 0.2, -1, wires=[0, 1]),
                [
                    cirq.ControlledGate(cirq.rz(-1.1)),
                    cirq.ControlledGate(cirq.ry(0.2)),
                    cirq.ControlledGate(cirq.rz(-1)),
                ],
            ),
            (
                qml.CRot(1.4, 2.3, -1.2, wires=[0, 1]).inv(),
                [
                    cirq.ControlledGate(cirq.rz(1.2)),
                    cirq.ControlledGate(cirq.ry(-2.3)),
                    cirq.ControlledGate(cirq.rz(-1.4)),
                ],
            ),
            (
                qml.CRot(1, 2, -1, wires=[0, 1]).inv(),
                [
                    cirq.ControlledGate(cirq.rz(1)),
                    cirq.ControlledGate(cirq.ry(-2)),
                    cirq.ControlledGate(cirq.rz(-1)),
                ],
            ),
            (
                qml.CRot(-1.1, 0.2, -1, wires=[0, 1]).inv(),
                [
                    cirq.ControlledGate(cirq.rz(1)),
                    cirq.ControlledGate(cirq.ry(-0.2)),
                    cirq.ControlledGate(cirq.rz(1.1)),
                ],
            ),
            (qml.QubitUnitary(np.eye(4), wires=[0, 1]), [cirq.MatrixGate(np.eye(4))]),
            (
                qml.QubitUnitary(
                    np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]),
                    wires=[0, 1],
                ),
                [
                    cirq.MatrixGate(
                        np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
                    )
                ],
            ),
            (
                qml.QubitUnitary(
                    np.array([[1, -1, -1, 1], [-1, -1, 1, 1], [-1, 1, -1, 1], [1, 1, 1, 1]]) / 2,
                    wires=[0, 1],
                ),
                [
                    cirq.MatrixGate(
                        np.array(
                            [
                                [1, -1, -1, 1],
                                [-1, -1, 1, 1],
                                [-1, 1, -1, 1],
                                [1, 1, 1, 1],
                            ]
                        )
                        / 2
                    )
                ],
            ),
            (
                qml.QubitUnitary(np.eye(4), wires=[0, 1]).inv(),
                [cirq.MatrixGate(np.eye(4)) ** -1],
            ),
            (
                qml.QubitUnitary(
                    np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]),
                    wires=[0, 1],
                ).inv(),
                [
                    cirq.MatrixGate(
                        np.array([[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
                    )
                    ** -1
                ],
            ),
            (
                qml.QubitUnitary(
                    np.array([[1, -1, -1, 1], [-1, -1, 1, 1], [-1, 1, -1, 1], [1, 1, 1, 1]]) / 2,
                    wires=[0, 1],
                ).inv(),
                [
                    cirq.MatrixGate(
                        np.array(
                            [
                                [1, -1, -1, 1],
                                [-1, -1, 1, 1],
                                [-1, 1, -1, 1],
                                [1, 1, 1, 1],
                            ]
                        )
                        / 2
                    )
                    ** -1
                ],
            ),
        ],
    )
    def test_apply_two_wires(self, cirq_device_2_wires, gate, expected_cirq_gates):
        """Tests that apply adds the correct gates to the circuit for two-qubit gates."""

        cirq_device_2_wires.reset()

        cirq_device_2_wires.apply([gate])

        ops = list(cirq_device_2_wires.circuit.all_operations())
        assert len(ops) == len(expected_cirq_gates)

        for i in range(len(ops)):
            assert ops[i].gate == expected_cirq_gates[i]
class CirqDevice(QubitDevice, abc.ABC):
    """Abstract base device for PennyLane-Cirq.

    Args:
        wires (int or Iterable[Number, str]]): Number of subsystems represented by the device,
            or iterable that contains unique labels for the subsystems as numbers (i.e., ``[-1, 0, 2]``)
            or strings (``['ancilla', 'q1', 'q2']``).
        shots (int): Number of circuit evaluations/random samples used
            to estimate expectation values of observables. Shots need to be >= 1.
        qubits (List[cirq.Qubit]): A list of Cirq qubits that are used
            as wires. By default, an array of ``cirq.LineQubit`` instances is created.
            Wires are mapped to qubits using Cirq's internal mechanism for ordering
            qubits. For example, if ``wires=2`` and ``qubits=[q1, q2]``, with
            ``q1>q2``, then the wire indices 0 and 1 are mapped to q2 and q1, respectively.
            If the user provides their own wire labels, e.g., ``wires=["alice", "bob"]``, and the
            qubits are the same as the previous example, then "alice" would map to qubit q2
            and "bob" would map to qubit q1.
    """

    name = "Cirq Abstract PennyLane plugin base class"
    pennylane_requires = ">=0.17.0"
    version = __version__
    author = "Xanadu Inc"
    _capabilities = {
        "model": "qubit",
        "tensor_observables": True,
        "inverse_operations": True,
    }

    short_name = "cirq.base_device"

    def __init__(self, wires, shots, qubits=None):

        if not isinstance(wires, Iterable):
            # interpret wires as the number of consecutive wires
            wires = range(wires)
        num_wires = len(wires)

        if qubits:
            if num_wires != len(qubits):
                raise qml.DeviceError(
                    "The number of given qubits and the specified number of wires have to match. Got {} wires and {} qubits."
                    .format(wires, len(qubits)))
        else:
            qubits = [cirq.LineQubit(idx) for idx in range(num_wires)]

        # cirq orders the subsystems based on a total order defined on qubits.
        # For consistency, this plugin uses that same total order
        self._unsorted_qubits = qubits
        self.qubits = sorted(qubits)

        super().__init__(wires, shots)

        self.circuit = None
        self.pre_rotated_circuit = None
        self.cirq_device = None

        # Add inverse operations
        self._inverse_operation_map = {}
        for key, value in self._operation_map.items():
            if not value:
                continue

            # We have to use a new CirqOperation instance because .inv() acts in-place
            inverted_operation = CirqOperation(value.parametrization)
            inverted_operation.inv()

            self._inverse_operation_map[
                key + Operation.string_for_inverse] = inverted_operation

        self._complete_operation_map = {
            **self._operation_map,
            **self._inverse_operation_map,
        }

    _operation_map = {
        "BasisState":
        None,
        "QubitStateVector":
        None,
        "QubitUnitary":
        CirqOperation(cirq.MatrixGate),
        "PauliX":
        CirqOperation(lambda: cirq.X),
        "PauliY":
        CirqOperation(lambda: cirq.Y),
        "PauliZ":
        CirqOperation(lambda: cirq.Z),
        "Hadamard":
        CirqOperation(lambda: cirq.H),
        "S":
        CirqOperation(lambda: cirq.S),
        "T":
        CirqOperation(lambda: cirq.T),
        "CNOT":
        CirqOperation(lambda: cirq.CNOT),
        "SWAP":
        CirqOperation(lambda: cirq.SWAP),
        "ISWAP":
        CirqOperation(lambda: cirq.ISWAP),
        "CZ":
        CirqOperation(lambda: cirq.CZ),
        "PhaseShift":
        CirqOperation(lambda phi: cirq.ZPowGate(exponent=phi / np.pi)),
        "CPhase":
        CirqOperation(lambda phi: cirq.CZPowGate(exponent=phi / np.pi)),
        "RX":
        CirqOperation(cirq.rx),
        "RY":
        CirqOperation(cirq.ry),
        "RZ":
        CirqOperation(cirq.rz),
        "Rot":
        CirqOperation(lambda a, b, c: [cirq.rz(
            a), cirq.ry(b), cirq.rz(c)]),
        "CRX":
        CirqOperation(lambda phi: cirq.ControlledGate(cirq.rx(phi))),
        "CRY":
        CirqOperation(lambda phi: cirq.ControlledGate(cirq.ry(phi))),
        "CRZ":
        CirqOperation(lambda phi: cirq.ControlledGate(cirq.rz(phi))),
        "CRot":
        CirqOperation(lambda a, b, c: [
            cirq.ControlledGate(cirq.rz(a)),
            cirq.ControlledGate(cirq.ry(b)),
            cirq.ControlledGate(cirq.rz(c)),
        ]),
        "CSWAP":
        CirqOperation(lambda: cirq.CSWAP),
        "Toffoli":
        CirqOperation(lambda: cirq.TOFFOLI),
    }

    _observable_map = {
        "PauliX": CirqOperation(lambda: cirq.X),
        "PauliY": CirqOperation(lambda: cirq.Y),
        "PauliZ": CirqOperation(lambda: cirq.Z),
        "Hadamard": CirqOperation(lambda: cirq.H),
        "Hermitian": None,
        # TODO: Consider using qml.utils.decompose_hamiltonian() to support this observable.
        "Identity": CirqOperation(lambda: cirq.I),
        "Projector": CirqOperation(lambda: cirq.ProductState.projector),
    }

    def to_paulistring(self, observable):
        """Convert an observable to a cirq.PauliString"""
        if isinstance(observable, Tensor):
            obs = [self.to_paulistring(o) for o in observable.obs]
            return functools.reduce(operator.mul, obs)
        cirq_op = self._observable_map[observable.name]
        if cirq_op is None:
            raise NotImplementedError(
                f"{observable.name} is not currently supported.")
        cirq_op.parametrize(*observable.parameters)
        device_wires = self.map_wires(observable.wires)
        return functools.reduce(
            operator.mul,
            cirq_op.apply(*[self.qubits[w] for w in device_wires.labels]))

    def reset(self):
        # pylint: disable=missing-function-docstring
        super().reset()

        if self.cirq_device:
            self.circuit = cirq.Circuit(device=self.cirq_device)
        else:
            self.circuit = cirq.Circuit()

    @property
    def observables(self):
        # pylint: disable=missing-function-docstring
        return set(self._observable_map.keys())

    @property
    def operations(self):
        # pylint: disable=missing-function-docstring
        return set(self._operation_map.keys())

    @abc.abstractmethod
    def _apply_basis_state(self, basis_state_operation):
        """Apply a basis state preparation.

        Args:
            basis_state_operation (pennylane.BasisState): the BasisState operation instance that shall be applied

        Raises:
            NotImplementedError: when not implemented in the subclass
        """
        raise NotImplementedError

    @abc.abstractmethod
    def _apply_qubit_state_vector(self, qubit_state_vector_operation):
        """Apply a state vector preparation.

        Args:
            qubit_state_vector_operation (pennylane.QubitStateVector): the QubitStateVector operation instance that shall be applied

        Raises:
            NotImplementedError: when not implemented in the subclass
        """
        raise NotImplementedError

    def _apply_operation(self, operation):
        """Apply a single PennyLane Operation.

        Args:
            operation (pennylane.Operation): the operation that shall be applied
        """
        cirq_operation = self._complete_operation_map[operation.name]

        # If command is None do nothing
        if cirq_operation:
            cirq_operation.parametrize(*operation.parameters)

            device_wires = self.map_wires(operation.wires)
            self.circuit.append(
                cirq_operation.apply(
                    *[self.qubits[w] for w in device_wires.labels]))

    def apply(self, operations, **kwargs):
        # pylint: disable=missing-function-docstring
        rotations = kwargs.pop("rotations", [])

        for i, operation in enumerate(operations):
            if i > 0 and operation.name in {"BasisState", "QubitStateVector"}:
                raise qml.DeviceError(
                    "The operation {} is only supported at the beginning of a circuit."
                    .format(operation.name))

            if operation.name == "BasisState":
                self._apply_basis_state(operation)
            elif operation.name == "QubitStateVector":
                self._apply_qubit_state_vector(operation)
            else:
                self._apply_operation(operation)

        self.pre_rotated_circuit = self.circuit.copy()

        # Diagonalize the given observables
        for operation in rotations:
            self._apply_operation(operation)

    def define_wire_map(self, wires):  # pylint: disable=missing-function-docstring
        cirq_order = np.argsort(self._unsorted_qubits)
        consecutive_wires = Wires(cirq_order)

        wire_map = zip(wires, consecutive_wires)
        return OrderedDict(wire_map)
    actual_expansion = cirq.pauli_expansion(actual)
    expected_expansion = cirq.pauli_expansion(expected)
    assert set(actual_expansion.keys()) == set(expected_expansion.keys())
    for name in actual_expansion.keys():
        assert abs(actual_expansion[name] - expected_expansion[name]) < 1e-12


@pytest.mark.parametrize('expression, expected_result', (
    ((cirq.X + cirq.Z) / np.sqrt(2), cirq.H),
    (cirq.X - cirq.Y, -cirq.Y + cirq.X),
    (cirq.X + cirq.S - cirq.X, cirq.S),
    (cirq.Y - 2 * cirq.Y, -cirq.Y),
    (cirq.rx(0.2), np.cos(0.1) * cirq.I - 1j * np.sin(0.1) * cirq.X),
    (1j * cirq.H * 1j, -cirq.H),
    (-1j * cirq.Y, cirq.ry(np.pi)),
    (np.sqrt(-1j) * cirq.S, cirq.rz(np.pi / 2)),
    (0.5 * (cirq.IdentityGate(2) + cirq.XX + cirq.YY + cirq.ZZ), cirq.SWAP),
    ((cirq.IdentityGate(2) + 1j *
      (cirq.XX + cirq.YY) + cirq.ZZ) / 2, cirq.ISWAP),
    (cirq.CNOT + 0 * cirq.SWAP, cirq.CNOT),
    (0.5 * cirq.FREDKIN, cirq.FREDKIN / 2),
    (cirq.FREDKIN * 0.5, cirq.FREDKIN / 2),
    (((cirq.X + cirq.Y) / np.sqrt(2))**2, cirq.I),
    ((cirq.X + cirq.Z)**3, 2 * (cirq.X + cirq.Z)),
    ((cirq.X + 1j * cirq.Y)**2, cirq.LinearCombinationOfGates({})),
    ((cirq.X - 1j * cirq.Y)**2, cirq.LinearCombinationOfGates({})),
    (((3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13)**24, cirq.I),
    (((3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13)**25,
     (3 * cirq.X - 4 * cirq.Y + 12 * cirq.Z) / 13),
    ((cirq.X + cirq.Y + cirq.Z)**0, cirq.I),
def random_single_qubit_unitary():
    a, b, c = np.random.random(3) * 2 * np.pi
    circuit = cirq.unitary(cirq.rz(a)) @ cirq.unitary(cirq.ry(b)) @ cirq.unitary(cirq.rz(c))
    assert np.allclose(circuit.conj().T @ circuit, np.eye(2))
    return circuit
    def decompose(self, matrix, controls, target, free_qubits=[], power=1.0):
        """Implements action of multi-controlled unitary gate.

        Returns sequence of operations, which, when applied in sequence, gives
        result equivalent to applying single-qubit gate with matrix
        `matrix^power` on `target`, controlled by `controls`.

        Result is guaranteed to consist exclusively of 1-qubit, CNOT and CCNOT
        gates.

        If matrix is special unitary, result has length `O(len(controls))`.
        Otherwise result has length `O(len(controls)**2)`.

        Args:
            matrix - 2x2 numpy unitary matrix (of real or complex dtype).
            controls - control qubits.
            targets - target qubits.
            free_qubits - qubits which are neither controlled nor target. Can
                be modified by algorithm but will end up in inital state.
            power - power in which `unitary` should be raised. Deafults to 1.0.
        """
        assert cirq.is_unitary(matrix)
        assert matrix.shape == (2, 2)
        u = _unitary_power(matrix, power)

        # Matrix parameters, see definitions in [1], chapter 4.
        delta = np.angle(np.linalg.det(u)) * 0.5
        alpha = np.angle(u[0, 0]) + np.angle(u[0, 1]) - 2 * delta
        beta = np.angle(u[0, 0]) - np.angle(u[0, 1])
        theta = 2 * np.arccos(np.minimum(1.0, np.abs(u[0, 0])))

        # Decomposing matrix into three matrices - see [1], lemma 4.3.
        A = _Rz(alpha) @ _Ry(theta / 2)
        B = _Ry(-theta / 2) @ _Rz(-(alpha + beta) / 2)
        C = _Rz((beta - alpha) / 2)
        X = np.array([[0, 1], [1, 0]])
        if not np.allclose(A @ B @ C, np.eye(2), atol=1e-4):
            print('alpha', alpha)
            print('beta', beta)
            print('theta', theta)
            print('delta', delta)
            print('A', A)
            print('B', B)
            print('C', C)
            print(np.abs(A @ B @ C))
        assert np.allclose(A @ B @ C, np.eye(2), atol=1e-2)
        assert np.allclose(A @ X @ B @ X @ C,
                           u / np.exp(1j * delta),
                           atol=1e-2)

        m = len(controls)
        ctrl = controls
        assert m > 0, "No control qubits."

        if m == 1:
            # See [1], chapter 5.1.
            result = [
                cirq.ZPowGate(exponent=delta / np.pi).on(ctrl[0]),
                cirq.rz(-0.5 * (beta - alpha)).on(target),
                cirq.CNOT.on(ctrl[0], target),
                cirq.rz(0.5 * (beta + alpha)).on(target),
                cirq.ry(0.5 * theta).on(target),
                cirq.CNOT.on(ctrl[0], target),
                cirq.ry(-0.5 * theta).on(target),
                cirq.rz(-alpha).on(target),
            ]

            # Remove no-ops.
            result = [g for g in result if not _is_identity(g._unitary_())]

            return result
        else:
            gate_is_special_unitary = np.allclose(delta, 0)

            if gate_is_special_unitary:
                # O(n) decomposition of SU matrix - [1], lemma 7.9.
                cnot_seq = self.multi_ctrl_x(ctrl[:-1],
                                             target,
                                             free_qubits=[ctrl[-1]])
                result = []
                result += self.decompose(C, [ctrl[-1]], target)
                result += cnot_seq
                result += self.decompose(B, [ctrl[-1]], target)
                result += cnot_seq
                result += self.decompose(A, [ctrl[-1]], target)
                return result
            else:
                # O(n^2) decomposition - [1], lemma 7.5.
                cnot_seq = self.multi_ctrl_x(ctrl[:-1],
                                             ctrl[-1],
                                             free_qubits=free_qubits +
                                             [target])
                part1 = self.decompose(matrix, [ctrl[-1]],
                                       target,
                                       power=0.5 * power)
                part2 = self.decompose(matrix, [ctrl[-1]],
                                       target,
                                       power=-0.5 * power)
                part3 = self.decompose(matrix,
                                       ctrl[:-1],
                                       target,
                                       power=0.5 * power,
                                       free_qubits=free_qubits + [ctrl[-1]])
                return part1 + cnot_seq + part2 + cnot_seq + part3

        return circuit
Exemple #29
0
class SerializerTest(tf.test.TestCase, parameterized.TestCase):
    """Tests basic serializer functionality"""

    @parameterized.parameters(
        [{
            'circ_proto_pair': v
        } for v in _get_controlled_circuit_proto_pairs() +
         _get_circuit_proto_pairs() + _get_noise_proto_pairs()])
    def test_serialize_circuit_valid(self, circ_proto_pair):
        """Test conversion of cirq Circuits to tfq_gate_set proto."""
        self.assertProtoEquals(serializer.serialize_circuit(circ_proto_pair[0]),
                               circ_proto_pair[1])

    @parameterized.parameters(
        [{
            'circ_proto_pair': v
        } for v in _get_controlled_circuit_proto_pairs() +
         _get_circuit_proto_pairs() + _get_noise_proto_pairs()])
    def test_deserialize_circuit_valid(self, circ_proto_pair):
        """Test deserialization of protos in tfq_gate_set."""

        # String casting is done here to round floating point values.
        # cirq.testing.assert_same_circuits will call  break and think
        # cirq.Z^0.30000001 is different from cirq.Z^0.3
        self.assertEqual(circ_proto_pair[0],
                         serializer.deserialize_circuit(circ_proto_pair[1]))

    @parameterized.parameters(
        [{
            'circ_proto_pair': v
        } for v in _get_controlled_circuit_proto_pairs() +
         _get_circuit_proto_pairs() + _get_noise_proto_pairs()])
    def test_serialize_deserialize_circuit_consistency(self, circ_proto_pair):
        """Ensure that serializing followed by deserializing works."""

        # String casting is done here to round floating point values.
        # cirq.testing.assert_same_circuits will call  break and think
        # cirq.Z^0.30000001 is different from cirq.Z^0.3
        self.assertProtoEquals(
            serializer.serialize_circuit(
                serializer.deserialize_circuit(circ_proto_pair[1])),
            circ_proto_pair[1])
        self.assertEqual(
            serializer.deserialize_circuit(
                serializer.serialize_circuit(circ_proto_pair[0])),
            circ_proto_pair[0])

    def test_serialize_circuit_unsupported_gate(self):
        """Ensure we error on unsupported gates."""
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(0, 1)
        unsupported_circuit = cirq.Circuit(cirq.qft(q0, q1))

        with self.assertRaises(ValueError):
            serializer.serialize_circuit(unsupported_circuit)

    def test_serialize_circuit_with_large_identity(self):
        """Ensure that multi qubit identity errors correctly."""
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(0, 1)
        unsupported_circuit = cirq.Circuit(
            cirq.IdentityGate(num_qubits=2)(q0, q1))

        with self.assertRaisesRegex(ValueError, expected_regex="cirq.I"):
            serializer.serialize_circuit(unsupported_circuit)

    @parameterized.parameters([
        {
            "gate_with_param": g(p)
        }
        # Use a gate from each category of serializer
        for g in [
            # eigen
            lambda p: cirq.Circuit(
                cirq.HPowGate(exponent=p, global_shift=p)
                (cirq.GridQubit(0, 0))),
            # phased eigen
            lambda p: cirq.Circuit(
                cirq.PhasedXPowGate(
                    phase_exponent=p, exponent=p, global_shift=p)
                (cirq.GridQubit(0, 0))),
            # fsim
            lambda p: cirq.Circuit(
                cirq.FSimGate(theta=p, phi=p)
                (cirq.GridQubit(0, 0), cirq.GridQubit(0, 1))),
        ]
        # Attempt parameterization with a variety of numeric types
        for p in
        [0.35, float(0.35), 35e-2,
         np.float32(0.35),
         np.float64(0.35), 7]
    ])
    def test_serialize_circuit_valid_number_types(self, gate_with_param):
        """Tests number datatype support by our serializer."""
        self.assertAllClose(
            gate_with_param.unitary(),
            serializer.deserialize_circuit(
                serializer.serialize_circuit(gate_with_param)).unitary())

    def test_serialize_circuit_unsupported_value(self):
        """Ensure we error on unsupported arithmetic expressions and qubits."""
        q0 = cirq.GridQubit(0, 0)
        unsupported_circuit = cirq.Circuit(
            cirq.HPowGate()(q0)**(sympy.Symbol('alpha') + 1))

        q1 = cirq.NamedQubit('wont work')
        unsupported_circuit2 = cirq.Circuit(cirq.H(q1))

        with self.assertRaises(ValueError):
            serializer.serialize_circuit(unsupported_circuit)

        with self.assertRaises(ValueError):
            serializer.serialize_circuit(unsupported_circuit2)

    def test_serialize_controlled_circuit_unsupported_value(self):
        """Ensure serializing invalid controlled gates fails gracefully."""
        qubits = cirq.GridQubit.rect(1, 2)
        bad_qubit = cirq.LineQubit(5)
        invalid_control = cirq.Circuit(
            cirq.H(qubits[0]).controlled_by(qubits[1], bad_qubit))
        invalid_symbol = cirq.Circuit((cirq.HPowGate()(
            qubits[0])**(sympy.Symbol('alpha') + 1)).controlled_by(qubits[1]))
        with self.assertRaises(ValueError):
            serializer.serialize_circuit(invalid_control)
        with self.assertRaises(ValueError):
            serializer.serialize_circuit(invalid_symbol)

    def test_serialize_noise_channel_unsupported_value(self):
        """Ensure serializing invalid channels fails gracefully."""
        qubit = cirq.LineQubit(5)
        simple_circuit = cirq.Circuit(cirq.depolarize(0.3)(qubit))
        with self.assertRaises(ValueError):
            serializer.serialize_circuit(simple_circuit)

    @parameterized.parameters([{'inp': v} for v in ['wrong', 1.0, None, []]])
    def test_serialize_circuit_wrong_type(self, inp):
        """Attempt to serialize invalid objects types."""
        with self.assertRaises(TypeError):
            serializer.serialize_circuit(input)

    @parameterized.parameters([{'inp': v} for v in ['wrong', 1.0, None, []]])
    def test_deserialize_circuit_wrong_type(self, inp):
        """Attempt to deserialize invalid objects types."""
        with self.assertRaises(TypeError):
            serializer.deserialize_circuit(input)

    @parameterized.parameters([{'inp': v} for v in ['wrong', 1.0, None, []]])
    def test_serialize_paulisum_wrong_type(self, inp):
        """Attempt to serialize invalid object types."""
        with self.assertRaises(TypeError):
            serializer.serialize_paulisum(inp)

    @parameterized.parameters([{'inp': v} for v in ['wrong', 1.0, None, []]])
    def test_deserialize_paulisum_wrong_type(self, inp):
        """Attempt to deserialize invalid object types."""
        with self.assertRaises(TypeError):
            serializer.deserialize_paulisum(inp)

    def test_serialize_paulisum_invalid(self):
        """Ensure we don't support anything but GridQubits."""
        q0 = cirq.NamedQubit('wont work')
        a = 3.0 * cirq.Z(q0) - 2.0 * cirq.X(q0)
        with self.assertRaises(ValueError):
            serializer.serialize_paulisum(a)

    @parameterized.parameters([{
        'sum_proto_pair': v
    } for v in _get_valid_pauli_proto_pairs()])
    def test_serialize_paulisum_simple(self, sum_proto_pair):
        """Ensure serialization is correct."""
        self.assertProtoEquals(sum_proto_pair[1],
                               serializer.serialize_paulisum(sum_proto_pair[0]))

    @parameterized.parameters([{
        'sum_proto_pair': v
    } for v in _get_valid_pauli_proto_pairs()])
    def test_deserialize_paulisum_simple(self, sum_proto_pair):
        """Ensure deserialization is correct."""
        self.assertEqual(serializer.deserialize_paulisum(sum_proto_pair[1]),
                         sum_proto_pair[0])

    @parameterized.parameters([{
        'sum_proto_pair': v
    } for v in _get_valid_pauli_proto_pairs()])
    def test_serialize_deserialize_paulisum_consistency(self, sum_proto_pair):
        """Serialize and deserialize and ensure nothing changed."""
        self.assertEqual(
            serializer.serialize_paulisum(
                serializer.deserialize_paulisum(sum_proto_pair[1])),
            sum_proto_pair[1])

        self.assertEqual(
            serializer.deserialize_paulisum(
                serializer.serialize_paulisum(sum_proto_pair[0])),
            sum_proto_pair[0])

    @parameterized.parameters([
        {
            'gate': cirq.rx(3.0 * sympy.Symbol('alpha'))
        },
        {
            'gate': cirq.ry(-1.0 * sympy.Symbol('alpha'))
        },
        {
            'gate': cirq.rz(sympy.Symbol('alpha'))
        },
    ])
    def test_serialize_deserialize_special_case_one_qubit(self, gate):
        """Check output state equality."""
        q0 = cirq.GridQubit(0, 0)
        c = cirq.Circuit(gate(q0))

        c = cirq.resolve_parameters(c, cirq.ParamResolver({"alpha": 0.1234567}))
        before = c.unitary()
        c2 = serializer.deserialize_circuit(serializer.serialize_circuit(c))
        after = c2.unitary()
        self.assertAllClose(before, after)

    def test_terminal_measurement_support(self):
        """Test that non-terminal measurements error during serialization."""
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(0, 1)
        simple_circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0), cirq.H(q1),
                                      cirq.Z(q1), cirq.measure(q1))

        simple_circuit_before_call = copy.deepcopy(simple_circuit)

        expected_circuit = cirq.Circuit(cirq.Moment([cirq.H(q0),
                                                     cirq.H(q1)]),
                                        cirq.Moment([cirq.Z(q1)]),
                                        cirq.Moment([]))

        self.assertEqual(serializer.serialize_circuit(simple_circuit),
                         serializer.serialize_circuit(expected_circuit))

        # Check that serialization didn't modify existing circuit.
        self.assertEqual(simple_circuit, simple_circuit_before_call)

        invalid_circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0),
                                       cirq.measure(q0))

        with self.assertRaisesRegex(ValueError, expected_regex="non-terminal"):
            serializer.serialize_circuit(invalid_circuit)

    def test_serialize_deserialize_identity(self):
        """Confirm that identity gates can be serialized and deserialized."""
        q0 = cirq.GridQubit(0, 0)
        q1 = cirq.GridQubit(0, 1)
        paulisum_with_identity = cirq.PauliSum.from_pauli_strings([
            cirq.PauliString(cirq.I(q0)),
            cirq.PauliString(cirq.Z(q0), cirq.Z(q1)),
        ])
        self.assertEqual(
            paulisum_with_identity,
            serializer.deserialize_paulisum(
                serializer.serialize_paulisum(paulisum_with_identity)))
Exemple #30
0
def to_cirq(circuit: Circuit,
            qubits_map: dict[any, any] = None,
            verbose: bool = False) -> cirq.Circuit:
    """
    Convert `Circuit` to `cirq.Circuit`.

    Parameters
    ----------
    circuit: Circuit
        `Circuit` to convert to `cirq.Circuit`.
    qubits_map: dict[any, any], optional
        How to map qubits in `Circuit` to `cirq.Circuit`. if not provided,
        `cirq.LineQubit`s are used and automatically mapped to `Circuit`'s
        qubits.
    verbose: bool, optional
        Verbose output.

    Returns
    -------
    cirq.Circuit
        `cirq.Circuit` obtained from `Circuit`.

    Example
    -------
    >>> from hybridq.extras.cirq import to_cirq
    >>> c = Circuit(Gate('H', qubits=[q]) for q in range(3))
    >>> c.append(Gate('CX', qubits=[0, 1]))
    >>> c.append(Gate('CX', qubits=[2, 0]))
    >>> c.append(Gate('CX', qubits=[1, 2]))
    >>> to_cirq(c)
    0: ───H───@───X───────
              │   │
    1: ───H───X───┼───@───
                  │   │
    2: ───H───────@───X───
    """

    _to_cirq_naming = {
        'I': lambda params: cirq.I,
        'P': lambda params: cirq.S,
        'T': lambda params: cirq.T,
        'X': lambda params: cirq.X,
        'Y': lambda params: cirq.Y,
        'Z': lambda params: cirq.Z,
        'H': lambda params: cirq.H,
        'RX': lambda params: cirq.rx(*params),
        'RY': lambda params: cirq.ry(*params),
        'RZ': lambda params: cirq.rz(*params),
        'CZ': lambda params: cirq.CZ,
        'ZZ': lambda params: cirq.ZZ,
        'CX': lambda params: cirq.CNOT,
        'SWAP': lambda params: cirq.SWAP,
        'ISWAP': lambda params: cirq.ISWAP,
        'FSIM': lambda params: cirq.FSimGate(*params),
        'CPHASE': lambda params: cirq.CZ**(params[0] / np.pi)
    }

    # Get circuit
    circ = cirq.Circuit()

    # If not provided, create trivial map
    if not qubits_map:
        try:
            sorted(circuit.all_qubits())
            _standard_sortable = True
        except:
            _standard_sortable = False

        if _standard_sortable:
            qubits_map = {q: cirq.LineQubit(q) for q in circuit.all_qubits()}
        else:
            qubits_map = {
                q: cirq.LineQubit(x)
                for x, q in enumerate(circuit.all_qubits())
            }

    # Apply gates
    for gate in tqdm(circuit, disable=not verbose):

        # Check if qubits are missing
        if not gate.provides('qubits') or gate.qubits is None:
            raise ValueError(
                f"Gate(name='{gate.name}') requires {gate.n_qubits} qubits.")

        # Check if params are missing
        if gate.provides('params') and gate.params is None:
            raise ValueError(
                f"Gate(name='{gate.name}') requires {gate.n_params} parameters."
            )

        # Get mapped qubits
        qubits = [qubits_map[q] for q in gate.qubits]

        # Get params
        params = gate.params if gate.provides('params') else None

        if gate.name in {
                'MATRIX', 'U3', 'R_PI_2'
        } or (gate.provides('is_conjugated')
              and gate.is_conjugated()) or (gate.provides('is_transposed')
                                            and gate.is_transposed()):
            cirq_gate = cirq.MatrixGate(gate.matrix())
        elif gate.name[:5] == 'SQRT_':
            cirq_gate = _to_cirq_naming[gate.name[5:]](params)**(0.5 *
                                                                 gate.power)
        elif gate.name in _to_cirq_naming:
            cirq_gate = _to_cirq_naming[gate.name](params)**gate.power
        else:
            raise ValueError(f"{gate} not yet supported.")

        # Append
        circ.append(cirq_gate.on(*qubits))

    return circ