By: Lucien Huber <im@lcnbr.ch>
complete Python Idenso API parity
User request:
PLEASE IMPLEMENT THIS PLAN:
# Complete Python Idenso API parity with Rust
## API shape
Expose every applicable Idenso operation in two forms:
```python
from symbolica.community import idenso
result = idenso.simplify_gamma(expression, settings=...)
result = tensor_expression.simplify_gamma(settings=...)
```
- Module-level functions accept ordinary Symbolica `Expression` and return ordinary `Expression` or the operation’s natural non-expression result.
- Matching methods live on `TensorExpression` and retain tensor-aware behavior.
- Do not monkey-patch methods onto the base Symbolica `Expression`.
- Module functions remain the explicit escape hatch for users who want tensor-aware dispatch dropped.
- `TensorExpression` methods delegate to the same Rust Idenso implementations; do not duplicate algorithms.
- Since `spynso3` already depends on `idenso`, implement the structured method adapters there without introducing a dependency cycle.
Examples of paired APIs:
```python
idenso.simplify_gamma(expr, settings=...)
tensor_expr.simplify_gamma(settings=...)
idenso.simplify_color(expr, settings=...)
tensor_expr.simplify_color(settings=...)
idenso.to_color_casimir(
expr,
fundamental=cof,
adjoint=coad,
settings=...,
)
tensor_expr.to_color_casimir(
fundamental=cof,
adjoint=coad,
settings=...,
)
idenso.cook(expr, settings=...)
tensor_expr.cook(settings=...)
```
- Single-expression methods that preserve valid tensor syntax return `TensorExpression` with the re-inferred interface.
- Operations intentionally producing ordinary symbolic encodings return `Expression`.
- Selective expansion methods return `(structure, coefficient)` expression pairs.
- Aliasing and network operations return their existing natural alias/network types.
- Stubs document these return types explicitly.
## Idenso surface coverage
Use the current Rust Idenso implementation as the source of truth. Treat `7d87d16a` only as optional historical inspiration.
Add paired function/method coverage for:
- Gamma, gamma-chain, gamma-conjugation, gamma-zero, epsilon, metric, and color simplification.
- Gamma/color collection, color-constant collection, wrapping, Casimir conversion, and cof-dimension conversion.
- General and representation-specific selective expansion.
- Canonization, subtensor aliasing, Spenso conjugation, conjugate transpose, and Dirac adjoint.
- Cook/uncook operations, source filters, tag filters, modes, and output-tag policies.
- Schoonschip expression/network execution, traversal, contraction ordering, and settings.
- Dot expansion/normalization, metric-to-dot conversion, chain collection/normalization, chainification, and undo operations.
Expose the associated public settings and enums:
```text
GammaChainOrdering
GammaSimplifySettings
ColorSimplifySettings
ColorCasimirSettings
CookMode
CookTagFilter
CookSourceFilter
CookSettings
SchoonschipMode
SchoonschipTraversal
SchoonschipContractionOrder
SchoonschipSettings
```
- Use immutable keyword constructors covering current Rust settings fields.
- Match current Rust defaults.
- Add named presets where Rust defines meaningful standard configurations.
- Keep Rust builders, traits, registries, macros, and internal pipeline stages private.
- Translate fallible Rust operations into specific Python exceptions.
## Representation and color support
Add representation-owned scalar helpers:
```python
rep.dimension
rep.casimir(degree=2)
rep.dynkin_index(degree=2)
rep.gram(degree, other=None)
```
These return ordinary `Expression`.
Provide representation-aware Casimir rewriting as one part of the wider color API:
- Receive `fundamental` and `adjoint` as required function keywords or method keywords.
- Rewrite the exact supplied adjoint dimension using:
```text
dA → dF * CF / TF
```
- Match only scalar coefficient positions; never rewrite representation atoms or tensor interfaces.
- Keep optional settings for \(d_F=C_A\) and \(T_F=1/2\).
- Do not globally replace concrete numbers such as `8`.
Remove legacy `NA` handling:
- Remove the registered symbol, evaluator, initialization, settings, documentation, and name-based rewrites.
- Do not merge `fix-color-adjoint-dimension`.
- Do not expose global color constants or `TensorName` invariant builders.
- Require typed color structures with explicit dimensions.
- Reject structured `f(a,b,c)` and remove the implicit `Nc²-1` fallback.
- Continue supporting explicitly supplied concrete or symbolic dimensions.
## Initialization, stubs, and verification
- Keep initialization automatic and private; expose neither `initialize` nor `initialize_module`.
- Generate module functions, settings, enums, and `TensorExpression` methods through native stub annotations.
- Verify every module function has the intended matching `TensorExpression` method.
- Verify base `Expression` has not been extended or monkey-patched.
- Require exact runtime/stub export, signature, and return-type parity.
- Generate, format, parse, and type-check all stubs twice and require byte-identical output.
- Assert removed legacy and prototype names are absent.
- Test every capability through both its module function and `TensorExpression` method.
- Verify interface preservation, natural non-expression return types, settings defaults, exceptions, representation-aware color rewriting, and absence of special `NA` behavior.
- Keep the 29-case color comparison at 29/29.
- Run direct licensed runtime and Community integration checks in separate `.envrc` processes.
- Preserve the existing working-copy changes and deliver on `simplify-spenso-api`.