Skip to content

Imperative

Zone-aware architecture builder.

Provides ZoneBuilder (single-zone construction with validation) and ArchBuilder (multi-zone composition) as the low-level building blocks. The high-level build_arch() function uses these internally.

ArchBuilder

ArchBuilder()

Compose ZoneBuilders into a complete ArchSpec.

Each zone added gets assigned global word IDs. Inter-zone connections go into zone_buses. Calls Rust validation on build().

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
def __init__(self) -> None:
    self._zones: list[ZoneBuilder] = []
    self._zone_name_to_id: dict[str, int] = {}
    self._word_id_offsets: list[int] = []
    self._connections: list[
        tuple[tuple[str, Sequence[int]], tuple[str, Sequence[int]]]
    ] = []
    self._modes: list[tuple[str, list[str]]] = []
    self._total_words: int = 0
    self._blockade_radius: float | None = None

blockade_radius property

blockade_radius: float | None

Rydberg blockade radius (µm) applied to all zones, or None.

add_mode

add_mode(name: str, zones: Sequence[str]) -> None

Add an operational mode.

Parameters:

Name Type Description Default
name str

Mode name (e.g. "all", "gate", "measure").

required
zones Sequence[str]

Zone names to include in this mode.

required
Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
def add_mode(self, name: str, zones: Sequence[str]) -> None:
    """Add an operational mode.

    Args:
        name: Mode name (e.g. "all", "gate", "measure").
        zones: Zone names to include in this mode.
    """
    for z in zones:
        if z not in self._zone_name_to_id:
            raise ValueError(f"Unknown zone: '{z}'")
    self._modes.append((name, list(zones)))

add_zone

add_zone(zone: ZoneBuilder) -> int

Add a zone. Returns zone_id. Assigns global word IDs.

Validates that sites_per_word matches across all zones.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
def add_zone(self, zone: ZoneBuilder) -> int:
    """Add a zone. Returns zone_id. Assigns global word IDs.

    Validates that sites_per_word matches across all zones.
    """
    if zone.name in self._zone_name_to_id:
        raise ValueError(f"Duplicate zone name: '{zone.name}'")
    if self._zones:
        existing_spw = self._zones[0].sites_per_word
        if zone.sites_per_word != existing_spw:
            raise ValueError(
                f"sites_per_word mismatch: zone '{zone.name}' has "
                f"{zone.sites_per_word} but existing zones have "
                f"{existing_spw}"
            )
    zone_id = len(self._zones)
    self._zone_name_to_id[zone.name] = zone_id
    self._word_id_offsets.append(self._total_words)
    self._total_words += zone.num_words
    self._zones.append(zone)
    return zone_id

build

build(
    feed_forward: bool = False,
    atom_reloading: bool = False,
    blockade_radius: float | None = None,
) -> ArchSpec

Assemble the ArchSpec and validate via Rust.

Parameters:

Name Type Description Default
feed_forward bool

Whether the device supports feed-forward.

False
atom_reloading bool

Whether the device supports atom reloading.

False
blockade_radius float | None

Explicit blockade radius (µm). If provided, overrides both builder-level and zone-level radii.

None

Raises:

Type Description
ValueError

