quimb.tensor.circuit.peps

PEPS simple-update circuit simulator.

Classes

CircuitPEPSSimpleUpdate

Quantum circuit simulation keeping the state as a generic tensor

Module Contents

class quimb.tensor.circuit.peps.CircuitPEPSSimpleUpdate(N=None, *, edges=None, gates=None, psi0=None, max_bond=None, cutoff=1e-10, renorm=False, gauge_smudge=1e-12, equilibrate_every=None, equilibrate_opts=None, gate_opts=None, dtype=None, to_backend=None, convert_eager=True, **circuit_opts)[source]

Bases: quimb.tensor.circuit.simple_update.CircuitSimpleUpdate

Quantum circuit simulation keeping the state as a generic tensor network (a “PEPS” defined by an arbitrary graph of edges) and applying gates with the simple update rule. The state always keeps a single tensor per site, with bonds only along the supplied edges; two-qubit gates are only supported on those edges. Bond singular values are tracked as Vidal-style gauges, which makes gate application and the computation of local expectations cheap and approximate.

This is useful for circuits on lattices that build up more than 1D worth of entanglement, where an exact or MPS simulation is intractable but a truncated, gauged tensor network state is a good approximation.

Parameters:
  • N (int, optional) – The number of qubits in the circuit. If not given it is inferred from the geometry. Supply it to pad the geometry up to N sites, including any that have no edges.

  • edges (sequence[tuple[int, int]], optional) – The edges defining the geometry of the PEPS. A bond is placed between each pair of sites, and two-qubit gates are only supported on these edges. Every site appearing in edges is included. If not given the geometry is taken from gates or psi0 instead.

  • gates (sequence, optional) – If edges is not given, infer the geometry from the two-qubit gates in this sequence. The gates are only inspected here, not applied, so you still pass them to apply_gates() afterwards.

  • psi0 (TensorNetworkGenVector, optional) – Supply the initial state directly instead of starting from the |00...0> product state. If edges is not given the geometry is read from the bonds of this state, and the bond gauges are seeded from it. Only a single seeding sweep is performed; unlike imaginary time simple update the gauge matters immediately, so for an arbitrary psi0 you may want to call equilibrate() once before applying gates.

  • max_bond (int, optional) – The maximum bond dimension to truncate to when applying gates.

  • cutoff (float, optional) – The singular value cutoff to use when truncating after applying gates.

  • renorm (bool, optional) – Whether to renormalize the singular values of a bond after each gate. The default False tracks the norm of the state rather than forcing it to one, which is the sensible choice for real time and general circuit dynamics. Set True to instead keep the state normalized after every gate, e.g. for the near-identity gates of imaginary time evolution.

  • gauge_smudge (float, optional) – Small value added to the gauges before they are multiplied in and inverted, for numerical stability with very small singular values.

  • equilibrate_every (int, optional) – If given, automatically call equilibrate() after every this many gates have been applied.

  • equilibrate_opts (dict, optional) – Default options forwarded to equilibrate().

  • gate_opts (dict, optional) – Default options to pass to gate_simple_ such as max_bond and cutoff.

  • dtype (str, optional) – If given, ensure the state tensors are cast to this data type.

  • to_backend (callable, optional) – If given, apply this function to the state tensors to convert them to a particular array backend.

  • convert_eager (bool, optional) – Whether to apply the dtype and to_backend conversions eagerly as each gate is applied. The default True matches the other running simulators (e.g. CircuitMPS), since the simple update rule contracts each gate into the state immediately rather than building a lazy network to contract later.

edges

The unique edges defining the PEPS geometry.

Type:

tuple[tuple[hashable, hashable]]

sites

The sites (qubit labels) of the PEPS.

Type:

tuple[hashable]

gauges

The current Vidal-style bond gauges (singular values), keyed by bond index, updated in place as gates are applied.

Type:

dict[str, array]

Notes

