Skip to main content

IndexLike

Trait IndexLike 

Source
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

  • Id as associated type: Lightweight identifier (conjugate-independent)
  • Eq by 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 index
  • conj_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 in HashMap<I, ...> / HashSet<I>
  • Clone: Indices are small value types, freely copyable
  • is_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() and dim()
  • 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§

Source

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§

Source

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).

Source

fn dim(&self) -> usize

Get the total dimension (state-space dimension) of the index.

Source

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).

Source

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).

Source

fn sim(&self) -> Self
where 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.

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.

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§

Source

fn plev(&self) -> i64

Get the prime level of this index. Default: 0 (unprimed).

Source

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() and dim()
  • 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:

  1. Same ID: self.id() == other.id()
  2. Same dimension: self.dim() == other.dim()
  3. Same prime level: self.plev() == other.plev()
  4. Compatible conjugate states (see rules above)
Source

fn same_id(&self, other: &Self) -> bool

Check if this index has the same ID as another.

Default implementation compares IDs directly. This is a convenience method for pure ID comparison (does not check contractability).

Source

fn has_id(&self, id: &Self::Id) -> bool

Check if this index has the given ID.

Default implementation compares with the given ID.

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.

Implementors§