If Rust validation fails.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
def build(
    self,
    feed_forward: bool = False,
    atom_reloading: bool = False,
    blockade_radius: float | None = None,
) -> ArchSpec:
    """Assemble the ArchSpec and validate via Rust.

    Args:
        feed_forward: Whether the device supports feed-forward.
        atom_reloading: Whether the device supports atom reloading.
        blockade_radius: Explicit blockade radius (µm). If provided,
            overrides both builder-level and zone-level radii.

    Raises:
        ValueError: If Rust validation fails.
    """
    # 1. Collect all words with global IDs.
    all_words: list[Word] = []
    for zone in self._zones:
        for positions in zone._words:
            all_words.append(Word(tuple(positions)))

    # 2. Build Rust Zone objects.
    # Zone-local word IDs must be translated to global IDs for the Rust
    # ArchSpec, which uses global word indices everywhere.
    rust_zones: list[_RustZone] = []
    for zone_idx, zone in enumerate(self._zones):
        offset = self._word_id_offsets[zone_idx]
        site_buses = [_RustSiteBus(src=s, dst=d) for s, d in zone._site_buses]
        word_buses = [
            _RustWordBus(
                src=[offset + w for w in s],
                dst=[offset + w for w in d],
            )
            for s, d in zone._word_buses
        ]
        # Only words flagged at add_word(has_site_bus=True) are
        # eligible for site-bus transport. Default is True, so the
        # historical "all words opt-in when any site bus exists"
        # behavior is preserved unless the caller overrides.
        words_with_site_buses = (
            [
                offset + w
                for w in range(zone.num_words)
                if zone._word_has_site_bus[w]
            ]
            if site_buses
            else []
        )
        sites_with_word_buses = (
            list(range(zone.sites_per_word)) if word_buses else []
        )
        entangling_pairs = [
            (offset + a, offset + b) for a, b in zone._entangling_pairs
        ]
        rust_zones.append(
            _RustZone(
                name=zone.name,
                grid=zone._grid,
                site_buses=site_buses,
                word_buses=word_buses,
                words_with_site_buses=words_with_site_buses,
                sites_with_word_buses=sites_with_word_buses,
                entangling_pairs=entangling_pairs,
            )
        )

    # 3. Build zone_buses from connect() calls.
    zone_buses: list[_RustZoneBus] = []
    for (src_name, src_words), (dst_name, dst_words) in self._connections:
        src_zid = self._zone_name_to_id[src_name]
        dst_zid = self._zone_name_to_id[dst_name]
        src_offset = self._word_id_offsets[src_zid]
        dst_offset = self._word_id_offsets[dst_zid]
        zone_buses.append(
            _RustZoneBus(
                src=[(src_zid, src_offset + w) for w in src_words],
                dst=[(dst_zid, dst_offset + w) for w in dst_words],
            )
        )

    # 4. Build modes.
    modes: list[_RustMode] = []
    for mode_name, zone_names in self._modes:
        zone_ids = [self._zone_name_to_id[z] for z in zone_names]
        bitstring_order: list[_RustLocAddr] = []
        for zid in zone_ids:
            offset = self._word_id_offsets[zid]
            zone = self._zones[zid]
            for w in range(zone.num_words):
                for s in range(zone.sites_per_word):
                    bitstring_order.append(_RustLocAddr(zid, offset + w, s))
        modes.append(
            _RustMode(
                name=mode_name,
                zones=zone_ids,
                bitstring_order=bitstring_order,
            )
        )

    # 5. Compute AOD waypoint paths for site and word buses.
    all_paths: dict[LaneAddress, tuple[tuple[float, float], ...]] = {}
    for zone_idx, zone in enumerate(self._zones):
        offset = self._word_id_offsets[zone_idx]
        all_paths.update(zone._compute_paths(zone_idx, offset))

    # 6. Determine the blockade radius to record on the ArchSpec.
    # Precedence: explicit build(blockade_radius=...) argument >
    # builder-level set_blockade_radius > zone-level agreement > None.
    resolved_radius = (
        blockade_radius
        if blockade_radius is not None
        else self._resolve_blockade_radius()
    )

    # 7. Assemble and validate.
    return ArchSpec.from_components(
        words=tuple(all_words),
        zones=tuple(rust_zones),
        modes=modes,
        zone_buses=zone_buses,
        paths=all_paths or None,
        feed_forward=feed_forward,
        atom_reloading=atom_reloading,
        blockade_radius=resolved_radius,
    )

connect

connect(
    src: tuple[str, Sequence[int]],
    dst: tuple[str, Sequence[int]],
) -> None

Add an inter-zone bus (zone_buses).

Parameters:

Name Type Description Default
src tuple[str, Sequence[int]]

(zone_name, zone_local_word_indices) — typically from zone[...] (indexing the zone itself, which returns a name-qualified tuple).

required
dst tuple[str, Sequence[int]]

(zone_name, zone_local_word_indices) — same format.

required

