Skip to content

Spec

ArchSpec

ArchSpec(inner: ArchSpec)

Bases: RustWrapper[ArchSpec]


              flowchart TD
              bloqade.lanes.arch.spec.ArchSpec[ArchSpec]
              bloqade.lanes.bytecode._wrapper.RustWrapper[RustWrapper]

                              bloqade.lanes.bytecode._wrapper.RustWrapper --> bloqade.lanes.arch.spec.ArchSpec
                


              click bloqade.lanes.arch.spec.ArchSpec href "" "bloqade.lanes.arch.spec.ArchSpec"
              click bloqade.lanes.bytecode._wrapper.RustWrapper href "" "bloqade.lanes.bytecode._wrapper.RustWrapper"
            

Architecture specification for a quantum device.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
37
38
39
def __init__(self, inner: _RustArchSpec):
    self._inner = inner
    self._inner.validate()

atom_reloading property

atom_reloading: bool

Whether the device supports reloading atoms after initial fill.

blockade_radius property

blockade_radius: float | None

Rydberg blockade radius (µm), or None if not provided.

This is metadata — when present, it indicates the radius associated with the architecture and is typically used to interpret the entangling pairs. It is not independently verified at the ArchSpec level; use :meth:ZoneBuilder.set_blockade_radius / :meth:ArchBuilder.set_blockade_radius if you want the pair list to be derived from and checked against a radius.

cz_zone_addresses cached property

cz_zone_addresses: frozenset[ZoneAddress]

Zones that host CZ entangling operations (have entangling_pairs).

feed_forward property

feed_forward: bool

Whether the device supports mid-circuit measurement with classical feedback.

home_sites cached property

home_sites: frozenset[LocationAddress]

All home (non-CZ-staging) LocationAddresses, across every zone.

A home site is (zone_id, word_id, site_id) where word_id is not the staging word of one of zone zone_id's entangling pairs. The word template is spec-wide, so every zone contributes. Delegates to Rust ArchSpec.home_locations().

max_qubits property

max_qubits: int

Get the maximum number of qubits supported by this architecture.

paths cached property

paths: MappingProxyType[
    LaneAddress, tuple[tuple[float, float], ...]
]

Transport path waypoints keyed by LaneAddress.

Derived from the Rust ArchSpec.paths on first access.

site_buses cached property

site_buses: tuple[SiteBus, ...]

Aggregate all site buses across all zones.

Note: indices in this flat list do NOT correspond to per-zone bus_id values in LaneAddress. Prefer iterating zones directly via self.zones[i].site_buses.

sites_per_word property

sites_per_word: int

Get the number of sites per word.

word_buses cached property

word_buses: tuple[WordBus, ...]

Aggregate all word buses across all zones.

Note: indices in this flat list do NOT correspond to per-zone bus_id values in LaneAddress. Prefer iterating zones directly via self.zones[i].word_buses.

word_zone_map cached property

word_zone_map: dict[int, int]

Map each word_id to a preferred zone_id.

Not ownership: every word exists in every zone. Delegates to Rust ArchSpec.word_zone_map().

words cached property

words: tuple[Word, ...]

Python Word wrappers, derived from the Rust ArchSpec.

check_lane_group

check_lane_group(
    lanes: Sequence[LaneAddress],
) -> Sequence[LaneGroupError]

Validate a group of lane addresses via Rust.

Checks individual lane validity, group consistency (direction, bus_id, move_type), bus membership, and AOD geometry constraints. Returns a list of LaneGroupError exceptions (empty if all valid).

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
375
376
377
378
379
380
381
382
383
384
385
def check_lane_group(
    self, lanes: Sequence[LaneAddress]
) -> Sequence[LaneGroupError]:
    """Validate a group of lane addresses via Rust.

    Checks individual lane validity, group consistency (direction, bus_id,
    move_type), bus membership, and AOD geometry constraints.
    Returns a list of LaneGroupError exceptions (empty if all valid).
    """
    rust_addrs = [lane._inner for lane in lanes]
    return self._inner.check_lanes(rust_addrs)

check_location_group

check_location_group(
    locations: Sequence[LocationAddress],
) -> Sequence[LocationGroupError]

Validate a group of location addresses via Rust.

Returns a list of LocationGroupError exceptions (empty if all valid).

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
365
366
367
368
369
370
371
372
373
def check_location_group(
    self, locations: Sequence[LocationAddress]
) -> Sequence[LocationGroupError]:
    """Validate a group of location addresses via Rust.

    Returns a list of LocationGroupError exceptions (empty if all valid).
    """
    rust_addrs = [loc._inner for loc in locations]
    return self._inner.check_locations(rust_addrs)

from_components classmethod

from_components(
    words: tuple[Word, ...],
    zones: tuple[Zone, ...],
    modes: Sequence[Mode],
    zone_buses: Sequence[ZoneBus] = (),
    paths: (
        dict[LaneAddress, tuple[tuple[float, float], ...]]
        | None
    ) = None,
    feed_forward: bool = False,
    atom_reloading: bool = False,
    blockade_radius: float | None = None,
) -> ArchSpec

