haliax 1.4.dev412__tar.gz → 1.4.dev413__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. {haliax-1.4.dev412 → haliax-1.4.dev413}/PKG-INFO +1 -1
  2. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/api.md +83 -13
  3. haliax-1.4.dev413/docs/primer.md +183 -0
  4. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/__about__.py +1 -1
  5. haliax-1.4.dev412/docs/primer.md +0 -114
  6. {haliax-1.4.dev412 → haliax-1.4.dev413}/.agents/projects/api_parity.md +0 -0
  7. {haliax-1.4.dev412 → haliax-1.4.dev413}/.coveragerc +0 -0
  8. {haliax-1.4.dev412 → haliax-1.4.dev413}/.flake8 +0 -0
  9. {haliax-1.4.dev412 → haliax-1.4.dev413}/.github/workflows/publish_dev.yaml +0 -0
  10. {haliax-1.4.dev412 → haliax-1.4.dev413}/.github/workflows/run_pre_commit.yaml +0 -0
  11. {haliax-1.4.dev412 → haliax-1.4.dev413}/.github/workflows/run_quick_levanter_tests.yaml +0 -0
  12. {haliax-1.4.dev412 → haliax-1.4.dev413}/.github/workflows/run_tests.yaml +0 -0
  13. {haliax-1.4.dev412 → haliax-1.4.dev413}/.gitignore +0 -0
  14. {haliax-1.4.dev412 → haliax-1.4.dev413}/.playbooks/add-types.md +0 -0
  15. {haliax-1.4.dev412 → haliax-1.4.dev413}/.playbooks/wrap-non-named.md +0 -0
  16. {haliax-1.4.dev412 → haliax-1.4.dev413}/.pre-commit-config.yaml +0 -0
  17. {haliax-1.4.dev412 → haliax-1.4.dev413}/.readthedocs.yaml +0 -0
  18. {haliax-1.4.dev412 → haliax-1.4.dev413}/AGENTS.md +0 -0
  19. {haliax-1.4.dev412 → haliax-1.4.dev413}/AUTHORS.md +0 -0
  20. {haliax-1.4.dev412 → haliax-1.4.dev413}/CONTRIBUTING.md +0 -0
  21. {haliax-1.4.dev412 → haliax-1.4.dev413}/CONTRIBUTORS.md +0 -0
  22. {haliax-1.4.dev412 → haliax-1.4.dev413}/LICENSE +0 -0
  23. {haliax-1.4.dev412 → haliax-1.4.dev413}/README.md +0 -0
  24. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/broadcasting.md +0 -0
  25. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/cheatsheet.md +0 -0
  26. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/css/material.css +0 -0
  27. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/css/mkdocstrings.css +0 -0
  28. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/faq.md +0 -0
  29. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/data_parallel_mesh.png +0 -0
  30. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/data_parallel_mesh_replicated.png +0 -0
  31. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_1d.png +0 -0
  32. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_1d_zero.png +0 -0
  33. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d.png +0 -0
  34. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d_batch_partitioned.png +0 -0
  35. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d_data_replicated.png +0 -0
  36. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d_data_replicated_mlp_partitioned.png +0 -0
  37. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d_intermediate_fully_partitioned.png +0 -0
  38. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/figures/device_mesh_2d_zero.png +0 -0
  39. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/fp8.md +0 -0
  40. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/index.md +0 -0
  41. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/indexing.md +0 -0
  42. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/matmul.md +0 -0
  43. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/nn.md +0 -0
  44. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/partitioning.md +0 -0
  45. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/rearrange.ipynb +0 -0
  46. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/rearrange.md +0 -0
  47. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/requirements.txt +0 -0
  48. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/scan.md +0 -0
  49. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/state-dict.md +0 -0
  50. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/tutorial.md +0 -0
  51. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/typing.md +0 -0
  52. {haliax-1.4.dev412 → haliax-1.4.dev413}/docs/vmap.md +0 -0
  53. {haliax-1.4.dev412 → haliax-1.4.dev413}/etc/license_header.txt +0 -0
  54. {haliax-1.4.dev412 → haliax-1.4.dev413}/mkdocs.yml +0 -0
  55. {haliax-1.4.dev412 → haliax-1.4.dev413}/pyproject.toml +0 -0
  56. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/__init__.py +0 -0
  57. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/__init__.py +0 -0
  58. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/compile_utils.py +0 -0
  59. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/dot.py +0 -0
  60. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/einsum.py +0 -0
  61. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/fp8.py +0 -0
  62. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/parsing.py +0 -0
  63. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/rearrange.py +0 -0
  64. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/scan.py +0 -0
  65. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/state_dict.py +0 -0
  66. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/_src/util.py +0 -0
  67. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/axis.py +0 -0
  68. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/core.py +0 -0
  69. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/debug.py +0 -0
  70. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/fft.py +0 -0
  71. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/field.py +0 -0
  72. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/haxtyping.py +0 -0
  73. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/hof.py +0 -0
  74. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/jax_utils.py +0 -0
  75. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/__init__.py +0 -0
  76. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/activations.py +0 -0
  77. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/attention.py +0 -0
  78. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/conv.py +0 -0
  79. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/dropout.py +0 -0
  80. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/embedding.py +0 -0
  81. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/linear.py +0 -0
  82. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/loss.py +0 -0
  83. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/mlp.py +0 -0
  84. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/normalization.py +0 -0
  85. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/pool.py +0 -0
  86. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/nn/scan.py +0 -0
  87. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/ops.py +0 -0
  88. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/partitioning.py +0 -0
  89. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/quantization.py +0 -0
  90. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/random.py +0 -0
  91. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/specialized_fns.py +0 -0
  92. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/state_dict.py +0 -0
  93. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/tree_util.py +0 -0
  94. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/types.py +0 -0
  95. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/util.py +0 -0
  96. {haliax-1.4.dev412 → haliax-1.4.dev413}/src/haliax/wrap.py +0 -0
  97. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/core_test.py +0 -0
  98. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_attention.py +0 -0
  99. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_axis.py +0 -0
  100. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_bitwise_ops.py +0 -0
  101. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_conv.py +0 -0
  102. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_debug.py +0 -0
  103. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_dot.py +0 -0
  104. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_dtype_typing.py +0 -0
  105. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_einsum.py +0 -0
  106. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_fft.py +0 -0
  107. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_field.py +0 -0
  108. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_fp8.py +0 -0
  109. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_hof.py +0 -0
  110. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_int8.py +0 -0
  111. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_moe_linear.py +0 -0
  112. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_namedarray_typing.py +0 -0
  113. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_nan_reductions.py +0 -0
  114. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_nn.py +0 -0
  115. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_ops.py +0 -0
  116. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_parsing.py +0 -0
  117. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_partitioning.py +0 -0
  118. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_pool.py +0 -0
  119. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_random.py +0 -0
  120. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_rearrange.py +0 -0
  121. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_scan.py +0 -0
  122. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_scatter_gather.py +0 -0
  123. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_specialized_fns.py +0 -0
  124. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_state_dict.py +0 -0
  125. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_tree_util.py +0 -0
  126. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_utils.py +0 -0
  127. {haliax-1.4.dev412 → haliax-1.4.dev413}/tests/test_visualize_sharding.py +0 -0
  128. {haliax-1.4.dev412 → haliax-1.4.dev413}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haliax
