def test_execute_with_pec_with_different_samples(circuit: Circuit, seed): """Tests that, on average, the error decreases as the number of samples is increased. """ errors_few_samples = [] errors_more_samples = [] for _ in range(10): mitigated = execute_with_pec( circuit, executor, decomposition_dict=DECO_DICT, num_samples=10, random_state=seed, ) errors_few_samples.append(abs(mitigated - 1.0)) mitigated = execute_with_pec( circuit, executor, decomposition_dict=DECO_DICT, num_samples=100, random_state=seed, ) errors_more_samples.append(abs(mitigated - 1.0)) assert np.average(errors_more_samples) < np.average(errors_few_samples)
def test_precision_option_in_execute_with_pec(precision: float): """Tests that the 'precision' argument is used to deduce num_samples.""" rnd_state = np.random.RandomState(0) def fake_exec(circuit: Circuit): """A fake executor which just samples from a normal distribution.""" return rnd_state.randn() # For a noiseless circuit we expect num_samples = 1/precision^2: _, pec_error = execute_with_pec( oneq_circ, fake_exec, NOISELESS_DECO_DICT, precision=precision, full_output=True, ) # The error should scale as precision assert np.isclose(pec_error / precision, 1.0, atol=0.1) # If num_samples is given, precision is ignored. _, pec_error = execute_with_pec( oneq_circ, fake_exec, NOISELESS_DECO_DICT, precision=precision, num_samples=1000, full_output=True, ) # The error should scale as 1/sqrt(num_samples) assert not np.isclose(pec_error / precision, 1.0, atol=0.1) assert np.isclose(pec_error * np.sqrt(1000), 1.0, atol=0.1)
def test_large_sample_size_warning(num_samples: int): """Tests whether a warning is raised when PEC sample size is greater than 10 ** 5 """ rnd_state = np.random.RandomState(0) def fake_exec(circuit: Circuit): """A fake executor which just samples from a normal distribution.""" return rnd_state.randn() with warns(LargeSampleWarning, match=r"The number of PEC samples is very large."): execute_with_pec(oneq_circ, fake_exec, DECO_DICT, num_samples=num_samples)
def test_execute_with_pec_with_full_output(): """Tests that the error associated to the PEC value is returned if the option 'full_output' is set to True. """ rnd_state = np.random.RandomState(0) def fake_exec(circuit: Circuit): """A fake executor which just samples from a normal distribution.""" return rnd_state.randn() _, error_few_samples = execute_with_pec( oneq_circ, fake_exec, DECO_DICT, num_samples=100, full_output=True ) _, error_many_samples = execute_with_pec( oneq_circ, fake_exec, DECO_DICT, num_samples=1000, full_output=True ) # The error should scale as 1/sqrt(num_samples) assert np.isclose(error_few_samples * np.sqrt(100), 1.0, atol=0.1) assert np.isclose(error_many_samples * np.sqrt(1000), 1.0, atol=0.1)
def test_execute_with_pec_one_qubit(circuit: Circuit, decomposition_dict: DecompositionDict): """Tests that execute_with_pec mitigates the error of a noisy expectation value. """ unmitigated = executor(circuit) mitigated = execute_with_pec(circuit, executor, decomposition_dict=decomposition_dict) error_unmitigated = abs(unmitigated - 1.0) error_mitigated = abs(mitigated - 1.0) # For a trivial noiseless decomposition no PEC mitigation should happen if decomposition_dict == NOISELESS_DECO_DICT: assert np.isclose(unmitigated, mitigated) else: assert error_mitigated < error_unmitigated assert np.isclose(mitigated, 1.0, atol=0.1)
def test_bad_precision_argument(bad_value: float): """Tests that if 'precision' is not within (0, 1] an error is raised.""" with raises(ValueError, match="The value of 'precision' should"): execute_with_pec(oneq_circ, executor, DECO_DICT, precision=bad_value)