Hop
dataclass
¶
Hop(
target_layer: int,
source_layers: tuple[int, ...],
source_dims: tuple[int, ...],
source_nodes: tuple[str, ...],
target_dim: int,
source_index: tuple[int, ...],
target_index: tuple[int, ...],
)
Every edge entering one layer, as packed indices.
One entry of LayeredSpec.hops, never built by hand: a hop
is exactly what a single PackedLinear or
MaskedLinear computes. Packed source_index /
target_index hold all parents of target_layer, so
a skip edge is an ordinary pair rather than a term added
later, and no edge can be dropped. Columns are the source
layers concatenated, the axis gather_hop_inputs
assembles. There is no stored mask; to_mask() allocates
one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
int
|
Depth of the layer this hop produces. Always at least 1;
layer 0 has no parents. |
required |
|
tuple[int, ...]
|
Depths this hop reads, ascending, each one below
|
required |
|
tuple[int, ...]
|
Units contributed by each entry of |
required |
|
tuple[str, ...]
|
Node names of the concatenated source axis, source
layers in |
required |
|
int
|
Units in the target layer, equal to
|
required |
|
tuple[int, ...]
|
Concat-column of each live unit pair. A named edge
|
required |
|
tuple[int, ...]
|
Target-layer row of each live unit pair. A dense
rectangle would have |
required |
See Also
LayeredSpec : Holds hops, one per layer after the first.
gather_hop_inputs : Builds the tensor whose columns these
indices address.
scatter_hop_outputs : Splits that concatenated axis back
onto source layers.
PackedLinear : Applies one hop from the packed indices.
PackedLinear.transpose : Tied decode of this hop.
MaskedLinear : Applies one hop after to_mask().
Skip : Metadata for the edges in this hop that span layers.
LayeredSpec.hop_units : Slice of one named node on this
hop's concatenated source axis.
LayeredSpec.node_units : Slice of one named node on its
layer tensor.
Notes
Every named edge is a block of packed unit pairs in exactly one hop, the one of its target layer. At width 1 that block is a single pair and the pairs summed over all hops give the named-edge count. Applying a hop applies every parent of its layer at once.
To locate one source layer's block on the concatenated axis, add the widths in front of it:
offset = sum(source_dims[:source_layers.index(layer)])
column_offsets does that for you.
LayeredSpec.hop_units locates one named node on that
axis, widths included.
Examples:
A chain A -> H -> C plus the skip A -> C:
>>> import pandas as pd
>>> import kpnn2
>>> edgelist = pd.DataFrame(
... {
... "source": ["A", "H", "A"],
... "target": ["H", "C", "C"],
... }
... )
>>> spec = kpnn2.parse_layered(edgelist)
>>> hop = spec.hops[1]
>>> hop.target_layer, hop.source_layers
(2, (0, 1))
>>> hop.source_nodes
('A', 'H')
>>> hop.source_index, hop.target_index
((0, 1), (0, 0))
>>> hop.to_mask().tolist()
[[1.0, 1.0]]
Attributes¶
column_offsets
property
¶
column_offsets: tuple[int, ...]
First source column of each entry of source_layers.
Same length and order as source_layers. Add a node's
block start inside its own layer to get its concatenated
first unit. At width 1 the block start equals the node's
ordinal in layer_nodes.