Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace standard deviation in operator estimation with standard error #870

Merged
merged 4 commits into from
Apr 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions pyquil/operator_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,16 +719,16 @@ class ExperimentResult:

setting: ExperimentSetting
expectation: Union[float, complex]
stddev: Union[float, complex]
std_err: Union[float, complex]
total_counts: int
raw_expectation: Union[float, complex] = None
raw_stddev: float = None
raw_std_err: float = None
calibration_expectation: Union[float, complex] = None
calibration_stddev: Union[float, complex] = None
calibration_std_err: Union[float, complex] = None
calibration_counts: int = None

def __str__(self):
return f'{self.setting}: {self.expectation} +- {self.stddev}'
return f'{self.setting}: {self.expectation} +- {self.std_err}'

def __repr__(self):
return f'ExperimentResult[{self}]'
Expand All @@ -738,19 +738,19 @@ def serializable(self):
'type': 'ExperimentResult',
'setting': self.setting,
'expectation': self.expectation,
'stddev': self.stddev,
'std_err': self.std_err,
'total_counts': self.total_counts,
'raw_expectation': self.raw_expectation,
'raw_stddev': self.raw_stddev,
'raw_std_err': self.raw_std_err,
'calibration_expectation': self.calibration_expectation,
'calibration_stddev': self.calibration_stddev,
'calibration_std_err': self.calibration_std_err,
'calibration_counts': self.calibration_counts,
}


def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperiment,
n_shots: int = 10000, progress_callback=None, active_reset=False,
readout_symmetrize: str = 'exhaustive',
symmetrize_readout: str = 'exhaustive',
calibrate_readout: str = 'plus-eig'):
"""
Measure all the observables in a TomographyExperiment.
Expand All @@ -766,7 +766,7 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
to True is much faster but there is a ~1% error per qubit in the reset operation.
Thermal noise from "traditional" reset is not routinely characterized but is of the same
order.
:param readout_symmetrize: Method used to symmetrize the readout errors, i.e. set
:param symmetrize_readout: Method used to symmetrize the readout errors, i.e. set
p(0|1) = p(1|0). For uncorrelated readout errors, this can be achieved by randomly
selecting between the POVMs {X.D1.X, X.D0.X} and {D0, D1} (where both D0 and D1 are
diagonal). However, here we currently support exhaustive symmetrization and loop through
Expand All @@ -781,7 +781,7 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
The preceding symmetrization and this step together yield a more accurate estimation of the observable. Set to `None` if no calibration is desired.
"""
# calibration readout only works with symmetrization turned on
if calibrate_readout is not None and readout_symmetrize is None:
if calibrate_readout is not None and symmetrize_readout is None:
raise ValueError("Readout calibration only works with readout symmetrization turned on")

# Outer loop over a collection of grouped settings for which we can simultaneously
Expand Down Expand Up @@ -809,10 +809,10 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
# 2. Symmetrization
qubits = max_weight_out_op.get_qubits()

if readout_symmetrize == 'exhaustive' and len(qubits) > 0:
if symmetrize_readout == 'exhaustive' and len(qubits) > 0:
bitstrings, d_qub_idx = _exhaustive_symmetrization(qc, qubits, n_shots, total_prog)

elif readout_symmetrize is None and len(qubits) > 0:
elif symmetrize_readout is None and len(qubits) > 0:
total_prog_no_symm = total_prog.copy()
ro = total_prog_no_symm.declare('ro', 'BIT', len(qubits))
d_qub_idx = {}
Expand Down Expand Up @@ -853,7 +853,7 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
yield ExperimentResult(
setting=setting,
expectation=coeff,
stddev=0.0,
std_err=0.0,
total_counts=n_shots,
)
continue
Expand All @@ -866,7 +866,7 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
# 4.1 Obtain calibration program
calibr_prog = _calibration_program(qc, tomo_experiment, setting)
# 4.2 Perform symmetrization on the calibration program
if readout_symmetrize == 'exhaustive':
if symmetrize_readout == 'exhaustive':
qubs_calibr = setting.out_operator.get_qubits()
calibr_shots = n_shots
calibr_results, d_calibr_qub_idx = _exhaustive_symmetrization(qc, qubs_calibr, calibr_shots, calibr_prog)
Expand All @@ -883,12 +883,12 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
yield ExperimentResult(
setting=setting,
expectation=corrected_mean.item(),
stddev=np.sqrt(corrected_var).item(),
std_err=np.sqrt(corrected_var).item(),
total_counts=n_shots,
raw_expectation=obs_mean.item(),
raw_stddev=np.sqrt(obs_var).item(),
raw_std_err=np.sqrt(obs_var).item(),
calibration_expectation=obs_calibr_mean.item(),
calibration_stddev=np.sqrt(obs_calibr_var).item(),
calibration_std_err=np.sqrt(obs_calibr_var).item(),
calibration_counts=calibr_shots,
)

Expand All @@ -897,7 +897,7 @@ def measure_observables(qc: QuantumComputer, tomo_experiment: TomographyExperime
yield ExperimentResult(
setting=setting,
expectation=obs_mean.item(),
stddev=np.sqrt(obs_var).item(),
std_err=np.sqrt(obs_var).item(),
total_counts=n_shots,
)

Expand Down Expand Up @@ -1000,7 +1000,7 @@ def _exhaustive_symmetrization(qc: QuantumComputer, qubits: List[int],
# Symmetrize -- flip qubits pre-measurement
n_shots_symm = int(round(np.ceil(shots / 2**len(qubits))))
if n_shots_symm * 2**len(qubits) > shots:
warnings.warn("Symmetrization increasing number of shots from {} to {}".format(shots, round(n_shots_symm * 2**len(qubits))))
warnings.warn(f"Symmetrization increasing number of shots from {shots} to {round(n_shots_symm * 2**len(qubits))}")
list_bitstrings_symm = []
for ops_bool in itertools.product([0, 1], repeat=len(qubits)):
total_prog_symm = prog.copy()
Expand Down Expand Up @@ -1034,7 +1034,7 @@ def _calibration_program(qc: QuantumComputer, tomo_experiment: TomographyExperim

:param tomo_experiment: A suite of tomographic observables
:param ExperimentSetting: The particular tomographic observable to measure
:param readout_symmetrize: Method used to symmetrize the readout errors (see docstring for
:param symmetrize_readout: Method used to symmetrize the readout errors (see docstring for
`measure_observables` for more details)
:param cablir_shots: number of shots to take in the measurement process
:return: Program performing the calibration
Expand Down
Loading