supermarq.qcvv.base_experiment
Base experiment class and tools used across all experiments.
Attributes
Classes
Base class for gate benchmarking experiments. |
|
A dataclass for storing the results of the experiment. Requires subclassing for |
|
A sample circuit to use along with any data about the circuit |
Module Contents
- class supermarq.qcvv.base_experiment.BenchmarkingExperiment(num_qubits: int, *, random_seed: int | numpy.random.Generator | None = None, **kwargs: Any)
Bases:
abc.ABC,Generic[ResultsT]Base class for gate benchmarking experiments.
The interface for implementing these experiments is as follows:
First instantiate the desired experiment object
experiment = ExampleExperiment(<<args/kwargs>>)
Prepare the circuits and run the experiment on the desired target. This can either be a custom simulator or a real device name. For example:
noise_model = cirq.depolarize(p=0.01, n_qubits=1) sim = cirq.DensityMatrixSimulator(noise=noise_model) experiment.prepare_experiment(<<args/kwargs>>) experiment.run_with_simulator(simulator=sim, <<args/kwargs>>)
Then we analyse the results. If the target was a local simulator this will be available as soon as the
run_with_simulator()method has finished executing. On the other hand if a real device was accessed via Superstaq then it may take time for the data to be available from the server. Thecollect_data()will returnTruewhen all data has been collected and is ready to be analysed.if experiment.collect_data(): results = experiment.analyze_results(<<args>>)
The final results of the experiment will be stored in the
resultsattribute as aBenchmarkingResultsof values, while all the data from the experiment will be stored in theraw_dataattribute as aDataFrame. Some experiments may include additional data attributes for data generated during the analysis.results = experiment.results data = experiment.raw_data
Additionally it is possible to pre-compile the experimental circuits for a given device using
experiment.prepare_experiment(<<args/kwargs>>) experiment.compile_circuits(target=<<target_name>>)
And then to run the experiment using a custom callable function for evaluating the circuits. For example this could be a function that uses a connection to a local device.
experiment.run_with_callable(<<function_name>>)
When implementing a new experiment, 4 methods need to be implemented:
_build_circuits(): Given a number of circuits and an iterable of the different numbersof layers to use, return a list of
Sampleobjects that need to be sampled during the experiment.
_process_probabilities(): Take the probability distribution over thecomputational basis resulting from running each circuit and combine the relevant details into a
pandas.DataFrame.
analyze_results(): Analyse the data in theraw_datadataframe and return aBenchmarkingResultsobject containing the results of the experiment.
plot_results(): Produce any relevant plots that are useful for understanding theresults of the experiment.
Additionally the
BenchmarkingResultsdataclass needs subclassing to hold the specific results of the new experiment.- abstract analyze_results(plot_results: bool = True) ResultsT
Perform the experiment analysis and store the results in the results attribute.
- Parameters:
plot_results – Whether to generate plots of the results. Defaults to False.
- Returns:
A named tuple of the final results from the experiment.
- collect_data(force: bool = False) bool
Collect the data from the samples and process it into the
raw_dataattribute.If the data is successfully stored in the
raw_dataattribute then the function will returnTrue.If either not all jobs submitted to the server have completed, or not all samples have probability results then no data will be saved in
raw_dataand the function will returnFalse. This check can be overridden withforce=Truein which case only the samples which have probability results will be used to generate the results dataframe.- Parameters:
force – Whether to override the check that all data is present. Defaults to False.
- Raises:
RuntimeError – If
force=Truebut there are no samples with any data.RuntimeError – If the experiment has not yet been run.
- Returns:
Whether the results dataframe has been successfully created.
- compile_circuits(target: str, **kwargs: Any) None
Compiles the experiment circuits for the given device. Useful if the samples are not going to be run via Superstaq.
- Parameters:
target – The device to compile to.
kwargs – Additional desired compile options.
- abstract plot_results() None
Plot the results of the experiment
- prepare_experiment(num_circuits: int, cycle_depths: collections.abc.Iterable[int], overwrite: bool = False) None
Prepares the circuits needed for the experiment
- Parameters:
num_circuits – Number of circuits to run.
cycle_depths – An iterable of the different layer depths to use during the experiment.
overwrite – Whether to force an experiment run even if there is existing data that would be over written in the process. Defaults to False.
- Raises:
RuntimeError – If the experiment has already been run once and the overwrite argument is not True
ValueError – If any of the cycle depths provided negative or zero.
- run_on_device(target: str, repetitions: int = 10000, method: str | None = None, overwrite: bool = False, **target_options: Any) cirq_superstaq.Job
Submit the circuit samples to the desired target device and store the resulting probabilities.
The set of circuits is partitioned as necessary to not exceed the maximum circuits that can be submitted to the given target device. The function then waits for the jobs to complete before saving the resulting probability distributions.
- Parameters:
target – The name of a Superstaq target.
repetitions – The number of shots to sample. Defaults to 10,000.
method – Optional method to use on the Superstaq device. Defaults to None corresponding to normal running.
target_options – Optional configuration dictionary passed when submitting the job.
overwrite – Whether to force an experiment run even if there is existing data that would be over written in the process. Defaults to False.
- Returns:
The superstaq job containing all the circuits submitted as part of the experiment.
- run_with_callable(circuit_eval_func: collections.abc.Callable[[cirq.Circuit], dict[str, float]], overwrite: bool = False, **kwargs: Any) None
Evaluates the probabilities for each circuit using a user provided callable function. This function should take a circuit as input and return a dictionary of probabilities for each bitstring (including states with zero probability).
- Parameters:
circuit_eval_func – The custom function to use when evaluating circuit probabilities.
overwrite – Whether to force an experiment run even if there is existing data that would be over written in the process. Defaults to False.
kwargs – Additional arguments to pass to the custom function.
- Raises:
RuntimeError – If the returned probabilities dictionary keys is missing include an incorrect number of bits.
RuntimeError – If the returned probabilities dictionary values do not sum to 1.0.
- run_with_simulator(simulator: cirq.Sampler | None = None, repetitions: int = 10000, overwrite: bool = False) None
Use the local simulator to sample the circuits and store the resulting probabilities.
- Parameters:
simulator – A local
Samplerto use. If None then the defaultcirq.Simulatorsimulator is used. Defaults to None.repetitions – The number of shots to sample. Defaults to 10,000.
overwrite – Whether to force an experiment run even if there is existing data that would be over written in the process. Defaults to False.
- property num_qubits: int
Returns: The number of qubits used in the experiment
- qubits
The qubits used in the experiment.
- property raw_data: pandas.DataFrame
The data from the most recently run experiment.
- Raises:
RuntimeError – If no results are available.
- property results: ResultsT
The results from the most recently run experiment.
- Raises:
RuntimeError – If no results are available.
- property samples: collections.abc.Sequence[Sample]
The samples generated during the experiment.
- Raises:
RuntimeError – If no samples are available.
- property targets: frozenset[str]
Returns: A set of the unique target that each sample was submitted to
- class supermarq.qcvv.base_experiment.BenchmarkingResults
Bases:
abc.ABCA dataclass for storing the results of the experiment. Requires subclassing for each new experiment type.
- experiment_name: str
The name of the experiment.
- target: str
The target device that was used.
- total_circuits: int
The total number of circuits used in the experiment.
- class supermarq.qcvv.base_experiment.Sample
A sample circuit to use along with any data about the circuit that is needed for analysis
- property circuit: cirq.Circuit
Returns: The circuit used for the experiment. Defaults to the compiled circuit if available and if not returns the raw circuit.
- compiled_circuit: cirq.Circuit | None = None
The compiled circuit. Only used if the circuits are compiled for a specific target.
- data: dict[str, Any]
The corresponding data about the circuit
- job: cirq_superstaq.Job | None = None
The superstaq job corresponding to the sample. Defaults to None if no job is associated with the sample.
- probabilities: dict[str, float] | None = None
The probabilities of the computational basis states
- raw_circuit: cirq.Circuit
The raw (i.e. pre-compiled) sample circuit.
- property target: str
Returns: The name of the target that the sample was submitted to.
- supermarq.qcvv.base_experiment.ResultsT