Beispiel #1
0
def _gate_product_tabulation_cached(
    optimizer_type: str, tabulation_resolution: float
) -> cirq.TwoQubitGateTabulation:
    random_state = np.random.RandomState(51)
    if optimizer_type == 'sycamore':
        return cirq.two_qubit_gate_product_tabulation(
            cirq.unitary(cg_ops.SYC), tabulation_resolution, random_state=random_state
        )
    else:
        raise NotImplementedError(f"Two qubit gate tabulation not supported for {optimizer_type}")
Beispiel #2
0
def test_convert_to_sycamore_tabulation():
    # A tabulation for the sycamore gate with an infidelity of .1.
    sycamore_tabulation = cirq.two_qubit_gate_product_tabulation(
        cirq.unitary(cirq_google.SYC), 0.1, random_state=cirq.value.parse_random_state(11)
    )
    circuit = cirq.Circuit(cirq.MatrixGate(cirq.unitary(cirq.CX)).on(*cirq.LineQubit.range(2)))
    converted_circuit = cirq.optimize_for_target_gateset(
        circuit, gateset=cirq_google.SycamoreTargetGateset(tabulation=sycamore_tabulation)
    )
    u1 = cirq.unitary(circuit)
    u2 = cirq.unitary(converted_circuit)
    overlap = abs(np.trace(u1.conj().T @ u2))
    assert np.isclose(overlap, 4.0, 0.1)
def test_convert_to_sycamore_tabulation():
    # A tabulation for the sycamore gate with an infidelity of .1.
    sycamore_tabulation = cirq.two_qubit_gate_product_tabulation(
        cirq.unitary(cirq_google.SYC), 0.1, random_state=_rng
    )
    qubits = [cirq.NamedQubit('a'), cirq.NamedQubit('b')]
    operation = cirq.MatrixGate(cirq.unitary(cirq.CX), qid_shape=(2, 2)).on(qubits[0], qubits[1])
    with cirq.testing.assert_deprecated("Use cirq.optimize_for_target_gateset", deadline='v1.0'):
        converted = cgoc.ConvertToSycamoreGates(sycamore_tabulation).convert(operation)
    u1 = cirq.unitary(cirq.Circuit(converted))
    u2 = cirq.unitary(operation)
    overlap = abs(np.trace(u1.conj().T @ u2))
    assert np.isclose(overlap, 4.0, 0.1)
Beispiel #4
0
def gate_product_tabulation(
    base_gate: np.ndarray,
    max_infidelity: float,
    *,
    sample_scaling: int = 50,
    allow_missed_points: bool = True,
    random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
) -> GateTabulation:
    r"""Generate a GateTabulation for a base two qubit unitary.

    Args:
        base_gate: The base gate of the tabulation.
        max_infidelity: Sets the desired density of tabulated product unitaries.
            The typical nearest neighbor Euclidean spacing (of the KAK vectors)
            will be on the order of $\sqrt{max\_infidelity}$. Thus the number of
            tabulated points will scale as $max\_infidelity^{-3/2}$.
        sample_scaling: Relative number of random gate products to use in the
            tabulation. The total number of random local unitaries scales as
            ~ $max\_infidelity^{-3/2} * sample\_scaling$. Must be positive.
        random_state: Random state or random state seed.
        allow_missed_points: If True, the tabulation is allowed to conclude
            even if not all points in the Weyl chamber are expected to be
            compilable using 2 or 3 base gates. Otherwise an error is raised
            in this case.

    Returns:
        A GateTabulation object used to compile new two-qubit gates from
        products of the base gate with 1-local unitaries.

    Raises:
        ValueError: If `allow_missed_points` is False and not all points
            in the Weyl chamber were compilable using 2 or 3 base gates.
    """
    return cast(
        GateTabulation,
        two_qubit_gate_product_tabulation(
            base_gate,
            max_infidelity,
            sample_scaling=sample_scaling,
            allow_missed_points=allow_missed_points,
            random_state=random_state,
        ),
    )