3
- Version: 1.4.dev412
3
+ Version: 1.4.dev413
4
4
  Summary: Named Tensors for Legible Deep Learning in JAX
5
5
  Project-URL: Homepage, https://github.com/stanford-crfm/haliax
6
6
  Project-URL: Bug Tracker, https://github.com/stanford-crfm/haliax/issues/
@@ -6,19 +6,89 @@ arrays (see [haliax.zeros][] and [haliax.ones][]) as well as things like reducti
6
6
 
7
7
  ## Axis Types
8
8
 
9
- There are four types related to [haliax.Axis][] you will see in the API reference:
10
-
11
- * [haliax.Axis][]: This is the main type for representing axes. It is a dataclass with a name and a size.
12
- * [haliax.AxisSelector][]: This is a type alias for either [haliax.Axis][] or a `str`. This type is used when we want
13
- one axis and the size can be inferred from the inputs.
14
- * [haliax.AxisSpec][]: This is a type alias for either [haliax.Axis][] or a tuple/list of [haliax.Axis][]. This type is
15
- used when we want one or more axes and the sizes cannot be inferred from the inputs, for instance when creating arrays.
16
- * [haliax.AxisSelection][]: This is a type alias for either [haliax.AxisSelector][] or a tuple/list of [haliax.AxisSelector][].
17
- This type is used when we want one or more axes and the sizes can be inferred from the inputs, for instance when
18
- reducing an array.
19
-
20
- Occasionally, an axis size can be inferred in some circumstances but not others. When this happens, we still use
21
- `AxisSelector` but document the behavior in the docstring. A RuntimeError will be raised if the size cannot be inferred.
9
+ If you already speak NumPy or `jax.numpy`, think of Haliax as swapping positional axes (`axis=0`) for named axes
10
+ (`axis="batch"`). The type hints in this section describe the different ways those named axes can be provided to the API.
11
+ They appear throughout the documentation and in signatures so that you can quickly tell which forms are accepted.
12
+
13
+ | Name | Accepts | When to use it | Example |
14
+ | --- | --- | --- | --- |
15
+ | [`Axis`][haliax.Axis] | `Axis(name: str, size: int)` | Define a named dimension with an explicit size | `Batch = Axis("batch", 32)` |
16
+ | [`AxisSelector`][haliax.AxisSelector] | `Axis` or `str` | Refer to an existing axis whose size can be inferred from the arrays you pass in | `x.sum(axis="batch")` |
17
+ | [`AxisSpec`][haliax.AxisSpec] | `dict[str, int]`, `Axis`, or a sequence of `Axis` objects | Create or reshape arrays when the axis sizes must be provided | `hax.zeros((Batch, Feature))` |
18
+ | [`AxisSelection`][haliax.AxisSelection] | `dict[str, int | None]`, `AxisSpec`, or a sequence of `AxisSelector` values | Work with one or more existing axes (reductions, indexing helpers, flattening, …) | `x.sum(axis=("batch", Feature))` |
19
+
20
+ ### Axis
21
+
22
+ An [`Axis`][haliax.Axis] is the fundamental building block: it is a tiny dataclass that stores a name and a size. You can
23
+ construct one directly or use [`haliax.make_axes`][] to generate several at a time.
24
+
25
+ ```python
26
+ import haliax as hax
27
+ from haliax import Axis
28
+
29
+ Batch = Axis("batch", 32)
30
+ Feature = Axis("feature", 128)
31
+ x = hax.ones((Batch, Feature))
32
+ print(Batch.name, Batch.size)
33
+ ```
34
+
35
+ Using `Axis` objects keeps array creation explicit and gives reusable handles you can share between different tensors.
36
+ Equality compares both the name and size so you get guardrails when wiring pieces together.
37
+
38
+ ### AxisSelector
39
+
40
+ An [`AxisSelector`][haliax.AxisSelector] accepts either an `Axis` object or just the axis name as a string. It is used
41
+ whenever a function can read the axis size from one of its arguments. This mirrors how NumPy lets you pass `axis=0` when
42
+ reducing an array:
43
+
44
+ ```python
45
+ total = x.sum(axis=Batch) # using the Axis handle
46
+ same_total = x.sum(axis="batch") # using only the name
47
+ ```
48
+
49
+ Strings are convenient when you only care about the name, but `Axis` objects still work so you can keep using the handles
50
+ you created earlier. If an axis with that name is missing, Haliax raises a `ValueError`.
51
+
52
+ ### AxisSpec
53
+
54
+ An [`AxisSpec`][haliax.AxisSpec] is used when Haliax needs full size information to create or reshape an array. You can
55
+ provide a shape dictionary (sometimes called a "shape dict") that maps names to sizes, or a sequence of `Axis` objects:
56
+
57
+ ```python
58
+ shape = {"batch": 32, "feature": 128}
59
+ y = hax.zeros(shape) # using a shape dict
60
+ z = hax.zeros((Batch, Feature)) # using the Axis objects directly
61
+ ```
62
+
63
+ Both forms describe the same layout. Python dictionaries preserve insertion order, so the ordering in a shape dict matches
64
+ the order that axes appear in the array. Sequences must contain `Axis` objects (not plain strings) because Haliax cannot
65
+ otherwise know the axis sizes.
66
+
67
+ ### AxisSelection
68
+
69
+ [`AxisSelection`][haliax.AxisSelection] generalizes the previous aliases so you can talk about several axes at once. It
70
+ shows up in reductions, indexing helpers, axis-mapping utilities, and anywhere you might have written `axis=(0, 1)` in
71
+ NumPy. You may supply:
72
+
73
+ * a sequence mixing `Axis` objects and strings, e.g. `("batch", Feature)` when reducing two axes,
74
+ * an `AxisSpec`, which is handy when you already have a tuple of `Axis` objects, or
75
+ * a "partial shape dict" where the values are either sizes or `None` to indicate "any size". Dictionaries are useful when
76
+ you only care about a subset of axes or want to assert a particular size.
77
+
78
+ ```python
79
+ # Reduce over two axes using a tuple of selectors.
80
+ scalar = x.sum(axis=("batch", Feature))
81
+
82
+ # Ask for the axes by name and optionally pin sizes.
83
+ x.resolve_axis({"batch": None, "feature": None}) # returns {"batch": 32, "feature": 128}
84
+
85
+ from haliax.axis import selects_axis
86
+ assert selects_axis((Batch, "feature"), {"batch": None, "feature": 128})
87
+ ```
88
+
89
+ Occasionally, an axis size can be inferred in some circumstances but not others. When this happens we still use
90
+ `AxisSelector` (or `AxisSelection` for multiple axes) but document the behavior in the docstring. A `RuntimeError` will be
91
+ raised if the size cannot be inferred.
22
92
 