The gates applied must address qubits using the same labels that appear in edges. Two-qubit gates are only supported along an existing edge.

Examples

>>> import quimb.tensor as qtn
>>> edges = [(0, 1), (1, 2), (0, 3), (1, 4), (2, 5), (3, 4), (4, 5)]
>>> circ = qtn.CircuitPEPSSimpleUpdate(edges=edges, max_bond=8)
>>> circ.apply_gates(gates)
>>> peps = circ.psi

See also

CircuitMPS, CircuitDense

gauges
_equilibrate_every = None
_equilibrate_opts
copy()[source]

Copy the circuit, including its state, gauges and geometry. The base CircuitSimpleUpdate copy carries the geometry; the gauges and equilibrate options are copied here so the two circuits can be evolved independently.

_init_state(N, dtype='complex128')[source]
_apply_gate(gate, tags=None, **gate_opts)[source]

Apply a Gate to this Circuit. This is the main method that all calls to apply a gate should go through.

Parameters:
  • gate (Gate) – The gate to apply.

  • tags (str or sequence of str, optional) – Tags to add to the gate tensor(s).

apply_gates(gates, progbar=False, **gate_opts)[source]

Apply a sequence of gates to this tensor network quantum circuit.

Parameters:
  • gates (Sequence[Gate] or Sequence[Tuple]) – The sequence of gates to apply.

  • gate_opts – Supplied to apply_gate().

equilibrate(**gauge_opts)[source]

Re-gauge the whole state with the simple update rule, improving the consistency of the tracked bond gauges. This does not change the state represented, only the gauge, and can be called periodically between rounds of gates to keep the simple update approximation well behaved.

The default options given at construction via equilibrate_opts are applied first, with any keyword arguments here taking precedence.

Parameters:

gauge_opts – Supplied to gauge_all_simple_(), for example max_iterations and tol.

local_expectation(G, where, *, max_distance=0, normalized=True, **contract_opts)[source]

Compute the local expectation value of operator G at the site(s) where, using the simple update bond gauges to approximate the environment beyond max_distance.

Parameters:
  • G (array_like) – The local operator.

  • where (hashable or sequence[hashable]) – The site or sites to compute the expectation at. A single site label (which may itself be a tuple, e.g. a 2D coordinate) is detected by membership in the set of sites.

  • max_distance (int, optional) – How many graph hops of neighboring tensors to include in the local cluster used to approximate the reduced density matrix. The default 0 uses only the target site(s) and their gauges, matching compute_local_expectation_cluster().

  • normalized (bool, optional) – Whether to normalize by the local norm.

  • contract_opts – Supplied to compute_local_expectation_cluster().

Return type:

float

get_state(absorb_gauges=True)[source]

Return the current PEPS state, optionally absorbing the bond gauges.

Parameters:

absorb_gauges (bool or "return", optional) – How to handle the tracked Vidal-style bond gauges. If True (the default) the gauges are absorbed, so the returned tensor network is the actual wavefunction (up to the simple update approximation). If False the gauges are added to the network as uncontracted diagonal tensors. If "return" the raw gauged network and a copy of the gauges are returned separately. The internal state is left untouched in every case.

Returns:

  • psi (TensorNetwork) – The current state.

  • gauges (dict) – The current gauges, only if absorb_gauges == "return".

get_psi()[source]

Get the PEPS tensor network state, with the simple update bond gauges absorbed back in so that it represents the actual wavefunction (a proper contraction of it gives the state, up to the simple update approximation). The internal gauged form is left untouched. Shorthand for get_state(absorb_gauges=True).

to_dense(*args, **kwargs)[source]

Contract the gauged PEPS into a dense wavefunction, a column-vector qarray of length 2**N ordered like sites, matching the output of Circuit.to_dense(). This is the actual (approximate) state, so the cost grows exponentially with the number of qubits.

Arguments are forwarded to to_dense().

abstractmethod _unsupported(name)[source]