Nicole 0.3.6
Nicole 0.3.6 — API Versioning and Hot-path Optimization
Release Date: April 30, 2026
Version 0.3.6 exposes the package version as nicole.__version__ and tightens the symmetry group internals: redundant validate_charge guard calls are removed from hot paths across SU2Group and ProductGroup, fuse_unique implementations in U1Group and Z2Group are simplified to built-in expressions, and ProductGroup caches its neutral element at construction time. No public API is changed.
✨ New Features
nicole.__version__
__version__ is now a public attribute of the nicole package, set at import time via importlib.metadata.version("nicole"):
import nicole
print(nicole.__version__) # e.g. "0.3.6"This follows the standard Python convention for installed packages and makes it easy to verify the running version in scripts, notebooks, and bug reports.
🚀 Enhancements
Symmetry group hot-path cleanup
Several symmetry group methods carried redundant validate_charge calls that re-checked types and ranges on charges that are already known to be valid at the call site (they came from internal tensor operations, not from user input). Those guards have been removed:
| Location | Removed guards |
|---|---|
U1Group.fuse_unique |
validation loop over qs |
Z2Group.fuse_unique |
validation loop over qs |
SU2Group.dual |
validate_charge(two_j) before returning |
SU2Group.irrep_dim |
validate_charge(two_j) before returning |
SU2Group.fuse_channels |
per-element validate_charge loop over two_js |
ProductGroup methods |
per-element validate_charge loops in several methods |
Validation still runs at tensor construction time (when charges originate from user input) and through the public validate_charge method. The removal eliminates repeated type and range checks in code paths that execute once per block per operation.
U1Group.fuse_unique is simplified to return sum(qs) and Z2Group.fuse_unique to a single XOR accumulation, replacing loops that also contained the now-removed guards. ProductGroup.equal is simplified to return a == b, delegating to built-in tuple equality instead of a manual component-wise loop.
ProductGroup neutral-element cache
ProductGroup.__init__ now precomputes the neutral element and stores it as a private _neutral tuple. The neutral property returns this cached value directly:
# before: tuple(comp.neutral for comp in self.components) on every access
# after: self._neutral (computed once at __init__)This is a minor but zero-cost improvement for code that accesses neutral repeatedly (e.g., inside fuse_unique and fuse_channels loops over many blocks).
🧪 Test Suite (1603 tests)
- 1593 tests pass, 10 skipped (accelerator-only tests on CPU-only CI)
- No new tests added in this release
📊 Statistics
Code Changes
- 7 commits since v0.3.5
- 4 files changed: 10 insertions, 29 deletions
- Source modules touched:
src/nicole/__init__.py,src/nicole/symmetry/abelian.py,src/nicole/symmetry/unitary.py,src/nicole/symmetry/product.py
✅ Compatibility
Breaking Changes: None. All previously valid calls continue to work unchanged. The new __version__ attribute does not conflict with any existing public name.
Requirements:
- Python ≥ 3.11
- PyTorch ≥ 2.5
- Yuzuha ≥ 0.1.5
📝 Notes
The validate_charge removals affect only internal method paths — dual, irrep_dim, fuse_unique, fuse_channels, and equal — which are not part of the documented public API. Code that calls symmetry group methods directly with out-of-range or wrong-type charges was already in undefined territory; the only change is that some of those paths will now propagate further before raising a Python-level error rather than being caught early. The public validate_charge method is untouched and remains the correct tool for validating user-supplied charges before passing them to a symmetry group.
nicole.__version__ reads from the installed package metadata via importlib.metadata.version. In an editable install (uv pip install -e .), the reported version reflects the value of version in pyproject.toml at the time the package was last (re-)installed, not at import time. Run uv pip install -e . again after bumping the version in pyproject.toml to keep __version__ in sync.