def test_sycamore_gate_tabulation(seed): base_gate = cirq.unitary(cirq.FSimGate(np.pi / 2, np.pi / 6)) tab = gate_product_tabulation( base_gate, 0.1, sample_scaling=2, random_state=np.random.RandomState(seed) ) result = tab.compile_two_qubit_gate(base_gate) assert result.success
def test_gate_compilation_on_base_gate_identity(): tabulation = gate_product_tabulation(np.eye(4), 0.25) base_gate = tabulation.base_gate result = tabulation.compile_two_qubit_gate(base_gate) assert len(result.local_unitaries) == 2 assert result.success fidelity = unitary_entanglement_fidelity(result.actual_gate, base_gate) assert fidelity > 0.99999
def test_convert_to_sycamore_tabulation(): # A tabulation for the sycamore gate with an infidelity of .1. sycamore_tabulation = 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]) 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)
def test_gate_compilation_missing_points_raises_error(): with pytest.raises(ValueError, match='Failed to tabulate a'): gate_product_tabulation(np.eye(4), 0.4, allow_missed_points=False, random_state=_rng)
"""Tests for gate_compilation.py""" import numpy as np import pytest from cirq import unitary, FSimGate, value from cirq_google.optimizers.two_qubit_gates.gate_compilation import ( gate_product_tabulation, GateTabulation, ) from cirq_google.optimizers.two_qubit_gates.math_utils import unitary_entanglement_fidelity from cirq.testing import random_special_unitary, assert_equivalent_repr _rng = value.parse_random_state(11) # for determinism sycamore_tabulation = gate_product_tabulation(unitary( FSimGate(np.pi / 2, np.pi / 6)), 0.2, random_state=_rng) sqrt_iswap_tabulation = gate_product_tabulation(unitary( FSimGate(np.pi / 4, np.pi / 24)), 0.1, random_state=_rng) _random_2Q_unitaries = np.array( [random_special_unitary(4, random_state=_rng) for _ in range(100)]) @pytest.mark.parametrize('tabulation', [sycamore_tabulation, sqrt_iswap_tabulation]) @pytest.mark.parametrize('target', _random_2Q_unitaries) def test_gate_compilation_matches_expected_max_infidelity(tabulation, target):
def test_deprecated_gate_product_tabulation(): with cirq.testing.assert_deprecated( deadline='v0.16', count=None, ): _ = gate_product_tabulation(np.eye(4), 0.25)
def main(samples: int = 1000, max_infidelity: float = 0.01): """Demonstration of the usage of the GateTabulation 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 = unitary(FSimGate(theta, phi)) # The GateTabulation 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 = 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()