Validates AOD Cartesian product across the two zone grids.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
def connect(
    self,
    src: tuple[str, Sequence[int]],
    dst: tuple[str, Sequence[int]],
) -> None:
    """Add an inter-zone bus (zone_buses).

    Args:
        src: ``(zone_name, zone_local_word_indices)`` — typically
            from ``zone[...]`` (indexing the zone itself, which
            returns a name-qualified tuple).
        dst: ``(zone_name, zone_local_word_indices)`` — same format.

    Validates AOD Cartesian product across the two zone grids.
    """
    src_name, src_words = src
    dst_name, dst_words = dst
    if src_name not in self._zone_name_to_id:
        raise ValueError(f"Unknown zone: '{src_name}'")
    if dst_name not in self._zone_name_to_id:
        raise ValueError(f"Unknown zone: '{dst_name}'")

    src_zone = self._zones[self._zone_name_to_id[src_name]]
    dst_zone = self._zones[self._zone_name_to_id[dst_name]]
    src_positions = [src_zone._word_origin(w) for w in src_words]
    dst_positions = [dst_zone._word_origin(w) for w in dst_words]
    _validate_aod_rectangle(src_positions, "Zone bus src")
    _validate_aod_rectangle(dst_positions, "Zone bus dst")

    self._connections.append((src, dst))

set_blockade_radius

set_blockade_radius(radius: float) -> None

Apply radius to every zone by calling :meth:ZoneBuilder.set_blockade_radius on each.

Overwrites every zone's entangling pairs with the scan result. The radius is stored on the builder and flows to ArchSpec.blockade_radius at :meth:build time.

The radius is validated up-front (positive, finite, nm-precise) before any zone is touched, and the scan is run two-phase: every zone is scanned before any pair list is overwritten, so a layout error in a later zone cannot leave earlier zones in a partially-updated state.

Parameters:

Name Type Description Default
radius float

Rydberg blockade radius in micrometers.

required

Raises:

Type Description
ValueError

if radius itself is invalid (non-positive, non-finite, sub-nm), or if any zone's layout is inconsistent with the radius. The error message includes the zone name and offending word IDs.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
def set_blockade_radius(self, radius: float) -> None:
    """Apply ``radius`` to every zone by calling
    :meth:`ZoneBuilder.set_blockade_radius` on each.

    Overwrites every zone's entangling pairs with the scan result.
    The radius is stored on the builder and flows to
    ``ArchSpec.blockade_radius`` at :meth:`build` time.

    The radius is validated up-front (positive, finite, nm-precise)
    *before* any zone is touched, and the scan is run two-phase:
    every zone is scanned before any pair list is overwritten, so
    a layout error in a later zone cannot leave earlier zones in a
    partially-updated state.

    Args:
        radius: Rydberg blockade radius in micrometers.

    Raises:
        ValueError: if ``radius`` itself is invalid (non-positive,
            non-finite, sub-nm), or if any zone's layout is
            inconsistent with the radius. The error message
            includes the zone name and offending word IDs.
    """
    if radius <= 0:
        raise ValueError(f"blockade_radius must be positive, got {radius}")
    radius_nm = _to_nm(radius, "blockade_radius")

    # Phase 1: scan every zone.  Any zone-level failure raises here
    # before we've mutated anything.
    scan_results: list[list[tuple[int, int]]] = [
        zone._scan_blockade_pairs(radius_nm) for zone in self._zones
    ]

    # Phase 2: commit.  No further failures possible.
    for zone, pairs in zip(self._zones, scan_results):
        zone._entangling_pairs = pairs
        zone._blockade_radius_nm = radius_nm
    self._blockade_radius = radius

ZoneBuilder

ZoneBuilder(
    name: str,
    grid: Grid,
    word_shape: tuple[int, int],
    *,
    x_clearance: float,
    y_clearance: float
)

Build a single zone with its words, grid, and buses.

All indices are zone-local. Words are placed on the zone's grid and validated for shape and overlap. Buses are validated for AOD Cartesian product compliance.

Parameters:

Name Type Description Default
name str

Human-readable zone name (stored in Rust Zone).

required
grid Grid

