ucon.basis¶
Core basis abstractions: Basis, BasisComponent, Vector, and related exceptions.
Basis abstraction for user-definable dimensional coordinate systems.
This package provides the foundation for representing dimensions in arbitrary bases (SI, CGS, CGS-ESU, natural units, custom domains) without hardcoding to a specific set of components.
Submodules¶
types: Core types (Basis,BasisComponent, exceptions includingBasisMismatch,LossyProjection,NoTransformPath).vector:Vectordimensional exponent vectors. Arithmetic is strict same-basis; cross-basis arithmetic lives inops.transforms: Transform types and standard transform instances.graph:BasisGraphregistry and standard-graph factory.ops: Explicit cross-basis arithmetic (multiply_via,divide_via,unify).builtin: Standard bases (SI, CGS, CGS-ESU, CGS-EMU, NATURAL, PLANCK, ATOMIC).
BasisGraph
¶
Graph of basis transforms with path-finding and composition.
Nodes are Basis objects (dimensional coordinate systems). Edges are BasisTransform objects. Path-finding composes transforms transitively.
Examples:
>>> graph = BasisGraph()
>>> graph.add_transform(SI_TO_CGS)
>>> graph.add_transform(CGS_TO_CGS_ESU)
>>> # Transitive composition: SI -> CGS -> CGS-ESU
>>> transform = graph.get_transform(SI, CGS_ESU)
add_transform(transform)
¶
Register a transform. Does NOT auto-register inverse.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
transform
|
'_Transform'
|
The transform to register. |
required |
add_transform_pair(forward, reverse)
¶
Register bidirectional transforms (e.g., projection + embedding).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
forward
|
'BasisTransform'
|
Transform A -> B. |
required |
reverse
|
'BasisTransform'
|
Transform B -> A. |
required |
get_transform(source, target)
¶
Find or compose a transform between bases.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Basis
|
The source basis. |
required |
target
|
Basis
|
The target basis. |
required |
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
A BasisTransform from source to target. |
Raises:
| Type | Description |
|---|---|
NoTransformPath
|
If no path exists between the bases. |
are_connected(a, b)
¶
reachable_from(basis)
¶
with_transform(transform)
¶
Return a new graph with an additional transform (copy-on-extend).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
transform
|
'BasisTransform'
|
The transform to add. |
required |
Returns:
| Type | Description |
|---|---|
'BasisGraph'
|
A new BasisGraph with the additional transform. |
BasisTransform
dataclass
¶
Linear map between dimensional bases.
Represents how each component of the source basis expresses in terms of the target basis components via matrix multiplication.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Basis
|
The source basis. |
required |
target
|
Basis
|
The target basis. |
required |
matrix
|
tuple[tuple[Fraction, ...], ...]
|
Transformation matrix as tuple of tuples. Shape is
(len(source), len(target)). Entry |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If matrix dimensions don't match basis dimensions. |
Examples:
>>> # Identity transform
>>> identity = BasisTransform.identity(some_basis)
>>> identity.is_identity()
True
>>> # SI current in CGS-ESU: I -> L^(3/2) M^(1/2) T^(-2)
>>> transform = BasisTransform(SI, CGS_ESU, matrix)
>>> esu_dim = transform(si_current_vector)
__str__()
¶
Human-readable string with matrix visualization.
__call__(vector, *, allow_projection=False)
¶
Transform a vector from source basis to target basis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
Vector
|
The vector to transform (must be in source basis). |
required |
allow_projection
|
bool
|
If False (default), raise LossyProjection when a non-zero component would be discarded. If True, silently project (drop) unrepresentable components. |
False
|
Returns:
| Type | Description |
|---|---|
Vector
|
A new Vector in the target basis. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If vector is not in the source basis. |
LossyProjection
|
If allow_projection=False and a non-zero component maps entirely to zeros in the target basis. |
inverse()
¶
Return the inverse transform (target -> source).
Uses Gaussian elimination with partial pivoting over Fraction for exact arithmetic.
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
A new BasisTransform from target to source. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the matrix is not square or is singular. |
embedding()
¶
Return the canonical embedding (target -> source).
For a projection A -> B, the embedding B -> A maps each B component back to its source A component, with zeros for unmapped A components.
Only valid for clean projections where each target component maps from exactly one source component with coefficient 1.
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
A new BasisTransform from target to source. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the transform is not a clean projection. |
__matmul__(other)
¶
Compose transforms: (self @ other)(v) = self(other(v)).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
other
|
'BasisTransform'
|
Transform to apply first. |
required |
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
A composed transform from other.source to self.target. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If other.target != self.source. |
identity(basis)
classmethod
¶
Return the identity transform for a basis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
basis
|
Basis
|
The basis for the identity transform. |
required |
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
An identity transform where source == target == basis. |
append_components_embedding(parent, extended)
classmethod
¶
Return the zero-pad embedding parent -> extended.
Builds a clean parent -> extended embedding where each parent
component maps 1-to-1 to the same-named component in extended,
and components present only in extended are zero-padded (i.e.,
a parent vector lifts into extended with zeros on the added
slots).
This is the canonical transform for an "append-only" basis
extension (e.g., SI extended with a currency component to
form a financial basis). With this transform registered in the
active :class:~ucon.basis.graph.BasisGraph,
:func:~ucon.basis.ops.unify succeeds when composing parent-basis
vectors with extended-basis vectors.
The reverse projection (extended -> parent) is derived via
:meth:embedding; it drops the added components and raises
:class:~ucon.basis.types.LossyProjection if any of them is
non-zero, which is the correct behavior for unification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
Basis
|
The smaller basis (e.g., |
required |
extended
|
Basis
|
The larger basis that contains every component of
|
required |
Returns:
| Type | Description |
|---|---|
'BasisTransform'
|
A |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any parent component is not present (by name)
in |
Examples:
is_identity()
¶
Check if this transform is the identity.
Returns:
| Type | Description |
|---|---|
bool
|
True if source == target and matrix is identity matrix. |
ConstantBinding
dataclass
¶
Binds a source dimension to a target expression via a physical constant.
Records that source_component in the source basis becomes
target_expression in the target basis, with the relationship
defined by a physical constant raised to exponent.
Parameters¶
source_component : BasisComponent The fundamental component being transformed. target_expression : Vector How it expresses in the target basis. constant_symbol : str Symbol of the constant defining this relationship (e.g., "c", "ℏ"). We use a string rather than a Constant object to avoid circular imports between ucon.basis and ucon.constants. exponent : Fraction Power of the constant in the relationship (usually ±1/2 or ±1).
Examples¶
In natural units: length = ℏc/E, so L → E⁻¹ via ℏc¶
from fractions import Fraction binding = ConstantBinding( ... source_component=BasisComponent("length", "L"), ... target_expression=Vector(NATURAL, (Fraction(-1),)), ... constant_symbol="ℏc", ... exponent=Fraction(1), ... )
ConstantBoundBasisTransform
dataclass
¶
A basis transform with constants that enable inversion of non-square matrices.
Extends BasisTransform with explicit constant bindings that record which
constants define each non-trivial mapping. This enables inverse() to work
on non-square transforms by providing the information needed to reverse
derived mappings.
Parameters¶
source : Basis Source basis. target : Basis Target basis. matrix : tuple[tuple[Fraction, ...], ...] Dimensional transformation matrix. Shape is (len(source), len(target)). bindings : tuple[ConstantBinding, ...] Constants that define derived relationships.
Examples¶
SI (8 dimensions) → NATURAL (1 dimension) transform¶
SI_TO_NATURAL = ConstantBoundBasisTransform( ... source=SI, ... target=NATURAL, ... matrix=(...), # 8×1 matrix ... bindings=(...), # Bindings for L, T, M, Θ → E ... )
This works because bindings record how to reverse!¶
NATURAL_TO_SI = SI_TO_NATURAL.inverse()
__call__(vector, *, allow_projection=False)
¶
Transform a vector from source basis to target basis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vector
|
Vector
|
The vector to transform (must be in source basis). |
required |
allow_projection
|
bool
|
If False (default), raise LossyProjection when a non-zero component would be discarded. If True, silently project (drop) unrepresentable components. |
False
|
Returns:
| Type | Description |
|---|---|
Vector
|
A new Vector in the target basis. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If vector is not in the source basis. |
LossyProjection
|
If allow_projection=False and a non-zero component maps entirely to zeros in the target basis. |
inverse()
¶
Compute the inverse transform using constant bindings.
For each binding (src_component → target_expression via constant): - The inverse maps target_expression → src_component - The constant exponent is negated (constant^(-exponent))
Returns¶
ConstantBoundBasisTransform The inverse transform from target to source.
Raises¶
ValueError If a source component has no binding and cannot be inverted.
Notes¶
Components that map to zero (truly dropped) cannot be recovered and will map to zero in the inverse. Only components with bindings are invertible for non-square matrices.
as_basis_transform()
¶
Return as plain BasisTransform (loses binding information).
Useful for interoperability with code expecting BasisTransform.
Basis
¶
An ordered collection of basis components defining a coordinate system.
A Basis defines the dimensional coordinate system for a set of units. Components are indexed by both name and symbol for flexible lookup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
A descriptive name for the basis (e.g., "SI", "CGS", "Mechanics"). |
required |
components
|
Sequence[str | BasisComponent]
|
Sequence of component names (str) or BasisComponent objects. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If component names or symbols collide. |
Examples:
>>> mechanics = Basis("Mechanics", ["length", "mass", "time"])
>>> len(mechanics)
3
>>> "length" in mechanics
True
>>> mechanics.index("length")
0
>>> si = Basis("SI", [
... BasisComponent("length", "L"),
... BasisComponent("mass", "M"),
... BasisComponent("time", "T"),
... ])
>>> "L" in si
True
>>> si.index("L")
0
name
property
¶
The descriptive name of this basis.
component_names
property
¶
Tuple of component names in order.
index(name)
¶
Return the index of a component by name or symbol.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Component name or symbol to look up. |
required |
Returns:
| Type | Description |
|---|---|
int
|
The zero-based index of the component. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If name/symbol is not found in this basis. |
BasisComponent
dataclass
¶
An atomic generator of a dimensional basis.
A BasisComponent represents a single independent dimension in a basis, such as "length", "mass", or "time" in SI, or custom dimensions like "mana" or "gold" in a game domain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The canonical name of the component (e.g., "length"). |
required |
symbol
|
str | None
|
Optional short symbol (e.g., "L"). If None, name is used. |
None
|
Examples:
>>> length = BasisComponent("length", "L")
>>> str(length)
'L'
>>> mass = BasisComponent("mass")
>>> str(mass)
'mass'
BasisMismatch
¶
Bases: ValueError
Raised when a same-basis Vector operation receives operands in different bases.
Vector arithmetic is strict same-basis. Cross-basis arithmetic must
go through :mod:ucon.basis.ops, which consults a BasisGraph for a
clean (non-lossy) projection.
Subclasses :class:ValueError so legacy except ValueError and
regex-matched pytest.raises(ValueError, ...) sites continue to
catch it.
Parameters¶
message : str
Human-readable description.
left, right : Basis, optional
The two bases that failed to unify.
op : str, optional
The operation that triggered the mismatch (e.g., "multiply",
"divide", "unify").
LossyProjection
¶
Bases: Exception
Raised when a basis transform would discard dimensional information.
This occurs when a source component has a non-zero exponent but maps entirely to zeros in the target basis (e.g., SI current -> CGS).
NoTransformPath
¶
Bases: Exception
Raised when no path exists between two bases in a BasisGraph.
Vector
dataclass
¶
A dimensional exponent vector tied to a specific basis.
Vector represents a point in dimensional space, where each component is the exponent of the corresponding basis component. For example, velocity (length/time) in SI would be Vector(SI, (1, 0, -1, 0, 0, 0, 0, 0)).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
basis
|
Basis
|
The Basis this vector belongs to. |
required |
components
|
tuple[int | Fraction, ...]
|
Tuple of Fraction exponents, one per basis component. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If components length doesn't match basis length. |
zero(basis)
classmethod
¶
Create a zero (dimensionless) vector in the given basis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
basis
|
Basis
|
The basis to create the zero vector against. |
required |
Returns:
| Type | Description |
|---|---|
'Vector'
|
A Vector with all components set to |
__getitem__(key)
¶
Get a component by name, symbol, or index.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
str | int
|
Component name, symbol, or integer index. |
required |
Returns:
| Type | Description |
|---|---|
Fraction
|
The Fraction exponent for that component. |
is_dimensionless()
¶
Return True if all exponents are zero.
__mul__(other)
¶
Multiply dimensions (add exponents). Strict same-basis.
Raises¶
BasisMismatch
If self and other are in different bases. Use
:func:ucon.basis.ops.multiply_via for cross-basis multiplication.
__truediv__(other)
¶
Divide dimensions (subtract exponents). Strict same-basis.
Raises¶
BasisMismatch
If self and other are in different bases. Use
:func:ucon.basis.ops.divide_via for cross-basis division.
__pow__(exponent)
¶
Raise dimension to a power (multiply all exponents).
__neg__()
¶
Negate all exponents (reciprocal dimension).