1# Copyright 2019 The Cirq Developers 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import matplotlib.pyplot as plt 16import numpy as np 17import pytest 18import cirq 19 20from cirq.experiments import ( 21 CrossEntropyResult, 22 CrossEntropyResultDict, 23 cross_entropy_benchmarking, 24 build_entangling_layers, 25) 26from cirq.experiments.cross_entropy_benchmarking import CrossEntropyPair, SpecklePurityPair 27 28 29def test_cross_entropy_benchmarking(): 30 # Check that the fidelities returned from a four-qubit XEB simulation are 31 # close to 1 (deviations from 1 is expected due to finite number of 32 # measurements). 33 simulator = cirq.Simulator() 34 qubits = cirq.GridQubit.square(2) 35 36 # Sanity check single-qubit-gate causes error 37 with pytest.raises(ValueError): 38 build_entangling_layers(qubits, cirq.Z ** 0.91) 39 40 # Build a sequence of CZ gates. 41 interleaved_ops = build_entangling_layers(qubits, cirq.CZ ** 0.91) 42 43 # Specify a set of single-qubit rotations. Pick prime numbers for the 44 # exponent to avoid evolving the system into a basis state. 45 single_qubit_rots = [ 46 [cirq.X ** 0.37], 47 [cirq.Y ** 0.73, cirq.X ** 0.53], 48 [cirq.Z ** 0.61, cirq.X ** 0.43], 49 [cirq.Y ** 0.19], 50 ] 51 52 # Simulate XEB using the default single-qubit gate set without two-qubit 53 # gates, XEB using the specified single-qubit gate set without two-qubit 54 # gates, and XEB using the specified single-qubit gate set with two-qubit 55 # gate. Check that the fidelities are close to 1.0 in all cases. Also, 56 # check that a single XEB fidelity is returned if a single cycle number 57 # is specified. 58 results_0 = cross_entropy_benchmarking( 59 simulator, qubits, num_circuits=3, repetitions=1000, cycles=range(4, 20, 5) 60 ) 61 results_1 = cross_entropy_benchmarking( 62 simulator, 63 qubits, 64 num_circuits=3, 65 repetitions=1000, 66 cycles=[4, 8, 12], 67 scrambling_gates_per_cycle=single_qubit_rots, 68 ) 69 results_2 = cross_entropy_benchmarking( 70 simulator, 71 qubits, 72 benchmark_ops=interleaved_ops, 73 num_circuits=3, 74 repetitions=1000, 75 cycles=[4, 8, 12], 76 scrambling_gates_per_cycle=single_qubit_rots, 77 ) 78 results_3 = cross_entropy_benchmarking( 79 simulator, 80 qubits, 81 benchmark_ops=interleaved_ops, 82 num_circuits=3, 83 repetitions=1000, 84 cycles=15, 85 scrambling_gates_per_cycle=single_qubit_rots, 86 ) 87 fidelities_0 = [datum.xeb_fidelity for datum in results_0.data] 88 fidelities_1 = [datum.xeb_fidelity for datum in results_1.data] 89 fidelities_2 = [datum.xeb_fidelity for datum in results_2.data] 90 fidelities_3 = [datum.xeb_fidelity for datum in results_3.data] 91 assert np.isclose(np.mean(fidelities_0), 1.0, atol=0.1) 92 assert np.isclose(np.mean(fidelities_1), 1.0, atol=0.1) 93 assert np.isclose(np.mean(fidelities_2), 1.0, atol=0.1) 94 assert len(fidelities_3) == 1 95 96 # Sanity test that plot runs. 97 ax = plt.subplot() 98 results_1.plot(ax) 99 100 101def test_cross_entropy_result_depolarizing_models(): 102 prng = np.random.RandomState(59566) 103 S = 0.8 104 p = 0.99 105 data = [ 106 CrossEntropyPair(num_cycle=d, xeb_fidelity=S * p ** d + prng.normal(scale=0.01)) 107 for d in range(10, 211, 20) 108 ] 109 purity_data = [ 110 SpecklePurityPair(num_cycle=d, purity=S * p ** (2 * d) + prng.normal(scale=0.01)) 111 for d in range(10, 211, 20) 112 ] 113 result = CrossEntropyResult(data=data, repetitions=1000, purity_data=purity_data) 114 model = result.depolarizing_model() 115 purity_model = result.purity_depolarizing_model() 116 np.testing.assert_allclose(model.spam_depolarization, S, atol=1e-2) 117 np.testing.assert_allclose(model.cycle_depolarization, p, atol=1e-2) 118 np.testing.assert_allclose(purity_model.purity, p ** 2, atol=1e-2) 119 120 121def test_cross_entropy_result_repr(): 122 result1 = CrossEntropyResult( 123 data=[CrossEntropyPair(2, 0.9), CrossEntropyPair(5, 0.5)], repetitions=1000 124 ) 125 result2 = CrossEntropyResult( 126 data=[CrossEntropyPair(2, 0.9), CrossEntropyPair(5, 0.5)], 127 repetitions=1000, 128 purity_data=[SpecklePurityPair(2, 0.8), SpecklePurityPair(5, 0.3)], 129 ) 130 cirq.testing.assert_equivalent_repr(result1) 131 cirq.testing.assert_equivalent_repr(result2) 132 133 134def test_cross_entropy_result_dict_repr(): 135 pair = tuple(cirq.LineQubit.range(2)) 136 result = CrossEntropyResult( 137 data=[CrossEntropyPair(2, 0.9), CrossEntropyPair(5, 0.5)], repetitions=1000 138 ) 139 result_dict = CrossEntropyResultDict(results={pair: result}) 140 cirq.testing.assert_equivalent_repr(result_dict) 141 142 143def test_cross_entropy_result_purity_model_fails_with_no_data(): 144 data = [ 145 CrossEntropyPair(num_cycle=2, xeb_fidelity=0.9), 146 CrossEntropyPair(num_cycle=4, xeb_fidelity=0.8), 147 ] 148 result = CrossEntropyResult(data=data, repetitions=1000) 149 with pytest.raises(ValueError): 150 _ = result.purity_depolarizing_model() 151