Construct an ArchSpec from Python component types.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
@classmethod
def from_components(
    cls,
    words: tuple[Word, ...],
    zones: tuple[_RustZone, ...],
    modes: Sequence[_RustMode],
    zone_buses: Sequence[ZoneBus] = (),
    paths: dict[LaneAddress, tuple[tuple[float, float], ...]] | None = None,
    feed_forward: bool = False,
    atom_reloading: bool = False,
    blockade_radius: float | None = None,
) -> ArchSpec:
    """Construct an ArchSpec from Python component types."""

    rust_paths = None
    if paths:
        rust_paths = [
            _RustTransportPath(
                lane=_RustLaneAddress(
                    lane.move_type,
                    lane.zone_id,
                    lane.word_id,
                    lane.site_id,
                    lane.bus_id,
                    lane.direction,
                ),
                waypoints=list(waypoints),
            )
            for lane, waypoints in paths.items()
        ]

    inner = _RustArchSpec(
        version=(2, 0),
        words=[w._inner for w in words],
        zones=list(zones),
        zone_buses=list(zone_buses),
        modes=list(modes),
        paths=rust_paths,
        feed_forward=feed_forward,
        atom_reloading=atom_reloading,
        blockade_radius=blockade_radius,
    )
    return cls(inner)

get_cz_partner

get_cz_partner(
    location: LocationAddress,
) -> LocationAddress | None

Get the CZ partner for a given location.

Uses Rust-side get_cz_partner which resolves via the zone's entangling_pairs.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
427
428
429
430
431
432
433
434
435
436
def get_cz_partner(self, location: LocationAddress) -> LocationAddress | None:
    """Get the CZ partner for a given location.

    Uses Rust-side get_cz_partner which resolves via the zone's
    entangling_pairs.
    """
    result = self._inner.get_cz_partner(location._inner)
    if result is None:
        return None
    return LocationAddress.from_inner(result)

get_lane_address

get_lane_address(
    src: LocationAddress, dst: LocationAddress
) -> LaneAddress | None

Given an input tuple of locations, gets the lane (w/direction).

Delegates to Rust ArchSpec.lane_for_endpoints().

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
387
388
389
390
391
392
393
394
395
396
397
def get_lane_address(
    self, src: LocationAddress, dst: LocationAddress
) -> LaneAddress | None:
    """Given an input tuple of locations, gets the lane (w/direction).

    Delegates to Rust ``ArchSpec.lane_for_endpoints()``.
    """
    result = self._inner.lane_for_endpoints(src._inner, dst._inner)
    if result is None:
        return None
    return LaneAddress.from_inner(result)

get_zone_index

get_zone_index(
    loc_addr: LocationAddress, zone_id: ZoneAddress
) -> int | None

O(1) flat index of a location within a zone.

Delegates to Rust ArchSpec.zone_location_index().

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
331
332
333
334
335
336
337
338
339
340
def get_zone_index(
    self,
    loc_addr: LocationAddress,
    zone_id: ZoneAddress,
) -> int | None:
    """O(1) flat index of a location within a zone.

    Delegates to Rust ``ArchSpec.zone_location_index()``.
    """
    return self._inner.zone_location_index(loc_addr._inner, zone_id.zone_id)

is_home_position

is_home_position(addr: LocationAddress) -> bool

True if this address is not a CZ-staging position in its own zone.

Delegates to Rust ArchSpec.is_home_position().

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
137
138
139
140
141
142
def is_home_position(self, addr: LocationAddress) -> bool:
    """True if this address is not a CZ-staging position in its own zone.

    Delegates to Rust ``ArchSpec.is_home_position()``.
    """
    return self._inner.is_home_position(addr._inner)

iter_all_lanes

iter_all_lanes() -> Iterator[LaneAddress]

Yield every valid lane address in the architecture.

Enumerates site-bus, word-bus, and zone-bus lanes in both forward and backward directions. Used by :class:~bloqade.lanes.arch.metrics.MoveMetricCalculator to compute max-duration bounds. Prefer get_lane_address(src, dst) for single-pair lookups.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
def iter_all_lanes(self) -> Iterator[LaneAddress]:
    """Yield every valid lane address in the architecture.

    Enumerates site-bus, word-bus, and zone-bus lanes in both forward
    and backward directions. Used by
    :class:`~bloqade.lanes.arch.metrics.MoveMetricCalculator` to compute
    max-duration bounds. Prefer ``get_lane_address(src, dst)`` for
    single-pair lookups.
    """
    sites_per_word = self.sites_per_word

    # Intra-zone: site buses and word buses.
    for zone_id, zone in enumerate(self._inner.zones):
        for bus_id, bus in enumerate(zone.site_buses):
            for word_id in zone.words_with_site_buses:
                for i in range(len(bus.src)):
                    for direction in (Direction.FORWARD, Direction.BACKWARD):
                        yield LaneAddress(
                            MoveType.SITE,
                            word_id,
                            bus.src[i],
                            bus_id,
                            direction,
                            zone_id,
                        )
        for bus_id, bus in enumerate(zone.word_buses):
            for site_id in zone.sites_with_word_buses:
                for word_id in bus.src:
                    for direction in (Direction.FORWARD, Direction.BACKWARD):
                        yield LaneAddress(
                            MoveType.WORD,
                            word_id,
                            site_id,
                            bus_id,
                            direction,
                            zone_id,
                        )

    # Inter-zone: zone buses.
    for bus_id, zb in enumerate(self._inner.zone_buses):
        for (src_zone, src_word), (_dst_zone, _dst_word) in zip(zb.src, zb.dst):
            for site_id in range(sites_per_word):
                for direction in (Direction.FORWARD, Direction.BACKWARD):
                    yield LaneAddress(
                        MoveType.ZONE,
                        src_word,
                        site_id,
                        bus_id,
                        direction,
                        src_zone,
                    )

