pub trait IndexLike:
Clone
+ Eq
+ Hash
+ Debug
+ Send
+ Sync
+ 'static {
type Id: Clone + Eq + Hash + Debug + Send + Sync;
// Required methods
fn id(&self) -> &Self::Id;
fn dim(&self) -> usize;
fn conj_state(&self) -> ConjState;
fn conj(&self) -> Self;
fn sim(&self) -> Self
where Self: Sized;
fn create_dummy_link_pair() -> (Self, Self)
where Self: Sized;
fn product_link(indices: &[Self]) -> Result<Self>
where Self: Sized;
// Provided methods
fn plev(&self) -> i64 { ... }
fn is_contractable(&self, other: &Self) -> bool { ... }
fn same_id(&self, other: &Self) -> bool { ... }
fn has_id(&self, id: &Self::Id) -> bool { ... }
}Expand description
Trait for index-like types that can be used in tensor operations.
This trait abstracts away the identity mechanism of indices, allowing algorithms to work with any index type that provides equality, hashing, and dimension access.
§Design Principles
Idas associated type: Lightweight identifier (conjugate-independent)Eqby object equality: Two indices are equal iff they represent the same object (including ID, dimension, and conjugate state if applicable)dim(): Returns the dimension of the indexconj_state(): Returns the conjugate state (direction) of the index
§Key Properties
Eq: Defines object equality (includes ID, dimension, and conjugate state)Hash: Enables efficient lookup inHashMap<I, ...>/HashSet<I>Clone: Indices are small value types, freely copyableis_contractable(): Determines if two indices can be contracted
§Conjugate State and Contractability
The conj_state() method returns the direction of an index:
Undirected: Directionless index (ITensors.jl-like default)Ket: Ingoing index (QSpace: no trailing*in itag)Bra: Outgoing index (QSpace: trailing*in itag)
Two indices are contractable if:
- They have the same
id()anddim() - Their conjugate states are compatible:
(Ket, Bra)or(Bra, Ket)→ contractable(Undirected, Undirected)→ contractable- Mixed
(Undirected, Ket/Bra)→ not contractable (mixing forbidden)
§Example
use tensor4all_core::{DynIndex, IndexLike};
let i = DynIndex::new_dyn(2);
let j = DynIndex::new_dyn(3);
let k = DynIndex::new_dyn(4);
let a = vec![i.clone(), j.clone()];
let b = vec![j.clone(), k.clone()];
let common: Vec<_> = a.iter().filter(|idx| b.contains(idx)).cloned().collect();
assert_eq!(common, vec![j]);Required Associated Types§
Sourcetype Id: Clone + Eq + Hash + Debug + Send + Sync
type Id: Clone + Eq + Hash + Debug + Send + Sync
Lightweight identifier type (conjugate-independent).
Rule: Contractable indices must have the same ID.
The ID serves as a “pairing key” to identify which legs are intended to contract. In large tensor networks, IDs enable efficient graph-based lookups (O(1) with HashSet/HashMap) to find matching legs across many tensors.
This is separate from dimension/direction checks:
- ID: “intent to pair” (which specific legs should connect)
- dim/ConjState: “mathematical compatibility” (can they actually contract)
Required Methods§
Sourcefn id(&self) -> &Self::Id
fn id(&self) -> &Self::Id
Get the identifier of this index.
The ID is used as the pairing key during contraction.
Contractable indices must have the same ID — this is enforced by is_contractable().
Two indices with the same ID represent the same logical leg (though they may differ in conjugate state for directed indices).
Sourcefn conj_state(&self) -> ConjState
fn conj_state(&self) -> ConjState
Get the conjugate state (direction) of this index.
Returns ConjState::Undirected for directionless indices (ITensors.jl-like default),
or ConjState::Ket/ConjState::Bra for directed indices (QSpace-compatible).
Sourcefn conj(&self) -> Self
fn conj(&self) -> Self
Create the conjugate of this index.
For directed indices, this toggles between Ket and Bra.
For Undirected indices, this returns self unchanged (no-op).
§Returns
A new index with the conjugate state toggled (if directed) or unchanged (if undirected).
Sourcefn sim(&self) -> Selfwhere
Self: Sized,
fn sim(&self) -> Selfwhere
Self: Sized,
Create a similar index with a new identity but the same structure (dimension, tags, etc.).
This is used to create “equivalent” indices that have the same properties but different identities, commonly needed in index replacement operations.
§Returns
A new index with a fresh identity and the same structure as self.
Sourcefn create_dummy_link_pair() -> (Self, Self)where
Self: Sized,
fn create_dummy_link_pair() -> (Self, Self)where
Self: Sized,
Create a pair of contractable dummy indices with dimension 1.
These are used for structural connections that don’t carry quantum numbers, such as connecting components in a tree tensor network.
Both indices will be Undirected and have the same ID, making them contractable.
§Returns
A pair (idx1, idx2) where idx1.is_contractable(&idx2) is true.
Sourcefn product_link(indices: &[Self]) -> Result<Self>where
Self: Sized,
fn product_link(indices: &[Self]) -> Result<Self>where
Self: Sized,
Create a fresh link index representing the tensor-product space of input indices.
Generic algorithms may use this to replace multiple local bond legs by one fused
leg without depending on a concrete index implementation. The returned link must
have a fresh identity and represent the exact tensor-product basis of indices.
Implementations with symmetry or sector metadata should preserve the tensor-product
basis and charge structure when possible. They should return Err if the fused
product link cannot be represented exactly.
§Arguments
indices- Non-empty input indices whose tensor-product space is represented by the output. Typical inputs are link or bond indices being fused into one link.
§Returns
A new index with fresh identity and dimension equal to the checked product of all input dimensions.
§Errors
Returns an error when indices is empty, when the product dimension overflows usize,
or when the implementation cannot represent the exact product-link structure.
§Examples
use tensor4all_core::{DynIndex, IndexLike, TagSetLike};
let a = DynIndex::new_link(2).unwrap();
let b = DynIndex::new_link(3).unwrap();
let product = DynIndex::product_link(&[a.clone(), b.clone()]).unwrap();
assert_eq!(product.dim(), 6);
assert!(product.tags().has_tag("Link"));
assert_ne!(product.id(), a.id());
assert_ne!(product.id(), b.id());Provided Methods§
Sourcefn is_contractable(&self, other: &Self) -> bool
fn is_contractable(&self, other: &Self) -> bool
Check if this index can be contracted with another index.
Two indices are contractable if:
- They have the same
id()anddim() - Their conjugate states are compatible:
(Ket, Bra)or(Bra, Ket)→ contractable(Undirected, Undirected)→ contractable- Mixed
(Undirected, Ket/Bra)→ not contractable (mixing forbidden)
§Default Implementation
The default implementation checks:
- Same ID:
self.id() == other.id() - Same dimension:
self.dim() == other.dim() - Same prime level:
self.plev() == other.plev() - Compatible conjugate states (see rules above)
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.