Computing observables
All emulators (backends) share a convenient way to define observables to be tracked during the simulation, as defined in pulser. The default available observables are listed below, together with examples for how to create them.
Example
How to use created observables to obtain results from an emulation is shown in the example notebooks for emu-sv and for emu-mps.
Warning
Please, take into account that, for performance reasons, individual emulators may overwrite the default implementation in pulser.
StateResult
Bases: Observable
Stores the quantum state at the evaluation times.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to store the state.
If left as
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
apply(*, state, **kwargs)
Calculates the observable to store in the Results.
BitStrings
Bases: Observable
Stores bitstrings sampled from the state at the evaluation times.
Error rates are taken from the NoiseModel passed to the backend via the EmulationConfig. The bitstrings are stored as a Counter[str].
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to sample bitstrings.
If left as
TYPE:
|
num_shots
|
How many bitstrings to sample each time this observable is computed.
TYPE:
|
one_state
|
The eigenstate that measures to 1. Can be left undefined if the state's eigenstates form a known eigenbasis with a defined "one state".
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
Initializes the observable.
apply(*, config, state, **kwargs)
Calculates the observable to store in the Results.
Fidelity
Bases: Observable
Stores the fidelity with a pure state at the evaluation times.
The fidelity uses the overlap between the given state and the state of
the system at each evaluation time. For pure states, this corresponds
to |<ψ|φ(t)>|^2
for the given state |ψ>
and the state |φ(t)>
obtained by time evolution.
PARAMETER | DESCRIPTION |
---|---|
state
|
The state
TYPE:
|
evaluation_times
|
The relative times at which to compute the fidelity.
If left as
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
Initializes the observable.
apply(*, state, **kwargs)
Calculates the observable to store in the Results.
Expectation
Bases: Observable
Stores the expectation of the given operator on the current state.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the
expectation value. If left as
TYPE:
|
operator
|
The operator to measure. Must be of the appropriate type for the backend.
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
Initializes the observable.
apply(*, state, **kwargs)
Calculates the observable to store in the Results.
CorrelationMatrix
Bases: Observable
Stores the correlation matrix for the current state.
The correlation matrix is calculated as
[[<φ(t)|n_i n_j|φ(t)> for j in qubits] for i in qubits]
where n_k = |one_state><one_state|
.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the
correlation matrix. If left as
TYPE:
|
one_state
|
The eigenstate to measure the population of in the correlation matrix. Can be left undefined if the state's eigenstates form a known eigenbasis with a defined "one state".
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
Initializes the observable.
apply(*, state, hamiltonian, **kwargs)
Calculates the observable to store in the Results.
QubitDensity
Bases: Observable
Stores the occupation number of an eigenstate on each qudit.
For every qudit i, calculates <φ(t)|n_i|φ(t)>
, where
n_i = |one_state><one_state|
.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the
correlation matrix. If left as
TYPE:
|
one_state
|
The eigenstate to measure the population of. Can be left undefined if the state's eigenstates form a known eigenbasis with a defined "one state".
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
Initializes the observable.
apply(*, state, hamiltonian, **kwargs)
Calculates the observable to store in the Results.
Energy
Bases: Observable
Stores the energy of the system at the evaluation times.
The energy is calculated as the expectation value of the Hamiltonian,
i.e. <φ(t)|H(t)|φ(t)>
.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the energy.
If left as
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
apply(*, state, hamiltonian, **kwargs)
Calculates the observable to store in the Results.
EnergyVariance
Bases: Observable
Stores the variance of the Hamiltonian at the evaluation times.
The variance of the Hamiltonian at time t
is calculated by
<φ(t)|H(t)^2|φ(t)> - <φ(t)|H(t)|φ(t)>^2
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the variance.
If left as
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
apply(*, state, hamiltonian, **kwargs)
Calculates the observable to store in the Results.
SecondMomentOfEnergy
Bases: Observable
Stores the expectation value of H(t)^2
at the evaluation times.
Useful for computing the variance when averaging over many executions of the program.
PARAMETER | DESCRIPTION |
---|---|
evaluation_times
|
The relative times at which to compute the variance.
If left as
TYPE:
|
tag_suffix
|
An optional suffix to append to the tag. Needed if multiple instances of the same observable are given to the same EmulationConfig.
TYPE:
|
apply(*, state, hamiltonian, **kwargs)
Calculates the observable to store in the Results.
Defining your own observable
Most commonly desired information can be obtained using the classes documented above
- Arbitrary observables can be measured using
Expectation(operator, ...)
which requires providing a valid operator for the backend in use. - Fidelities on arbitrary states can be computed using
Fidelity(state, ...)
which requires providing a valid state for the backend in use. - Information about the time dependent states and Hamiltonians is available via
StateResult
,Energy
etc.
If additional behavior is desired (e.g. the kurtosis of the energy, or entanglement entropy), the user can subclass the Observable
class to implement any behavior only depending on the parameters of its apply
method (see here). Computation of the entanglement entropy, for example, cannot be done in a backend-independent manner, so it is unlikely to ever make it into the above default list. However, we do intend to define backend-specific callbacks in the future, which would belong to the API of a specific backend. Callbacks that can be implemented in a backend-independent manner can be added to the above list upon popular request.
Observables on remote backend
In heavy simulations, the entire quantum state can easily occupy few GBs while operators, might not even fit into the available memory. For this reason, only for remote backend execution on pasaqal-cloud, and when defining a state/operator :
Info
state
inFidelity(state, ...)
, besides being a proper state for the backend, must also be defined with itsfrom_state_amplitudes()
class method.operator
inExpectation(operator, ...)
, besides being a proper operator for the backend, must also be defined with itsfrom_operator_repr()
class method.
The methods above requires the user to locally install a backend to instantiate a state or an operator class.
It might not be desirable in all cases since, for example, pulser-simulation
will install qutip
, while emu-mps/sv
will install torch
.
To avoid such dependency, the classes StateRepr
, OperatorRepr
just implements the abstract representation of such objects.
Tip
If the full backend is not needed, state/operator in the observable can just be defined with their abstract representation
StateRepr.from_state_amplitudes()
OperatorRepr.from_operator_repr()
Moreover, the observable
Failure
StateResult
is not supported in pasaqal-cloud remote backend emulators.