tensorcircuit.shadows¶
Classical shadows functions
- tensorcircuit.shadows.entropy_shadow(snapshots: Any, pauli_strings: Any | None = None, sub: Sequence[int] | None = None, alpha: int = 2, *, subsystem_to_keep: Sequence[int] | None = None, subsystems_to_trace_out: Sequence[int] | None = None) Any[source]¶
To calculate the Renyi entropy of a subsystem from shadow state or shadow snapshot states
The subsystem can be specified by
sub(legacy, the qubits to keep) or by exactly one ofsubsystem_to_keep/subsystems_to_trace_out. If bothsuband a new argument are given, the new argument wins andsubis ignored (with aUserWarning). If none is given, the entropy of the full system is computed.Warning
Unlike
tensorcircuit.quantum.reduced_density_matrix(), the legacysubargument here names the qubits to keep, not to trace out. Prefer the explicitsubsystem_to_keep/subsystems_to_trace_outto avoid ambiguity.- Parameters:
snapshots – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
pauli_strings – shape = None or (ns, nq) or (ns, repeat, nq)
sub – qubit indices of subsystem (kept).
alpha – order of the Renyi entropy, alpha=1 corresponds to the von Neumann entropy
subsystem_to_keep (Optional[Sequence[int]]) – qubit indices to keep (entropy of this subsystem). Mutually exclusive with
subsystems_to_trace_out.subsystems_to_trace_out (Optional[Sequence[int]]) – qubit indices to trace out (complement is kept).
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Type:
int
- Return Renyi entropy:
shape = ()
- Return type:
Tensor
- tensorcircuit.shadows.expectation_ps_shadow(snapshots: Any, pauli_strings: Any | None = None, x: Sequence[int] | None = None, y: Sequence[int] | None = None, z: Sequence[int] | None = None, ps: Sequence[int] | None = None, k: int = 1) List[Any][source]¶
To calculate the expectation value of an observable on shadow snapshot states
- Parameters:
snapshots – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
pauli_strings – shape = None or (ns, nq) or (ns, repeat, nq)
x – sites to apply X gate, defaults to None
y – sites to apply Y gate, defaults to None
z – sites to apply Z gate, defaults to None
ps – or one can apply a ps structures instead of x, y, z, e.g. [1, 1, 0, 2, 3, 0] for X_0X_1Y_3Z_4 defaults to None, ps can overwrite x, y and z
k – Number of equal parts to split the shadow snapshot states to compute the median of means. k=1 (default) corresponds to simply taking the mean over all shadow snapshot states.
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Type:
Optional[Sequence[int]]
- Type:
Optional[Sequence[int]]
- Type:
Optional[Sequence[int]]
- Type:
int
- Return expectation values:
shape = (k,)
- Return type:
List[Tensor]
- tensorcircuit.shadows.global_shadow_state(snapshots: Any, pauli_strings: Any | None = None, sub: Sequence[int] | None = None) Any[source]¶
To generate the global shadow state from local snapshot states or snapshots and pauli strings. This is the recommended implementation as it typically offers the best performance
- Parameters:
snapshots – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
pauli_strings – shape = None or (ns, nq) or (ns, repeat, nq)
sub – qubit indices of subsystem
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Return gsdw_state:
shape = (2 ** nq, 2 ** nq)
- Return type:
Tensor
- tensorcircuit.shadows.global_shadow_state1(snapshots: Any, pauli_strings: Any | None = None, sub: Sequence[int] | None = None) Any[source]¶
To generate the global snapshots states from local snapshot states or snapshots and pauli strings. Note: This version uses a single pure einsum which may be slower during compilation and execution for larger qubit counts compared to global_shadow_state.
- Parameters:
snapshots – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
pauli_strings – shape = None or (ns, nq) or (ns, repeat, nq)
sub – qubit indices of subsystem
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Return gsdw_state:
shape = (2 ** nq, 2 ** nq)
- Return type:
Tensor
- tensorcircuit.shadows.global_shadow_state2(snapshots: Any, pauli_strings: Any | None = None, sub: Sequence[int] | None = None) Any[source]¶
To generate the global snapshots states from local snapshot states or snapshots and pauli strings. Note: This version uses vmap over einsum which may be slower during compilation and execution for larger qubit counts compared to global_shadow_state.
Warning
Not compatible with the tensorflow backend: the inner vmap unpacks the per-qubit axis (
*dms), which is forbidden inside tensorflow’s graph mode. Use global_shadow_state instead on tensorflow.- Parameters:
snapshots – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
pauli_strings – shape = None or (ns, nq) or (ns, repeat, nq)
sub – qubit indices of subsystem
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Return gsdw_state:
shape = (2 ** nq, 2 ** nq)
- Return type:
Tensor
- tensorcircuit.shadows.local_snapshot_states(snapshots: Any, pauli_strings: Any, sub: Sequence[int] | None = None) Any[source]¶
To generate the local snapshots states from snapshots and pauli strings
- Parameters:
snapshots – shape = (ns, repeat, nq)
pauli_strings – shape = (ns, nq) or (ns, repeat, nq)
sub – qubit indices of subsystem
- Type:
Tensor
- Type:
Tensor
- Type:
Optional[Sequence[int]]
- Return lss_states:
shape = (ns, repeat, nq, 2, 2)
- Return type:
Tensor
- tensorcircuit.shadows.renyi_entropy_2(snapshots: Any, sub: Sequence[int] | None = None, *, subsystem_to_keep: Sequence[int] | None = None, subsystems_to_trace_out: Sequence[int] | None = None) Any[source]¶
To calculate the second order Renyi entropy of a subsystem from snapshot, please refer to Brydges, T. et al. Science 364, 260-263 (2019). This function is not jitable.
The subsystem can be specified by
sub(legacy, the qubits to keep) or by exactly one ofsubsystem_to_keep/subsystems_to_trace_out. If bothsuband a new argument are given, the new argument wins andsubis ignored (with aUserWarning). If none is given, the entropy of the full system is computed.Warning
Unlike
tensorcircuit.quantum.reduced_density_matrix(), the legacysubargument here names the qubits to keep, not to trace out. Prefer the explicitsubsystem_to_keep/subsystems_to_trace_outto avoid ambiguity.- Parameters:
snapshots – shape = (ns, repeat, nq)
sub – qubit indices of subsystem (kept).
subsystem_to_keep (Optional[Sequence[int]]) – qubit indices to keep (entropy of this subsystem). Mutually exclusive with
subsystems_to_trace_out.subsystems_to_trace_out (Optional[Sequence[int]]) – qubit indices to trace out (complement is kept).
- Type:
Tensor
- Type:
Optional[Sequence[int]]
- Return second order Renyi entropy:
shape = ()
- Return type:
Tensor
Note
The estimator
tr = sum pp[x,y] * (-2)**(-h)is a signed sum that only converges to a positiveTr(rho**2)with sufficient snapshots. Whenns/repeatis too small (or the subsystem is near-maximally mixed, so the true value is ~= 0), finite-sample noise can drivetrto zero or negative, and this function returnsNaN/+inf. This is the correct “estimate failed” signal — increasens/repeatrather than interpreting such a return as a finite entropy.
- tensorcircuit.shadows.shadow_bound(observables: Any | Sequence[int], epsilon: float, delta: float = 0.01) Tuple[int, int][source]¶
Calculate the shadow bound of the Pauli observables, please refer to the Theorem S1 and Lemma S3 in Huang, H.-Y., R. Kueng, and J. Preskill, 2020, Nat. Phys. 16, 1050.
- Parameters:
observables – shape = (nq,) or (M, nq), where nq is the number of qubits, M is the number of observables
epsilon – error on the estimator
delta – rate of failure for the bound to hold
- Type:
Union[Tensor, Sequence[int]]
- Type:
float
- Type:
float
- Return Nk:
number of snapshots
- Return type:
int
- Return k:
number of equal parts to split the shadow snapshot states to compute the median of means. k=1 (default) corresponds to simply taking the mean over all shadow snapshot states.
- Return type:
int
- tensorcircuit.shadows.shadow_snapshots(psi: Any, pauli_strings: Any, status: Any | None = None, sub: Sequence[int] | None = None, measurement_only: bool = False) Any[source]¶
To generate the shadow snapshots from given pauli string observables on psi
- Parameters:
psi – shape = (2 ** nq,), where nq is the number of qubits
pauli_strings – shape = (ns, nq), where ns is the number of pauli strings
status – shape = None or (ns, repeat), where repeat is the times to measure on one pauli string
sub – qubit indices of subsystem
measurement_only – return snapshots (True) or snapshot states (False), default=False
- Type:
Tensor
- Type:
Tensor
- Type:
Optional[Tensor]
- Type:
Optional[Sequence[int]]
- Type:
bool
- Return snapshots:
shape = (ns, repeat, nq) if measurement_only=True otherwise (ns, repeat, nq, 2, 2)
- Return type:
Tensor
- tensorcircuit.shadows.slice_sub(entirety: Any, sub: Sequence[int]) Any[source]¶
To slice off the subsystem
- Parameters:
entirety – shape = (ns, repeat, nq, 2, 2) or (ns, repeat, nq)
sub – qubit indices of subsystem
- Type:
Tensor
- Type:
Sequence[int]
- Return subsystem:
shape = (ns, repeat, nq_sub, 2, 2)
- Return type:
Tensor