23
93
  ::: haliax.Axis
24
94
  ::: haliax.AxisSelector
@@ -0,0 +1,183 @@
1
+ # Haliax Primer
2
+
3
+ Haliax provides named tensors built on top of JAX. This primer is written for LLM agents and other downstream libraries and collects the core ideas for quick reference.
4
+
5
+ ## Axes and Named Arrays
6
+
7
+ Arrays are indexed by `Axis` objects. You can define them explicitly or generate several with `make_axes`.
8
+ You may also specify shapes with a **shape dict**, mapping axis names to sizes.
9
+
10
+ ```python
11
+ import haliax as hax
12
+ from haliax import Axis
13
+
14
+ Batch = Axis("batch", 4)
15
+ Feature = Axis("feature", 8)
16
+ # or: Batch, Feature = hax.make_axes(batch=4, feature=8)
17
+ # using Axis objects
18
+ x = hax.zeros((Batch, Feature))
19
+ # or using a shape dict
20
+ shape = {"batch": 4, "feature": 8}
21
+ x = hax.zeros(shape)
22
+ ```
23
+
24
+ Most functions accept either axes or shape dicts interchangeably.
25
+
26
+ A tensor with named axes is a [`NamedArray`][haliax.NamedArray]. Elementwise operations mirror `jax.numpy` but accept named axes.
27
+
28
+ ### Ways to Describe Axes
29
+
30
+ If you're used to `axis=0` style code in NumPy or JAX, think of Haliax as swapping those positional indices for names
31
+ like `axis="batch"`. The API hints refer to a few helper aliases; this table shows how they map back to familiar
32
+ concepts:
33
+
34
+ | Name | Accepts | Typical use | Example |
35
+ | --- | --- | --- | --- |
36
+ | [`Axis`][haliax.Axis] | `Axis(name: str, size: int)` | Define a named dimension with a fixed size | `Batch = Axis("batch", 32)` |
37
+ | [`AxisSelector`][haliax.AxisSelector] | `Axis` or `str` | Refer to an existing axis when the size can be inferred from the argument | `x.sum(axis="batch")` |
38
+ | [`AxisSpec`][haliax.AxisSpec] | `dict[str, int]`, `Axis`, or a sequence of `Axis` objects | Supply complete shape information (array creation, reshaping) | `hax.zeros((Batch, Feature))` |
39
+ | [`AxisSelection`][haliax.AxisSelection] | `dict[str, int | None]`, `AxisSpec`, or a sequence of `AxisSelector` values | Work with one or more existing axes (reductions, indexing helpers, flattening, …) | `x.sum(axis=("batch", Feature))` |
40
+
41
+ The following sections expand on each alias with quick references and NumPy-style parallels.
42
+
43
+ #### `Axis`: reusable named dimensions
44
+
45
+ An [`Axis`][haliax.Axis] stores a `name` and a `size`. Create them directly or let
46
+ [`haliax.make_axes`][] build a handful at once. Because axes compare by both name and size, they act as reusable handles and
47
+ catch many wiring mistakes early.
48
+
49
+ ```python
50
+ Batch = Axis("batch", 32)
51
+ Feature = Axis("feature", 128)
52
+ x = hax.ones((Batch, Feature))
53
+ print(Batch.name, Batch.size)
54
+ ```
55
+
56
+ #### `AxisSelector`: when the size is already known
57
+
58
+ Many functions already see the array whose axes you're referencing (e.g. reductions). In those cases you can pass either the
59
+ `Axis` object or simply the axis name as a string. Haliax resolves the name against the array, similar to `axis=0` in NumPy.
60
+
61
+ ```python
62
+ total = x.sum(axis=Batch) # use the Axis handle
63
+ same_total = x.sum(axis="batch") # or just the name
64
+ ```
65
+
66
+ If you reference an axis name that isn't present, Haliax raises a `ValueError`.
67
+
68
+ #### `AxisSpec`: describing complete shapes
69
+
70
+ When Haliax needs explicit sizes—creating arrays, reshaping, broadcasting to a new axis—you provide an [`AxisSpec`][haliax.AxisSpec].
71
+ Shape dictionaries keep things close to standard Python, while sequences require actual `Axis` objects so the sizes stay explicit.
72
+
73
+ ```python
74
+ shape = {"batch": 32, "feature": 128}
75
+ y = hax.zeros(shape) # using a shape dict
76
+ z = hax.zeros((Batch, Feature)) # or a sequence of Axis objects
77
+ ```
78
+
79
+ Python dictionaries preserve insertion order, so the layout in a shape dict matches the order of axes in the resulting array.
80
+
81
+ #### `AxisSelection`: several axes at once
82
+
83
+ [`AxisSelection`][haliax.AxisSelection] is the plural form used by reductions, indexing helpers, and flattening utilities. Supply a
84
+ tuple mixing `Axis` objects and strings, reuse an existing `AxisSpec`, or pass a partial shape dict where values are either
85
+ sizes or `None` for "any size".
86
+
87
+ ```python
88
+ scalar = x.sum(axis=("batch", Feature))
89
+
90
+ # Ask for the axes by name and optionally pin sizes.
91
+ x.resolve_axis({"batch": None, "feature": None}) # returns {"batch": 32, "feature": 128}
92
+ ```
93
+
94
+ Partial shape dicts shine when you only care about a subset of axes or want assertions about their sizes. If the axis size
95
+ cannot be inferred from the provided arguments, Haliax raises a `RuntimeError`.
96
+
97
+ ## Indexing and Broadcasting
98
+
99
+ Use axis names when slicing. Dictionaries are convenient for several axes:
100
+
101
+ ```python
102
+ first = x["batch", 0]
103
+ sub = x["batch", 1:3]
104
+ # or with a dict
105
+ first = x[{"batch": 0}]
106
+ sub = x[{"batch": slice(1, 3)}]
107
+ ```
108
+
109
+ Axes broadcast by matching names. `broadcast_axis` adds a new axis to an array:
110
+
111
+ ```python
112
+ row = hax.arange(Feature)
113
+ outer = row.broadcast_axis(Batch) * hax.arange(Batch)
114
+ ```
115
+
116
+ See [Indexing and Slicing](indexing.md) and [Broadcasting](broadcasting.md) for details.
117
+
118
+ ## Rearranging Axes
119
+
120
+ `rearrange` changes axis order and can merge or split axes using einops‑style syntax. It is useful when interfacing with positional APIs.
121
+
122
+ ```python
123
+ # transpose features and batch
124
+ x_t = hax.rearrange(x, "batch feature -> feature batch")
125
+ ```
126
+
127
+ More examples appear in [Rearrange](rearrange.md).
128
+
129
+ ## Matrix Multiplication
130
+
131
+ `dot` contracts over named axes while preserving order independence.
132
+
133
+ ```python
134
+ Weight = Axis("weight", 8)
135
+ w = hax.ones((Feature, Weight))
136
+ prod = hax.dot(x, w, axis=Feature)
137
+ ```
138
+
139
+ For more complex contractions use [`einsum`][haliax.einsum]. See [Matrix Multiplication](matmul.md).
140
+
141
+ ## Scans and Folds
142
+
143
+ Use [`scan`][haliax.scan] or [`fold`][haliax.fold] to apply a function along an axis with optional gradient checkpointing.
144
+
145
+ ```python
146
+ Time = Axis("time", 10)
147
+ sequence = hax.ones((Time, Feature))
148
+
149
+ def add(prev, cur):
150
+ return prev + cur
151
+
152
+ result = hax.fold(add, Time)(hax.zeros((Feature,)), sequence)
153
+ ```
154
+
155
+ See [Scan and Fold](scan.md) for checkpointing policies and stacked modules.
156
+
157
+ ## Partitioning
158
+
159
+ Arrays and modules can be distributed across devices by mapping named axes to mesh axes:
160
+
161
+ ```python
162
+ with hax.axis_mapping({"batch": "data"}):
163
+ sharded = hax.shard(x)
164
+ ```
165
+
166
+ The [Partitioning](partitioning.md) guide explains how to set up device meshes and shard arrays.
167
+
168
+ ## Typing Support
169
+
170
+ Type annotations use `haliax.haxtyping` which extends `jaxtyping`:
171
+
172
+ ```python
173
+ import haliax.haxtyping as ht
174
+
175
+ def f(t: ht.Float[hax.NamedArray, "batch feature"]):
176
+ ...
177
+ ```
178
+
179
+ See [Typing](typing.md) for matching runtime checks and dtype-aware annotations.
180
+
181
+ ---
182
+
183
+ This primer highlights common patterns. The [cheatsheet](cheatsheet.md) lists many additional conversions from JAX to Haliax.
@@ -3,4 +3,4 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
5
 