Beispiel #5
0
def main(samples: int = 1000, max_infidelity: float = 0.01):
    """Demonstration of the usage of the TwoQubitGateTabulation gate compiler.

    Args:
        samples: Number of random 2-qubit unitary samples to compile.
        max_infidelity: Maximum allowed infidelity between randomly generated
            gate and the gate compilation used to generate it. The example
            runtime scales as max_infidelity^{-2}.
    """
    # Define a base gate for compilation
    theta = np.pi / 4
    phi = np.pi / 24
    base = cirq.unitary(cirq.FSimGate(theta, phi))

    # The TwoQubitGateTabulation object is essentially a tabulation of many randomly
    # generated gate products (of the form A k A or A k A k A), along with their
    # associate KAK vectors. The parameter max_infidelity determines the
    # approximate "density" of the tabulated gates. Specifically, it bounds the
    # typical distance between an arbitrary two-qubit gate and the nearest
    # tabulated gate.
    start = time()
    tabulation = cirq.two_qubit_gate_product_tabulation(base, max_infidelity)

    print(tabulation.summary)
    print(f'Gate tabulation time : {time() - start} seconds.')

    # Generate many random two-qubit gates, then attempt to compile them using
    # the tabulation.
    unitaries = [random_special_unitary(4) for _ in range(samples)]

    infidelities = []
    failed_infidelities = []
    start = time()
    for target in unitaries:
        # result.actual_gate is the compiled gate product intended to match the
        # target. result.success denotes is the actual gate is expected to be
        # within the desired fidelity to the target. It can be False if the
        # base gate cannot "fill" the Weyl chamber using at most 3 products.
        # result.local_unitaries stores the local unitaries required to
        # compile the target unitary from the base unitary.
        result = tabulation.compile_two_qubit_gate(target)
        infidelity = 1 - unitary_entanglement_fidelity(target,
                                                       result.actual_gate)
        if result.success:
            infidelities.append(infidelity)
        else:
            failed_infidelities.append(infidelity)  # coverage: ignore
    t_comp = time() - start

    print(
        f'Gate compilation time : {t_comp:.3f} seconds ({t_comp / samples:.4f} s per gate)'
    )

    infidelities = np.array(infidelities)
    failed_infidelities = np.array(failed_infidelities)

    if np.size(failed_infidelities):
        # coverage: ignore
        print(
            f'Number of "failed" compilations: {np.size(failed_infidelities)}.'
        )
        print(
            f'Maximum infidelity of "failed" compilation: {np.max(failed_infidelities)}'
        )

    plt.figure()
    plt.hist(infidelities, bins=25, range=[0, max_infidelity * 1.1])
    ylim = plt.ylim()
    plt.plot([max_infidelity] * 2,
             ylim,
             '--',
             label='Maximum tabulation infidelity')
    plt.xlabel('Compiled gate infidelity vs target')
    plt.ylabel('Counts')
    plt.legend()
    plt.title(f'Base FSim(theta={theta:.4f}, phi={phi:.4f})')

    plt.show()
Beispiel #6
0
        matrix_gate(q[0]).controlled_by(q[1]).with_tags('test_tags'),
        matrix_gate(q[0]).with_tags('test_tags').controlled_by(q[1]),
    ],
)
def test_supported_operation(op):
    circuit = cirq.Circuit(op)
    converted_circuit = cirq.optimize_for_target_gateset(
        circuit, gateset=cirq_google.SycamoreTargetGateset()
    )
    cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
        circuit, converted_circuit, atol=1e-8
    )
    multi_qubit_ops = [e for e in converted_circuit.all_operations() if len(e.qubits) > 1]
    assert all(isinstance(e.gate, cirq_google.SycamoreGate) for e in multi_qubit_ops)


@pytest.mark.parametrize(
    'gateset',
    [
        cirq_google.SycamoreTargetGateset(),
        cirq_google.SycamoreTargetGateset(
            tabulation=cirq.two_qubit_gate_product_tabulation(
                cirq.unitary(cirq_google.SYC), 0.1, random_state=cirq.value.parse_random_state(11)
            )
        ),
    ],
)
def test_repr_json(gateset):
    assert eval(repr(gateset)) == gateset
    assert cirq.read_json(json_text=cirq.to_json(gateset)) == gateset