def test_bitstring_accumulator_errors(): q0, q1 = cirq.LineQubit.range(2) settings = cw.observables_to_settings( [ cirq.X(q0), cirq.Y(q0), cirq.Z(q0), cirq.Z(q0) * cirq.Z(q1), ], qubits=[q0, q1], ) grouped_settings = cw.group_settings_greedy(settings) max_setting = list(grouped_settings.keys())[0] simul_settings = grouped_settings[max_setting] with pytest.raises(ValueError): bsa = cw.BitstringAccumulator( meas_spec=_MeasurementSpec(max_setting, {}), simul_settings=simul_settings, qubit_to_index={ q0: 0, q1: 1 }, bitstrings=np.array([[0, 1], [0, 1]]), chunksizes=np.array([2]), ) with pytest.raises(ValueError): bsa = cw.BitstringAccumulator( meas_spec=_MeasurementSpec(max_setting, {}), simul_settings=simul_settings, qubit_to_index={ q0: 0, q1: 1 }, bitstrings=np.array([[0, 1], [0, 1]]), chunksizes=np.array([3]), timestamps=[datetime.datetime.now()], ) bsa = cw.BitstringAccumulator( meas_spec=_MeasurementSpec(max_setting, {}), simul_settings=simul_settings[:1], qubit_to_index={ q0: 0, q1: 1 }, ) with pytest.raises(ValueError): bsa.covariance() with pytest.raises(ValueError): bsa.variance(simul_settings[0]) with pytest.raises(ValueError): bsa.mean(simul_settings[0]) bsa.consume_results(np.array([[0, 0]], dtype=np.uint8)) assert bsa.covariance().shape == (1, 1)
def _get_mock_readout_calibration(qa_0=90, qa_1=10, qb_0=91, qb_1=9): # Mock readout correction results by constructing a BitstringAccumulator # with two <Z> measurements q1_ro = np.array([0] * qa_0 + [1] * qa_1) q2_ro = np.array([0] * qb_0 + [1] * qb_1) rs = np.random.RandomState(52) rs.shuffle(q1_ro) rs.shuffle(q2_ro) ro_bitstrings = np.vstack((q1_ro, q2_ro)).T assert ro_bitstrings.shape == (100, 2) chunksizes = np.asarray([100]) timestamps = np.asarray([datetime.datetime.now()]) a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') qubit_to_index = {a: 0, b: 1} ro_settings = list( cw.observables_to_settings([cirq.Z(a), cirq.Z(b)], qubits=[a, b])) (ro_meas_spec_setting, ) = list( cw.observables_to_settings([cirq.Z(a) * cirq.Z(b)], qubits=[a, b])) ro_meas_spec = _MeasurementSpec(ro_meas_spec_setting, {}) ro_bsa = cw.BitstringAccumulator( meas_spec=ro_meas_spec, simul_settings=ro_settings, qubit_to_index=qubit_to_index, bitstrings=ro_bitstrings, chunksizes=chunksizes, timestamps=timestamps, ) return ro_bsa, ro_settings, ro_meas_spec_setting
def example_bsa() -> 'cw.BitstringAccumulator': """Test fixture to create an (empty) example BitstringAccumulator""" q0, q1 = cirq.LineQubit.range(2) setting = cw.InitObsSetting(init_state=cirq.KET_ZERO(q0) * cirq.KET_ZERO(q1), observable=cirq.X(q0) * cirq.Y(q1)) meas_spec = _MeasurementSpec( max_setting=setting, circuit_params={ 'beta': 0.123, 'gamma': 0.456, }, ) bsa = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[ setting, cw.InitObsSetting(init_state=setting.init_state, observable=cirq.X(q0)), cw.InitObsSetting(init_state=setting.init_state, observable=cirq.Y(q1)), ], qubit_to_index={ q0: 0, q1: 1 }, ) return bsa
def test_flatten_grouped_results(): q0, q1 = cirq.LineQubit.range(2) settings = cw.observables_to_settings( [cirq.X(q0), cirq.Y(q0), cirq.Z(q0), cirq.Z(q0) * cirq.Z(q1)], qubits=[q0, q1]) grouped_settings = cw.group_settings_greedy(settings) bsas = [] for max_setting, simul_settings in grouped_settings.items(): bsa = cw.BitstringAccumulator( meas_spec=_MeasurementSpec(max_setting, {}), simul_settings=simul_settings, qubit_to_index={ q0: 0, q1: 1 }, ) bsa.consume_results(np.array([[0, 0], [0, 0], [0, 0]], dtype=np.uint8)) bsas.append(bsa) results = cw.flatten_grouped_results(bsas) assert len(results) == 4 for res in results: # We pass all 0's to each consume_results, so everything is 1 +- 0 assert res.mean == 1 assert res.variance == 0 assert res.repetitions == 3
def test_bitstring_accumulator_stats(): kwargs = _get_ZZ_Z_Z_bsa_constructor_args() settings = kwargs['simul_settings'] a, b = kwargs['qubit_to_index'] bsa = cw.BitstringAccumulator(**kwargs) # There are three observables, each with mean 0 because # the four 2-bit strings have even numbers of a) ones in the # first position b) ones in the second position c) even parity # pairs. np.testing.assert_allclose([0, 0, 0], bsa.means()) # Covariance: Sum[(x - xbar)(y - ybar)] / (N-1) # where xbar and ybar are 0, per above. Each individual observed # value is +-1, so (x-xbar)(y-bar) is +-1 (neglecting observable coefficients) # For off-diagonal elements, there are two +1 and two -1 terms for each entry # so the total contribution is zero, and the matrix is diagonal should_be = np.array([[4 * 7**2, 0, 0], [0, 4 * 5**2, 0], [0, 0, 4 * 3**2]]) should_be = should_be / (4 - 1) # covariance formula should_be = should_be / 4 # cov of the distribution of sample mean np.testing.assert_allclose(should_be, bsa.covariance()) for setting, var in zip(settings, [4 * 7**2, 4 * 5**2, 4 * 3**2]): np.testing.assert_allclose(0, bsa.mean(setting)) np.testing.assert_allclose(var / 4 / (4 - 1), bsa.variance(setting)) np.testing.assert_allclose(np.sqrt(var / 4 / (4 - 1)), bsa.stderr(setting)) bad_obs = [cirq.X(a) * cirq.X(b)] bad_setting = list(cw.observables_to_settings(bad_obs, qubits=[a, b]))[0] with pytest.raises(ValueError): bsa.mean(bad_setting)
def test_readout_correction_errors(): kwargs = _get_ZZ_Z_Z_bsa_constructor_args() settings = kwargs['simul_settings'] ro_bsa, _, _ = _get_mock_readout_calibration() kwargs['readout_calibration'] = ro_bsa bsa = cw.BitstringAccumulator(**kwargs) # Variance becomes singular as the estimated value approaches zero np.testing.assert_allclose(bsa.means(), [0, 0, 0]) assert bsa.variance(settings[0]) == np.inf
def test_bitstring_accumulator_stats_2(): bitstrings = np.array( [ [0, 0], [0, 0], [1, 1], [1, 1], ], np.uint8, ) chunksizes = np.asarray([4]) timestamps = np.asarray([datetime.datetime.now()]) a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') qubit_to_index = {a: 0, b: 1} settings = list( cw.observables_to_settings( [cirq.Z(a) * 5, cirq.Z(b) * 3], qubits=[a, b])) meas_spec = _MeasurementSpec(settings[0], {}) bsa = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=settings, qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, ) # There are three observables, each with mean 0 because # the four 2-bit strings have even numbers of a) ones in the # first position b) ones in the second position. np.testing.assert_allclose([0, 0], bsa.means()) # Covariance: Sum[(x - xbar)(y - ybar)] / (N-1) # where xbar and ybar are 0, per above. Each individual observed # value is +-1, so (x-xbar)(y-bar) is +-1 (neglecting observable coefficients) # In this case, the measurements are perfectly correlated. should_be = 4 * np.array([ [5 * 5, 5 * 3], [3 * 5, 3 * 3], ]) should_be = should_be / (4 - 1) # covariance formula should_be = should_be / 4 # cov of the distribution of sample mean np.testing.assert_allclose(should_be, bsa.covariance()) for setting, var in zip(settings, [4 * 5**2, 4 * 3**2]): np.testing.assert_allclose(0, bsa.mean(setting)) np.testing.assert_allclose(var / 4 / (4 - 1), bsa.variance(setting)) np.testing.assert_allclose(np.sqrt(var / 4 / (4 - 1)), bsa.stderr(setting))
def _set_up_meas_specs_for_testing(): q0, q1 = cirq.LineQubit.range(2) setting = cw.InitObsSetting(init_state=cirq.KET_ZERO(q0) * cirq.KET_ZERO(q1), observable=cirq.X(q0) * cirq.Y(q1)) meas_spec = _MeasurementSpec(max_setting=setting, circuit_params={ 'beta': 0.123, 'gamma': 0.456 }) bsa = cw.BitstringAccumulator( meas_spec, [], {q: i for i, q in enumerate(cirq.LineQubit.range(3))}) return bsa, meas_spec
def test_meas_specs_still_todo(): q0, q1 = cirq.LineQubit.range(2) setting = cw.InitObsSetting(init_state=cirq.KET_ZERO(q0) * cirq.KET_ZERO(q1), observable=cirq.X(q0) * cirq.Y(q1)) meas_spec = _MeasurementSpec( max_setting=setting, circuit_params={ 'beta': 0.123, 'gamma': 0.456, }, ) bsa = cw.BitstringAccumulator( meas_spec, [], {q: i for i, q in enumerate(cirq.LineQubit.range(3))}) # 1. before taking any data still_todo, reps = _check_meas_specs_still_todo( meas_specs=[meas_spec], accumulators={meas_spec: bsa}, desired_repetitions=1_000) assert still_todo == [meas_spec] assert reps == 1_000 # 2. After taking a mocked-out 997 shots. bsa.consume_results(np.zeros((997, 3), dtype=np.uint8)) still_todo, reps = _check_meas_specs_still_todo( meas_specs=[meas_spec], accumulators={meas_spec: bsa}, desired_repetitions=1_000) assert still_todo == [meas_spec] assert reps == 3 # 3. After taking the final 3 shots bsa.consume_results(np.zeros((reps, 3), dtype=np.uint8)) still_todo, reps = _check_meas_specs_still_todo( meas_specs=[meas_spec], accumulators={meas_spec: bsa}, desired_repetitions=1_000) assert still_todo == [] assert reps == 0
def test_readout_correction(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') ro_bsa, ro_settings, ro_meas_spec_setting = _get_mock_readout_calibration() # observables range from 1 to -1 while bitstrings range from 0 to 1 assert ro_bsa.mean(ro_settings[0]) == 0.8 assert ro_bsa.mean(ro_settings[1]) == 0.82 assert np.isclose(ro_bsa.mean(ro_meas_spec_setting), 0.8 * 0.82, atol=0.05) bitstrings = np.array( [ [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 1], [1, 1], ], dtype=np.uint8, ) chunksizes = np.asarray([len(bitstrings)]) timestamps = np.asarray([datetime.datetime.now()]) qubit_to_index = {a: 0, b: 1} settings = list( cw.observables_to_settings( [cirq.X(a) * cirq.Y(b), cirq.X(a), cirq.Y(b)], qubits=[a, b])) meas_spec = _MeasurementSpec(settings[0], {}) # First, make one with no readout correction bsa1 = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=settings, qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, ) # [XY: one excitation, X: one excitation, Y: two excitations] np.testing.assert_allclose([1 - 1 / 4, 1 - 1 / 4, 1 - 2 / 4], bsa1.means()) np.testing.assert_allclose([0.75, 0.75, 0.5], bsa1.means()) # Turn on readout correction bsa2 = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=settings, qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, readout_calibration=ro_bsa, ) # Readout correction increases variance for setting in settings: assert bsa2.variance(setting) > bsa1.variance(setting) np.testing.assert_allclose([0.75 / (0.8 * 0.82), 0.75 / 0.8, 0.5 / 0.82], bsa2.means(), atol=0.01) # Variance becomes singular when readout error is 50/50 ro_bsa_50_50, _, _ = _get_mock_readout_calibration(qa_0=50, qa_1=50) bsa3 = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=settings, qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, readout_calibration=ro_bsa_50_50, ) with pytest.raises(ZeroDivisionError): bsa3.means() assert bsa3.variance(settings[1]) == np.inf
def test_bitstring_accumulator_equality(): et = cirq.testing.EqualsTester() bitstrings = np.array( [ [0, 0], [0, 1], [1, 0], [1, 1], ], dtype=np.uint8, ) chunksizes = np.asarray([4]) timestamps = np.asarray([datetime.datetime.now()]) a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') qubit_to_index = {a: 0, b: 1} obs = cirq.Z(a) * cirq.Z(b) * 10 setting = cw.InitObsSetting(init_state=cirq.Z(a) * cirq.Z(b), observable=obs) meas_spec = _MeasurementSpec(setting, {}) cirq.testing.assert_equivalent_repr( cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings.copy(), chunksizes=chunksizes.copy(), timestamps=timestamps.copy(), )) et.add_equality_group( cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings.copy(), chunksizes=chunksizes.copy(), timestamps=timestamps.copy(), ), cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings.copy(), chunksizes=chunksizes.copy(), timestamps=timestamps.copy(), ), ) time.sleep(1) timestamps = np.asarray([datetime.datetime.now()]) et.add_equality_group( cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, )) et.add_equality_group( cw.BitstringAccumulator( meas_spec=_MeasurementSpec(setting, {'a': 2}), simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, )) bitstrings = bitstrings.copy() bitstrings[0] = [1, 1] et.add_equality_group( cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, )) chunksizes = np.asarray([2, 2]) timestamps = np.asarray(list(timestamps) * 2) et.add_equality_group( cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=[setting], qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, ))
def test_bitstring_accumulator_stats(): bitstrings = np.array( [ [0, 0], [0, 1], [1, 0], [1, 1], ], dtype=np.uint8, ) chunksizes = np.asarray([4]) timestamps = np.asarray([datetime.datetime.now()]) a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') qubit_to_index = {a: 0, b: 1} settings = list( cw.observables_to_settings( [cirq.Z(a) * cirq.Z(b) * 7, cirq.Z(a) * 5, cirq.Z(b) * 3], qubits=[a, b])) meas_spec = _MeasurementSpec(settings[0], {}) bsa = cw.BitstringAccumulator( meas_spec=meas_spec, simul_settings=settings, qubit_to_index=qubit_to_index, bitstrings=bitstrings, chunksizes=chunksizes, timestamps=timestamps, ) # There are three observables, each with mean 0 because # the four 2-bit strings have even numbers of a) ones in the # first position b) ones in the second position c) even parity # pairs. np.testing.assert_allclose([0, 0, 0], bsa.means()) # Covariance: Sum[(x - xbar)(y - ybar)] / (N-1) # where xbar and ybar are 0, per above. Each individual observed # value is +-1, so (x-xbar)(y-bar) is +-1 (neglecting observable coefficients) # For off-diagonal elements, there are two +1 and two -1 terms for each entry # so the total contribution is zero, and the matrix is diagonal should_be = np.array([ [4 * 7**2, 0, 0], [0, 4 * 5**2, 0], [0, 0, 4 * 3**2], ]) should_be = should_be / (4 - 1) # covariance formula should_be = should_be / 4 # cov of the distribution of sample mean np.testing.assert_allclose(should_be, bsa.covariance()) for setting, var in zip(settings, [4 * 7**2, 4 * 5**2, 4 * 3**2]): np.testing.assert_allclose(0, bsa.mean(setting)) np.testing.assert_allclose(var / 4 / (4 - 1), bsa.variance(setting)) np.testing.assert_allclose(np.sqrt(var / 4 / (4 - 1)), bsa.stderr(setting)) bad_obs = [cirq.X(a) * cirq.X(b)] bad_setting = list(cw.observables_to_settings(bad_obs, qubits=[a, b]))[0] with pytest.raises(ValueError): bsa.mean(bad_setting)