6
- __version__ = "1.4.dev412"
6
+ __version__ = "1.4.dev413"
@@ -1,114 +0,0 @@
1
- # Haliax Primer
2
-
3
- Haliax provides named tensors built on top of JAX. This primer is written for LLM agents and other downstream libraries and collects the core ideas for quick reference.
4
-
5
- ## Axes and Named Arrays
6
-
7
- Arrays are indexed by `Axis` objects. You can define them explicitly or generate several with `make_axes`.
8
- You may also specify shapes with a **shape dict**, mapping axis names to sizes.
9
-
10
- ```python
11
- import haliax as hax
12
- from haliax import Axis
13
-
14
- Batch = Axis("batch", 4)
15
- Feature = Axis("feature", 8)
16
- # or: Batch, Feature = hax.make_axes(batch=4, feature=8)
17
- # using Axis objects
18
- x = hax.zeros((Batch, Feature))
19
- # or using a shape dict
20
- shape = {"batch": 4, "feature": 8}
21
- x = hax.zeros(shape)
22
- ```
23
-
24
- Most functions accept either axes or shape dicts interchangeably.
25
-
26
- A tensor with named axes is a [`NamedArray`][haliax.NamedArray]. Elementwise operations mirror `jax.numpy` but accept named axes.
27
-
28
- ## Indexing and Broadcasting
29
-
30
- Use axis names when slicing. Dictionaries are convenient for several axes:
31
-
32
- ```python
33
- first = x["batch", 0]
34
- sub = x["batch", 1:3]
35
- # or with a dict
36
- first = x[{"batch": 0}]
37
- sub = x[{"batch": slice(1, 3)}]
38
- ```
39
-
40
- Axes broadcast by matching names. `broadcast_axis` adds a new axis to an array:
41
-
42
- ```python
43
- row = hax.arange(Feature)
44
- outer = row.broadcast_axis(Batch) * hax.arange(Batch)
45
- ```
46
-
47
- See [Indexing and Slicing](indexing.md) and [Broadcasting](broadcasting.md) for details.
48
-
49
- ## Rearranging Axes
50
-
51
- `rearrange` changes axis order and can merge or split axes using einops‑style syntax. It is useful when interfacing with positional APIs.
52
-
53
- ```python
54
- # transpose features and batch
55
- x_t = hax.rearrange(x, "batch feature -> feature batch")
56
- ```
57
-
58
- More examples appear in [Rearrange](rearrange.md).
59
-
60
- ## Matrix Multiplication
61
-
62
- `dot` contracts over named axes while preserving order independence.
63
-
64
- ```python
65
- Weight = Axis("weight", 8)
66
- w = hax.ones((Feature, Weight))
67
- prod = hax.dot(x, w, axis=Feature)
68
- ```
69
-
70
- For more complex contractions use [`einsum`][haliax.einsum]. See [Matrix Multiplication](matmul.md).
71
-
72
- ## Scans and Folds
73
-
74
- Use [`scan`][haliax.scan] or [`fold`][haliax.fold] to apply a function along an axis with optional gradient checkpointing.
75
-
76
- ```python
77
- Time = Axis("time", 10)
78
- sequence = hax.ones((Time, Feature))
79
-
80
- def add(prev, cur):
81
- return prev + cur
82
-
83
- result = hax.fold(add, Time)(hax.zeros((Feature,)), sequence)
84
- ```
85
-
86
- See [Scan and Fold](scan.md) for checkpointing policies and stacked modules.
87
-
88
- ## Partitioning
89
-
90
- Arrays and modules can be distributed across devices by mapping named axes to mesh axes:
91
-
92
- ```python
93
- with hax.axis_mapping({"batch": "data"}):
94
- sharded = hax.shard(x)
95
- ```
96
-
97
- The [Partitioning](partitioning.md) guide explains how to set up device meshes and shard arrays.
98
-
99
- ## Typing Support
100
-
101
- Type annotations use `haliax.haxtyping` which extends `jaxtyping`:
102
-
103
- ```python
104
- import haliax.haxtyping as ht
105
-
106
- def f(t: ht.Float[hax.NamedArray, "batch feature"]):
107
- ...
108
- ```
109
-
110
- See [Typing](typing.md) for matching runtime checks and dtype-aware annotations.
111
-
112
- ---
113
-
114
- This primer highlights common patterns. The [cheatsheet](cheatsheet.md) lists many additional conversions from JAX to Haliax.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes