Execution Outcomes#
Qibo circuits return different objects when executed depending on what the circuit contains and on the settings of the simulation. The following table summarizes which outcomes to expect depending on whether:
the circuit contains noise channels
the qubits are measured at the end of the execution
some collapse measurement is present in the circuit
density_matrixis set toTruein simulation
Noise |
Measurements |
Collapse |
Density Matrix |
Outcome |
|---|---|---|---|---|
❌ |
❌ |
❌ |
❌ / ✅ |
|
❌ |
✅ |
❌ |
❌ / ✅ |
|
❌ / ✅ |
❌ |
❌ / ✅ |
✅ |
|
❌ / ✅ |
✅ |
❌ / ✅ |
❌ |
|
❌ / ✅ |
✅ |
❌ / ✅ |
✅ |
Therefore, one of the three objects qibo.result.QuantumState,
qibo.result.MeasurementOutcomes or qibo.result.CircuitResult
is going to be returned by the circuit execution. The first gives acces to the final
state and probabilities via the qibo.result.QuantumState.state() and
qibo.result.QuantumState.probabilities() methods, whereas the second
allows to retrieve the final samples, the frequencies and the probabilities (calculated
as frequencies/nshots) with the qibo.result.MeasurementOutcomes.samples(),
qibo.result.MeasurementOutcomes.frequencies() and
qibo.result.MeasurementOutcomes.probabilities() methods respectively. The
qibo.result.CircuitResult object includes all the above instead.
Every time some measurement is performed at the end of the execution, the result
will be a CircuitResult unless the final state could not be represented with the
current simulation settings, i.e. if some stochasticity is present in the ciruit
(via noise channels or collapse measurements) and density_matrix=False. In that
case a simple MeasurementOutcomes object is returned.
If no measurement is appended at the end of the circuit, the final QuantumState
is going to be provided as output. However, if the circuit is stochastic,
density_matrix should be set to True in order to recover the final state,
otherwise an error is raised.
The final result of the circuit execution can also be saved to disk and loaded back:
circuit = Circuit(2)
circuit.add(gates.M(0,1))
# this will be a CircuitResult object
result = circuit()
# save it to final_result.npy
result.dump('final_result.npy')
# can be loaded back
from qibo.result import load_result
loaded_result = load_result('final_result.npy')
- class qibo.result.QuantumState(state, backend=None)[source]#
Data structure to represent the final state after circuit execution.
- Parameters:
state (ndarray) – Input quantum state as
ndarray.backend (
qibo.backends.abstract.Backend) – Backend used for the calculations. If not provided, the global backend is going to be used.
- symbolic(decimals=5, cutoff=1e-10, max_terms=20)[source]#
Dirac notation representation of the state in the computational basis.
- Parameters:
decimals (int, optional) – Number of decimals for the amplitudes. Defaults to \(5\).
cutoff (float, optional) – Amplitudes with absolute value smaller than the cutoff are ignored from the representation. Defaults to
1e-10.max_terms (int, optional) – Maximum number of terms to print. If the state contains more terms they will be ignored. Defaults to \(20\).
- Returns:
String representing the state in the computational basis.
- Return type:
- state(numpy=False)[source]#
State’s tensor representation as a backend tensor.
Note
If the state has Hamming weight \(k\) and is computed using the
HammingWeightBackend, its dimension is \(d = \binom{n}{k}\), where \(n\) is the number of qubits.- Parameters:
numpy (bool, optional) – If
Truethe returned tensor will be anumpyarray, otherwise it will follow the backend tensor type. Defaults toFalse.- Returns:
The state in the computational basis.
- probabilities(qubits=None)[source]#
Calculates measurement probabilities by tracing out qubits.
When noisy model is applied to a circuit and circuit.density_matrix=False, this method returns the average probability resulting from repeated execution. This probability distribution approximates the exact probability distribution obtained when circuit.density_matrix=True.
- to_dict()[source]#
Returns a dictonary containinig all the information needed to rebuild the
QuantumState
- dump(filename)[source]#
Writes to file the
QuantumStatefor future reloading.- Parameters:
filename (str) – Path to the file to write to.
- classmethod from_dict(payload)[source]#
Builds a
QuantumStateobject starting from a dictionary.- Parameters:
payload (dict) – Dictionary containing all the information to load the
QuantumStateobject.- Returns:
Quantum state object..
- Return type:
- class qibo.result.MeasurementOutcomes(measurements, backend=None, probabilities=None, samples=None, nshots=1000, nqubits=None)[source]#
Object to store the outcomes of measurements after circuit execution.
- Parameters:
measurements (
qibo.gates.M) – Measurement gates.backend (
qibo.backends.abstract.Backend) – Backend used for the calculations. IfNone, then the current backend is used. Defaults toNone.probabilities (np.ndarray) – Use these probabilities to generate samples and frequencies.
samples (np.darray) – Use these samples to generate probabilities and frequencies.
nshots (int) – Number of shots used for samples, probabilities and frequencies generation.
nqubits (int, optional) – Total number of qubits in the circuit. When set,
probabilities()withqubits=Nonereturns probabilities over all circuit qubits (not just the measured ones). IfNone, defaults to the number of measured qubits. Defaults toNone.
- frequencies(binary=True, registers=False)[source]#
Returns the frequencies of measured samples.
- Parameters:
- Returns:
A
collections.Counterwhere the keys are the observed values and the values the corresponding frequencies, that is the number of times each measured value/bitstring appears.- If
binaryisTrue the keys of the
collections.Counterare in binary form, as strings of \(0\) and :math`1`.- If
binaryisFalse the keys of the
collections.Counterare integers.- If
registersisTrue a dict of
collections.Counteris returned where keys are the name of each register.- If
registersisFalse a single
collections.Counteris returned which contains samples from all the measured qubits, independently of their registers.
- If
- probabilities(qubits=None)[source]#
Calculate the probabilities as frequencies / nshots
- Parameters:
qubits (list or set, optional) – Set of qubits for which to compute probabilities. If
Noneandnqubitswas provided at construction, probabilities are returned over all circuit qubits; otherwise only over the measured qubits. Defaults toNone.- Returns:
The array containing the probabilities of the requested qubits.
- Return type:
ArrayLike
- has_samples()[source]#
Check whether the samples are available already.
- Returns:
Trueif the samples are available,Falseotherwise.- Return type:
(bool)
- samples(binary=True, registers=False)[source]#
Returns raw measurement samples.
- Parameters:
- Returns:
- If
binaryisTrue samples are returned in binary form as a tensor of shape
(nshots, n_measured_qubits).- If
binaryisFalse samples are returned in decimal form as a tensor of shape
(nshots,).- If
registersisTrue samples are returned in a
dictwhere the keys are the register names and the values are the samples tensors for each register.- If
registersisFalse a single tensor is returned which contains samples from all the measured qubits, independently of their registers.
- If
- property measurement_gate#
Single measurement gate containing all measured qubits.
Useful for sampling all measured qubits at once when simulating.
- apply_bitflips(p0, p1=None)[source]#
Apply bitflips to the measurements with probabilities p0 and p1
- expectation_from_samples(observable)[source]#
Computes the real expectation value of a diagonal observable from frequencies.
- Parameters:
observable (Hamiltonian/SymbolicHamiltonian) – diagonal observable in the computational basis.
- Returns:
expectation value from samples.
- Return type:
(float)
- to_dict()[source]#
Returns a dictonary containinig all the information needed to rebuild the
qibo.result.MeasurementOutcomes.
- dump(filename)[source]#
Writes to file the
qibo.result.MeasurementOutcomesfor future reloading.- Parameters:
filename (str) – Path to the file to write to.
- classmethod from_dict(payload)[source]#
Builds a
qibo.result.MeasurementOutcomesobject starting from a dictionary.- Parameters:
payload (dict) – Dictionary containing all the information to load the
qibo.result.MeasurementOutcomesobject.- Returns:
Object storing the measurement outcomes.
- Return type:
- classmethod load(filename)[source]#
Builds the
qibo.result.MeasurementOutcomesobject stored in a file.- Parameters:
filename (str) – Path to the file containing the
qibo.result.MeasurementOutcomes.- Returns:
instance of the
MeasurementOutcomesclass.- Return type:
- classmethod from_samples(samples, qubits=None, backend=None)[source]#
Constructs a
qibo.result.MeasurementOutcomesdirectly from a binary samples array.This is useful when building measurement outcomes from experimental data without needing to manually construct measurement gates.
- Parameters:
samples (ArrayLike) – Binary array of shape
(nshots, nqubits). where each row is a measurement outcome with 0/1 values.qubits (tuple or list, optional) – Qubit indices for the measured qubits. If
None, defaults to(0, 1, ..., nqubits - 1). Defaults toNone.backend (
qibo.backends.abstract.Backend, optional) – Backend used for calculations. IfNone, the current default backend is used. Defaults toNone.
- Returns:
Object storing the measurement outcomes.
- Return type:
Example
import numpy as np from qibo.result import MeasurementOutcomes samples = np.array([[0, 1], [1, 0], [1, 1]]) result = MeasurementOutcomes.from_samples(samples) print(result.frequencies()) # Counter({'01': 1, '10': 1, '11': 1})
- classmethod from_frequencies(frequencies, nqubits=None, qubits=None, seed=None, backend=None)[source]#
Constructs a
qibo.result.MeasurementOutcomesfrom a frequencies dictionary.The frequencies are expanded into a binary samples array, shuffled to avoid ordering artifacts, and passed through the standard construction path so that all methods (
samples(),frequencies(),probabilities()) work correctly.- Parameters:
frequencies (dict or Counter) – Mapping from measurement outcomes to their counts. Keys can be binary strings (e.g.
"010") or integers (e.g.2). Values are non-negative integer counts.nqubits (int, optional) – Total number of qubits in the circuit. When binary-string keys are used, the number of measured qubits is inferred from the key length;
nqubitsmay be larger than or equal to that length, and the extra qubits are treated as unmeasured. When integer keys are used withoutqubits,nqubitsis required and is interpreted as the number of measured qubits (backward-compatible behaviour). Defaults toNone.qubits (tuple or list, optional) – Qubit indices for the measured qubits. If
None, defaults to(0, 1, ..., n_measured - 1)wheren_measuredis the number of measured qubits. Defaults toNone.seed (int, optional) – Seed for sampling generation.
backend (
qibo.backends.abstract.Backend, optional) – Backend used for calculations. IfNone, the current default backend is used. Defaults toNone.
- Returns:
Object storing the measurement outcomes.
- Return type:
- Raises:
ValueError – If the number of measured qubits cannot be determined from the inputs.
Example
from qibo.result import MeasurementOutcomes freq = {"00": 50, "11": 50} result = MeasurementOutcomes.from_frequencies(freq) print(result.frequencies()) # Counter({'00': 50, '11': 50})
- class qibo.result.CircuitResult(final_state, measurements, backend=None, samples=None, nshots=1000)[source]#
Object to store both the outcomes of measurements and the final state after circuit execution.
- Parameters:
final_state (ndarray) – Input quantum state as np.ndarray.
measurements (
qibo.gates.M) – The measurement gates containing the measurements.backend (
qibo.backends.abstract.Backend) – Backend used for the calculations. If not provided, then the current backend is going to be used.probabilities (ndarray) – Use these probabilities to generate samples and frequencies.
samples (ndarray) – Use these samples to generate probabilities and frequencies.
nshots (int) – Number of shots used for samples, probabilities and frequencies generation.
- probabilities(qubits=None)[source]#
Calculates measurement probabilities by tracing out qubits.
When noisy model is applied to a circuit and circuit.density_matrix=False, this method returns the average probability resulting from repeated execution. This probability distribution approximates the exact probability distribution obtained when circuit.density_matrix=True.
- to_dict()[source]#
Returns a dictonary containinig all the information needed to rebuild the
CircuitResult.