Coordinate grid for this zone. Every x- and y-position must be representable at 1 nm precision (i.e., at most 3 decimal places when given in µm).

required
word_shape tuple[int, int]

(num_x_sites, num_y_sites) — uniform shape for all words in this zone. sites_per_word = product of shape.

required
x_clearance float

Minimum physical distance (> 0, µm) from grid lines that path waypoints must maintain on the x-axis. Must be representable at 1 nm precision.

required
y_clearance float

Same as x_clearance, applied to the y-axis. Allowing separate values is useful when row and column spacings differ substantially (e.g., tight intra-pair x spacing but wide row spacing).

required

Raises:

Type Description
ValueError

If either clearance is not positive or any position / clearance value is not nm-precise.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
def __init__(
    self,
    name: str,
    grid: _RustGrid,
    word_shape: tuple[int, int],
    *,
    x_clearance: float,
    y_clearance: float,
):
    """Initialize a zone.

    Args:
        name: Human-readable zone name (stored in Rust Zone).
        grid: Coordinate grid for this zone.  Every x- and y-position
            must be representable at 1 nm precision (i.e., at most 3
            decimal places when given in µm).
        word_shape: (num_x_sites, num_y_sites) — uniform shape for
            all words in this zone. sites_per_word = product of shape.
        x_clearance: Minimum physical distance (> 0, µm) from grid
            lines that path waypoints must maintain on the x-axis.
            Must be representable at 1 nm precision.
        y_clearance: Same as ``x_clearance``, applied to the y-axis.
            Allowing separate values is useful when row and column
            spacings differ substantially (e.g., tight intra-pair x
            spacing but wide row spacing).

    Raises:
        ValueError: If either clearance is not positive or any
            position / clearance value is not nm-precise.
    """
    if x_clearance <= 0:
        raise ValueError(f"x_clearance must be positive, got {x_clearance}")
    if y_clearance <= 0:
        raise ValueError(f"y_clearance must be positive, got {y_clearance}")
    self._name = name
    self._grid = grid
    self._word_shape = word_shape
    # Internal nm-integer representation for exact path search.
    self._x_clearance_nm = _to_nm(x_clearance, "x_clearance")
    self._y_clearance_nm = _to_nm(y_clearance, "y_clearance")
    self._grid_x_nm: list[int] = [
        _to_nm(x, "grid x-position") for x in grid.x_positions
    ]
    self._grid_y_nm: list[int] = [
        _to_nm(y, "grid y-position") for y in grid.y_positions
    ]
    self._words: list[list[tuple[int, int]]] = []
    self._word_has_site_bus: list[bool] = []
    self._position_to_word: dict[tuple[int, int], int] = {}
    self._site_buses: list[tuple[list[int], list[int]]] = []
    self._word_buses: list[tuple[list[int], list[int]]] = []
    self._entangling_pairs: list[tuple[int, int]] = []
    self._blockade_radius_nm: int | None = None

blockade_radius property

blockade_radius: float | None

Rydberg blockade radius (µm) used to derive entangling pairs, or None.

name property

name: str

Zone name.

num_words property

num_words: int

Number of words added so far.

sites property

sites: _SiteGridQuery

Query site indices within the word shape.

sites_per_word property

sites_per_word: int

Total sites per word (product of word_shape).

word_shape property

word_shape: tuple[int, int]

(num_x_sites, num_y_sites) for each word.

words property

words: _WordGridQuery

Query word indices by grid region for intra-zone use.

Returns a plain list[int] of zone-local word indices whose sites intersect the queried region — suitable for passing directly to add_word_bus / add_entangling_pairs.

For cross-zone references (e.g. ArchBuilder.connect), index the zone itself (zone[region]) to get a name-qualified (name, list[int]) tuple.

x_clearance property

x_clearance: float

Minimum x-axis clearance (µm) from grid lines for waypoints.

y_clearance property

y_clearance: float

Minimum y-axis clearance (µm) from grid lines for waypoints.

__getitem__

__getitem__(
    key: tuple[
        slice | int | Sequence[int],
        slice | int | Sequence[int],
    ],
) -> tuple[str, list[int]]

