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
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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))
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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)