location_at

location_at(
    zone: int, row: int, col: int
) -> LocationAddress | None

Resolve a (zone, row, col) grid coordinate to a LocationAddress.

col is the grid x-index and row the grid y-index within zone. Returns the location whose word site sits at that grid position (a unique (word_id, site_id) within the zone), or None if no atom occupies it. This is the authoritative (row, col) -> location mapping for the architecture's addressing scheme (defined Rust-side); callers depend only on this, not on the word/site layout.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
438
439
440
441
442
443
444
445
446
447
448
449
450
451
def location_at(self, zone: int, row: int, col: int) -> LocationAddress | None:
    """Resolve a ``(zone, row, col)`` grid coordinate to a ``LocationAddress``.

    ``col`` is the grid x-index and ``row`` the grid y-index within ``zone``.
    Returns the location whose word site sits at that grid position (a
    unique ``(word_id, site_id)`` within the zone), or ``None`` if no atom
    occupies it. This is the authoritative ``(row, col)`` -> location
    mapping for the architecture's addressing scheme (defined Rust-side);
    callers depend only on this, not on the word/site layout.
    """
    result = self._inner.location_at(zone, row, col)
    if result is None:
        return None
    return LocationAddress.from_inner(result)

to_json

to_json() -> str

Serialize this architecture spec to a JSON string.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
275
276
277
def to_json(self) -> str:
    """Serialize this architecture spec to a JSON string."""
    return self._inner.to_json()

try_get_endpoints

try_get_endpoints(
    lane_address: LaneAddress,
) -> tuple[LocationAddress, LocationAddress] | None

Resolve lane_address to its (src, dst) location pair, or None when the lane is not a valid lane in the architecture (matches the Rust lane_endpoints contract).

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
def try_get_endpoints(
    self, lane_address: LaneAddress
) -> tuple[LocationAddress, LocationAddress] | None:
    """Resolve ``lane_address`` to its (src, dst) location pair, or
    ``None`` when the lane is not a valid lane in the architecture
    (matches the Rust ``lane_endpoints`` contract).
    """
    result = self._inner.lane_endpoints(lane_address._inner)
    if result is None:
        return None
    rust_src, rust_dst = result
    return (
        LocationAddress.from_inner(rust_src),
        LocationAddress.from_inner(rust_dst),
    )

try_get_position

try_get_position(
    location: LocationAddress,
) -> tuple[float, float] | None

Resolve location to its physical (x, y) position, or None when location doesn't correspond to a valid site under the zone its zone_id selects (matches the Rust location_position contract).

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
357
358
359
360
361
362
363
def try_get_position(self, location: LocationAddress) -> tuple[float, float] | None:
    """Resolve ``location`` to its physical (x, y) position, or
    ``None`` when ``location`` doesn't correspond to a valid site
    under the zone its ``zone_id`` selects (matches the Rust
    ``location_position`` contract).
    """
    return self._inner.location_position(location._inner)

yield_zone_locations

yield_zone_locations(
    zone_address: ZoneAddress,
) -> Iterator[LocationAddress]

Yield LocationAddresses in the canonical zone-bitstring iteration order.

This is the layout that get_zone_index(loc, zone_address) numbers: every (word, site) pair in the architecture, tagged with zone_address, walked in word-major then site-major order. The iterator visits every word — zone_address is the tag stamped onto each yielded address (and the grid through which downstream calls like get_position interpret it), not a membership filter.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/spec.py
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
def yield_zone_locations(
    self, zone_address: ZoneAddress
) -> Iterator[LocationAddress]:
    """Yield ``LocationAddress``es in the canonical zone-bitstring iteration order.

    This is the layout that ``get_zone_index(loc, zone_address)``
    numbers: every ``(word, site)`` pair in the architecture, tagged
    with ``zone_address``, walked in word-major then site-major order.
    The iterator visits every word — ``zone_address`` is the tag
    stamped onto each yielded address (and the grid through which
    downstream calls like ``get_position`` interpret it), not a
    membership filter.
    """
    zone_id = zone_address.zone_id
    for word_id in range(len(self.words)):
        word = self.words[word_id]
        for site_id in range(len(word.site_indices)):
            yield LocationAddress(word_id, site_id, zone_id)