Query word indices by grid region, name-qualified for cross-zone use.

Returns (self.name, zone.words[key]) so the result can be passed directly to ArchBuilder.connect(src=..., dst=...), which expects (zone_name, zone_local_indices).

For intra-zone use (passing indices to add_word_bus etc.), use zone.words[key] which returns just the index list.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
554
555
556
557
558
559
560
561
562
563
564
565
566
def __getitem__(
    self, key: tuple[slice | int | Sequence[int], slice | int | Sequence[int]]
) -> tuple[str, list[int]]:
    """Query word indices by grid region, name-qualified for cross-zone use.

    Returns ``(self.name, zone.words[key])`` so the result can be
    passed directly to ``ArchBuilder.connect(src=..., dst=...)``,
    which expects ``(zone_name, zone_local_indices)``.

    For intra-zone use (passing indices to ``add_word_bus`` etc.),
    use ``zone.words[key]`` which returns just the index list.
    """
    return (self._name, self.words[key])

add_entangling_pairs

add_entangling_pairs(
    words_a: Sequence[int], words_b: Sequence[int]
) -> None

Mark paired zone-local words as CZ pairs.

words_a[i] is paired with words_b[i]. The two sequences must have the same length.

For most users, prefer :meth:set_blockade_radius — it derives the pair list directly from geometry and validates the word layout against the CZ-pairing convention.

Any blockade_radius previously recorded on this zone (via :meth:set_blockade_radius) is cleared, since a manual append means the pair list is no longer purely radius-derived.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
def add_entangling_pairs(
    self, words_a: Sequence[int], words_b: Sequence[int]
) -> None:
    """Mark paired zone-local words as CZ pairs.

    ``words_a[i]`` is paired with ``words_b[i]``. The two sequences
    must have the same length.

    For most users, prefer :meth:`set_blockade_radius` — it derives
    the pair list directly from geometry and validates the word
    layout against the CZ-pairing convention.

    Any ``blockade_radius`` previously recorded on this zone (via
    :meth:`set_blockade_radius`) is cleared, since a manual append
    means the pair list is no longer purely radius-derived.
    """
    if len(words_a) != len(words_b):
        raise ValueError(
            f"words_a has {len(words_a)} entries but words_b has " f"{len(words_b)}"
        )
    n = len(self._words)
    for a, b in zip(words_a, words_b):
        if a < 0 or a >= n:
            raise ValueError(f"word index {a} out of range [0, {n})")
        if b < 0 or b >= n:
            raise ValueError(f"word index {b} out of range [0, {n})")
        self._entangling_pairs.append((a, b))
    # Pair list was just manually modified; the cached radius no
    # longer describes its full state.
    self._blockade_radius_nm = None

add_site_bus

add_site_bus(
    src: Sequence[int], dst: Sequence[int]
) -> None

Add a site bus (intra-word movement).

