Geometry
Site-selection vocabulary — broadcast ("distribution") vs. set ("region") geometries; see Design Philosophy for the conceptual split.
All geometries address sites on a one-dimensional chain (1:L). Higher-dimensional (2D+) circuit geometries are a planned future direction — see the project ROADMAP.
QuantumCircuitsMPS.AbstractGeometry — Type
AbstractGeometryAbstract base type for all geometry specifications — the "where" of a gate application (apply!(state, gate, geometry)).
Geometries fall into two families, reported by the is_broadcast(geo) trait:
- Broadcast ("distribution") geometries expand to
K ≥ 1independent elements, each receiving its own gate application (and, insideapply_with_prob!, its own coin):AllSites,Bricklayer,EachSite. - Set ("region") geometries denote ONE region of sites, a single element:
SingleSite,AdjacentPair,Sites,StaircaseLeft/StaircaseRight,Pointer.
The canonical enumeration for either family is elements(geo, L, bc) -> Vector{Vector{Int}} (physical site indices). Dynamic geometries (staircases, Pointer) are MUTABLE — staircases advance after each application, Pointer moves only via move!.
Geometries always speak PHYSICAL site indices; backends translate to their internal (RAM) indexing via state.phy_ram.
QuantumCircuitsMPS.SingleSite — Type
SingleSite(site::Int)Geometry specifying a single physical site. Used for single-qubit gates like PauliX, Projection.
QuantumCircuitsMPS.AdjacentPair — Type
AdjacentPair(first::Int)Geometry specifying an adjacent pair of physical sites: (first, first+1). For PBC, wraps: (L, 1) when first=L.
QuantumCircuitsMPS.Sites — Type
Sites(sites)Set geometry: ONE region made of the given sites (a range or collection of Ints, kept in the given order). A gate applied to Sites(c) must have support(gate) == length(c) (see validate_support).
Expands to a single element [collect(sites)]. For applying a gate independently at each site, use EachSite instead.
QuantumCircuitsMPS.AllSites — Type
AllSitesGeometry for applying single-site gates to all sites. apply! loops internally over all L sites.
QuantumCircuitsMPS.EachSite — Type
EachSite(sites)Broadcast geometry: apply a single-site gate independently at each site in sites (a range or collection of Ints, kept in the given order).
Expands to [[i] for i in sites] — one element per site. Example: SRN bulk eligibility is EachSite(2:L-1).
See also AllSites (all L sites) and Sites (one multi-site region, NOT a broadcast).
QuantumCircuitsMPS.Bricklayer — Type
Bricklayer(parity::Symbol)Geometry for bricklayer gate application pattern.
Nearest-neighbor (NN) modes:
:oddparity → pairs (1,2), (3,4), (5,6), ...:evenparity → pairs (2,3), (4,5), ... plus (L,1) for PBC:nnparity → ALL NN pairs (combines :odd + :even)
Next-nearest-neighbor (NNN) modes (4 sublayers covering all 12 NNN pairs for L=12):
:nnn_odd_1parity → pairs (1,3), (5,7), (9,11), ... (stride 4, offset 1):nnn_odd_2parity → pairs (3,5), (7,9), (11,1), ... (stride 4, offset 3, PBC wrap):nnn_even_1parity → pairs (2,4), (6,8), (10,12), ... (stride 4, offset 2):nnn_even_2parity → pairs (4,6), (8,10), (12,2), ... (stride 4, offset 4, PBC wrap):nnnparity → ALL NNN pairs (combines all 4 sublayers)
apply! loops internally over all pairs.
An odd-length ring cannot be tiled by disjoint NN pairs. At odd L with bc = :periodic, no wrap pair is added to either single layer: :odd leaves site L unpaired and :even leaves site 1 unpaired, and the wrap bond (L, 1) is gated by NEITHER layer — an alternating :odd/:even brickwork circuit is effectively open across that bond. A one-time warning is emitted at circuit-build / apply! time (internal helper _warn_bricklayer_odd_pbc); double-check the intended pattern with print_circuit. :nn (ALL NN bonds, not a single layer) still enumerates all L ring bonds and does not warn.
QuantumCircuitsMPS.StaircaseLeft — Type
StaircaseLeft(start_position::Int; range::Int=1)Staircase that moves left: applies at (pos, pos+range), then decrements pos.
Arguments
start_position: Initial positionrange: Distance between sites (default 1 for nearest neighbors)
Examples
StaircaseLeft(1) # NN: (1,2), (2,3), ...
StaircaseLeft(1; range=2) # NNN: (1,3), (2,4), ...QuantumCircuitsMPS.StaircaseRight — Type
StaircaseRight(start_position::Int; range::Int=1)Staircase that moves right: applies at (pos, pos+range), then advances pos.
Arguments
start_position: Initial positionrange: Distance between sites (default 1 for nearest neighbors)
Examples
StaircaseRight(1) # NN: (1,2), (2,3), ...
StaircaseRight(1; range=2) # NNN: (1,3), (2,4), ...QuantumCircuitsMPS.Pointer — Type
Pointer(start_position::Int)A bidirectional pointer that can move left or right. Unlike StaircaseLeft/StaircaseRight which are unidirectional, Pointer supports explicit direction control via move!().
For two-qubit gates, the pair is (position, position+1) with PBC wrap.
QuantumCircuitsMPS.move! — Function
move!(p::Pointer, direction::Symbol, L::Int, bc::Symbol=:periodic)Move the pointer in the specified direction.
- direction = :left → position decreases (wraps L → 1 for PBC)
- direction = :right → position increases (wraps 1 → L for PBC)
This is the PUBLIC API for pointer movement, unlike advance!() which is internal.
QuantumCircuitsMPS.elements — Function
elements(geo::AbstractGeometry, L::Int, bc::Symbol) -> Vector{Vector{Int}}Canonical element enumeration for a geometry: each inner vector is the sites for one gate application. This is the SINGLE source of truth consolidating the former get_pairs / get_compound_elements duplicates.
Broadcast geometries return K ≥ 1 elements in their documented canonical order (API contract — RNG coin consumption follows this order):
AllSites()→[[1], [2], ..., [L]]EachSite(c)→[[i] for i in c](collection order)Bricklayer(parity)→ pairs exactly as documented in the README parity table (e.g.:odd→[[1,2],[3,4],...];:even→[[2,3],...,[L,1]]for PBC at evenL;:nn=:oddthen:evenplus the(L,1)wrap bond;:nnn= sublayers 1,2,3,4). At oddL, single layers (:odd,:even) leave one site unpaired rather than double-touching a site — see the parity branches below. Using:odd/:evenat oddLunder PBC emits a one-time warning at circuit-build /apply!time (helper_warn_bricklayer_odd_pbcinGeometry/static.jl— deliberately NOT called here:elementssits in performance-critical loops).
Set geometries return a single element [[sites...]]:
SingleSite(i)→[[i]]AdjacentPair(i)→[[i, i+1]](PBC wrap at L)Sites(c)→[collect(c)]StaircaseLeft/Right→[[pos, pos+range]]at the CURRENT position (PBC wrap viamod1; OBC out-of-bounds throwsArgumentError)Pointer→[[pos, pos+1]]at the current position (PBC wrap at L)
QuantumCircuitsMPS.element_count — Function
element_count(geo::AbstractGeometry, L::Int, bc::Symbol) -> IntNumber of elements (K) that geo expands to via elements. Broadcast geometries give K ≥ 1; set geometries always give 1. Used by builder validation (equal-K rule across stochastic outcomes).
QuantumCircuitsMPS.is_broadcast — Function
is_broadcast(geo::AbstractGeometry) -> BoolTrait: true for broadcast ("distribution") geometries that expand to multiple independent elements (AllSites, Bricklayer, EachSite); false for set ("region") geometries that denote a single region (SingleSite, AdjacentPair, Sites, StaircaseLeft/StaircaseRight, Pointer).