src/dst are site indices within word_shape (0..sites_per_word). Must have equal length. Validates that src and dst positions each form a valid AOD Cartesian product on the word grid.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
def add_site_bus(self, src: Sequence[int], dst: Sequence[int]) -> None:
    """Add a site bus (intra-word movement).

    src/dst are site indices within word_shape (0..sites_per_word).
    Must have equal length. Validates that src and dst positions each
    form a valid AOD Cartesian product on the word grid.
    """
    if len(src) != len(dst):
        raise ValueError(
            f"Site bus src has {len(src)} entries but dst has {len(dst)}"
        )
    total = self.sites_per_word
    nx = self._word_shape[0]
    for s in src:
        if s < 0 or s >= total:
            raise ValueError(f"site index {s} out of range [0, {total})")
    for d in dst:
        if d < 0 or d >= total:
            raise ValueError(f"site index {d} out of range [0, {total})")

    src_positions = [(s % nx, s // nx) for s in src]
    dst_positions = [(d % nx, d // nx) for d in dst]
    _validate_aod_rectangle(src_positions, "Site bus src")
    _validate_aod_rectangle(dst_positions, "Site bus dst")
    self._site_buses.append((list(src), list(dst)))

add_word

add_word(
    x_sites: slice | Sequence[int],
    y_sites: slice | Sequence[int],
    *,
    has_site_bus: bool = True
) -> int

Add a word occupying the given grid positions.

The number of x-indices and y-indices must match word_shape. Grid positions must not overlap with any existing word.

Parameters:

Name Type Description Default
x_sites slice | Sequence[int]

Grid x-indices for the word's sites.

required
y_sites slice | Sequence[int]

Grid y-indices for the word's sites.

required
has_site_bus bool

Whether this word participates in site-bus transport. Feeds the zone-level words_with_site_buses list on the final ArchSpec — only words with has_site_bus=True are eligible to have site buses applied to them. Defaults to True, which preserves the historical "all words opt-in" behavior. Set to False on storage words that shouldn't participate in site-level routing.

True

Returns:

Type Description
int

Zone-local word index.

Raises:

Type Description
ValueError

Shape mismatch or grid position overlap.

IndexError

Indices out of range for this zone's grid.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
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
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
def add_word(
    self,
    x_sites: slice | Sequence[int],
    y_sites: slice | Sequence[int],
    *,
    has_site_bus: bool = True,
) -> int:
    """Add a word occupying the given grid positions.

    The number of x-indices and y-indices must match word_shape.
    Grid positions must not overlap with any existing word.

    Args:
        x_sites: Grid x-indices for the word's sites.
        y_sites: Grid y-indices for the word's sites.
        has_site_bus: Whether this word participates in site-bus
            transport. Feeds the zone-level
            ``words_with_site_buses`` list on the final ``ArchSpec``
            — only words with ``has_site_bus=True`` are eligible to
            have site buses applied to them. Defaults to ``True``,
            which preserves the historical "all words opt-in"
            behavior. Set to ``False`` on storage words that
            shouldn't participate in site-level routing.

    Returns:
        Zone-local word index.

    Raises:
        ValueError: Shape mismatch or grid position overlap.
        IndexError: Indices out of range for this zone's grid.
    """
    xs = _normalize_index(x_sites, self._grid.num_x)
    ys = _normalize_index(y_sites, self._grid.num_y)

    if len(xs) != self._word_shape[0]:
        raise ValueError(
            f"x_sites has {len(xs)} indices but word_shape requires "
            f"{self._word_shape[0]}"
        )
    if len(ys) != self._word_shape[1]:
        raise ValueError(
            f"y_sites has {len(ys)} indices but word_shape requires "
            f"{self._word_shape[1]}"
        )

    for x in xs:
        if x < 0 or x >= self._grid.num_x:
            raise IndexError(
                f"x index {x} out of range for grid with "
                f"{self._grid.num_x} x-positions"
            )
    for y in ys:
        if y < 0 or y >= self._grid.num_y:
            raise IndexError(
                f"y index {y} out of range for grid with "
                f"{self._grid.num_y} y-positions"
            )

    positions = [(x, y) for y in ys for x in xs]
    for pos in positions:
        if pos in self._position_to_word:
            owner = self._position_to_word[pos]
            raise ValueError(
                f"Grid position (x={pos[0]}, y={pos[1]}) "
                f"already belongs to word {owner}"
            )

    word_id = len(self._words)
    self._words.append(positions)
    self._word_has_site_bus.append(has_site_bus)
    for pos in positions:
        self._position_to_word[pos] = word_id
    return word_id

add_word_bus

add_word_bus(
    src: Sequence[int], dst: Sequence[int]
) -> None

Add a word bus (intra-zone movement).

src/dst are zone-local word indices. Must have equal length. Validates that src and dst word positions each form a valid AOD Cartesian product on the zone grid.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
def add_word_bus(self, src: Sequence[int], dst: Sequence[int]) -> None:
    """Add a word bus (intra-zone movement).

    src/dst are zone-local word indices. Must have equal length.
    Validates that src and dst word positions each form a valid AOD
    Cartesian product on the zone grid.
    """
    if len(src) != len(dst):
        raise ValueError(
            f"Word bus src has {len(src)} entries but dst has {len(dst)}"
        )
    n = len(self._words)
    for s in src:
        if s < 0 or s >= n:
            raise ValueError(f"word index {s} out of range [0, {n})")
    for d in dst:
        if d < 0 or d >= n:
            raise ValueError(f"word index {d} out of range [0, {n})")

    src_positions = [self._word_origin(s) for s in src]
    dst_positions = [self._word_origin(d) for d in dst]
    _validate_aod_rectangle(src_positions, "Word bus src")
    _validate_aod_rectangle(dst_positions, "Word bus dst")
    self._word_buses.append((list(src), list(dst)))

set_blockade_radius

set_blockade_radius(radius: float) -> None

Derive entangling word pairs from the Rydberg blockade radius.

Scans every pair of distinct words in the zone and classifies each under the matching-site-index CZ convention:

  • All matching-index site distances <= radius and all non-matching-index site distances > radius: valid CZ pair.
  • Some matching-index distances within radius, some outside: ValueError (partial blockade — the word layout doesn't cleanly map onto the CZ-pairing convention).
  • Any non-matching-index site distance within radius (regardless of whether the matching-index distances also fall within): ValueError (crossed-index — two words are arranged such that site i of one word sits next to site j != i of the other, violating the exclusivity the convention requires).
  • All distances outside radius: words ignore each other, no pair recorded.

After classification, every word must appear in at most one valid pair; multiple partners raise ValueError.

This call overwrites _entangling_pairs with the scan result and stores the radius on the zone. To have it flow into the final ArchSpec.blockade_radius, either call :meth:ArchBuilder.set_blockade_radius (which applies to every zone and records the value at builder scope) or, for a single zone already set via ZoneBuilder.set_blockade_radius, ArchBuilder.build() will pick up a consistent zone-level radius automatically.

Parameters:

Name Type Description Default
radius float

Blockade radius in micrometers. Must be positive and representable at 1 nm precision.

required

Raises:

Type Description
ValueError

if the layout is inconsistent with the radius (partial blockade / crossed-index / multi-partner) or if radius is not positive / nm-precise.

Source code in .venv/lib/python3.12/site-packages/bloqade/lanes/arch/build/imperative.py
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
def set_blockade_radius(self, radius: float) -> None:
    """Derive entangling word pairs from the Rydberg blockade radius.

    Scans every pair of distinct words in the zone and classifies
    each under the matching-site-index CZ convention:

    * All matching-index site distances ``<= radius`` and all
      non-matching-index site distances ``> radius``: valid CZ pair.
    * Some matching-index distances within radius, some outside:
      ``ValueError`` (partial blockade — the word layout doesn't
      cleanly map onto the CZ-pairing convention).
    * Any non-matching-index site distance within radius (regardless
      of whether the matching-index distances also fall within):
      ``ValueError`` (crossed-index — two words are arranged such
      that site ``i`` of one word sits next to site ``j != i`` of
      the other, violating the exclusivity the convention requires).
    * All distances outside radius: words ignore each other, no
      pair recorded.

    After classification, every word must appear in **at most one**
    valid pair; multiple partners raise ``ValueError``.

    This call **overwrites** ``_entangling_pairs`` with the scan
    result and stores the radius on the zone.  To have it flow into
    the final ``ArchSpec.blockade_radius``, either call
    :meth:`ArchBuilder.set_blockade_radius` (which applies to every
    zone and records the value at builder scope) or, for a single
    zone already set via ``ZoneBuilder.set_blockade_radius``,
    ``ArchBuilder.build()`` will pick up a consistent zone-level
    radius automatically.

    Args:
        radius: Blockade radius in micrometers. Must be positive and
            representable at 1 nm precision.

    Raises:
        ValueError: if the layout is inconsistent with the radius
            (partial blockade / crossed-index / multi-partner) or
            if ``radius`` is not positive / nm-precise.
    """
    if radius <= 0:
        raise ValueError(f"blockade_radius must be positive, got {radius}")
    radius_nm = _to_nm(radius, "blockade_radius")
    self._entangling_pairs = self._scan_blockade_pairs(radius_nm)
    self._blockade_radius_nm = radius_nm