TensorLike

Trait TensorLike 

Source
pub trait TensorLike: TensorIndex {
Show 22 methods // Required methods fn factorize( &self, left_inds: &[<Self as TensorIndex>::Index], options: &FactorizeOptions, ) -> Result<FactorizeResult<Self>, FactorizeError>; fn conj(&self) -> Self; fn direct_sum( &self, other: &Self, pairs: &[(<Self as TensorIndex>::Index, <Self as TensorIndex>::Index)], ) -> Result<DirectSumResult<Self>>; fn outer_product(&self, other: &Self) -> Result<Self>; fn norm_squared(&self) -> f64; fn permuteinds( &self, new_order: &[<Self as TensorIndex>::Index], ) -> Result<Self>; fn contract(tensors: &[&Self], allowed: AllowedPairs<'_>) -> Result<Self>; fn contract_connected( tensors: &[&Self], allowed: AllowedPairs<'_>, ) -> Result<Self>; fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>; fn scale(&self, scalar: AnyScalar) -> Result<Self>; fn inner_product(&self, other: &Self) -> Result<AnyScalar>; fn maxabs(&self) -> f64; fn diagonal( input_index: &<Self as TensorIndex>::Index, output_index: &<Self as TensorIndex>::Index, ) -> Result<Self>; fn scalar_one() -> Result<Self>; fn ones(indices: &[<Self as TensorIndex>::Index]) -> Result<Self>; fn onehot( index_vals: &[(<Self as TensorIndex>::Index, usize)], ) -> Result<Self>; // Provided methods fn norm(&self) -> f64 { ... } fn sub(&self, other: &Self) -> Result<Self> { ... } fn neg(&self) -> Result<Self> { ... } fn isapprox(&self, other: &Self, atol: f64, rtol: f64) -> bool { ... } fn validate(&self) -> Result<()> { ... } fn delta( input_indices: &[<Self as TensorIndex>::Index], output_indices: &[<Self as TensorIndex>::Index], ) -> Result<Self> { ... }
}
Expand description

Trait for tensor-like objects that expose external indices and support contraction.

This trait is fully generic (monomorphic), meaning it does not support trait objects (dyn TensorLike). For heterogeneous tensor collections, use an enum wrapper instead.

§Design Principles

  • Minimal interface: Only external indices and automatic contraction
  • Fully generic: Uses associated type for Index, returns Self
  • Stable ordering: external_indices() returns indices in deterministic order
  • No trait objects: Requires Sized, cannot use dyn TensorLike

§Example

use tensor4all_core::{TensorLike, AllowedPairs};

fn contract_pair<T: TensorLike>(a: &T, b: &T) -> Result<T> {
    T::contract(&[a, b], AllowedPairs::All)
}

§Heterogeneous Collections

For mixing different tensor types, define an enum:

enum TensorNetwork {
    Dense(TensorDynLen),
    MPS(MatrixProductState),
}

§Supertrait

TensorLike extends TensorIndex, which provides:

  • external_indices() - Get all external indices
  • num_external_indices() - Count external indices
  • replaceind() / replaceinds() - Replace indices

This separation allows tensor networks (like TreeTN) to implement index operations without implementing contraction/factorization.

Required Methods§

Source

fn factorize( &self, left_inds: &[<Self as TensorIndex>::Index], options: &FactorizeOptions, ) -> Result<FactorizeResult<Self>, FactorizeError>

Factorize this tensor into left and right factors.

This function dispatches to the appropriate algorithm based on options.alg:

  • SVD: Singular Value Decomposition
  • QR: QR decomposition
  • LU: Rank-revealing LU decomposition
  • CI: Cross Interpolation

The canonical option controls which factor is “canonical”:

  • Canonical::Left: Left factor is orthogonal (SVD/QR) or unit-diagonal (LU/CI)
  • Canonical::Right: Right factor is orthogonal (SVD) or unit-diagonal (LU/CI)
§Arguments
  • left_inds - Indices to place on the left side
  • options - Factorization options
§Returns

A FactorizeResult containing the left and right factors, bond index, singular values (for SVD), and rank.

§Errors

Returns FactorizeError if:

  • The storage type is not supported (only DenseF64 and DenseC64)
  • QR is used with Canonical::Right
  • The underlying algorithm fails
Source

fn conj(&self) -> Self

Tensor conjugate operation.

This is a generalized conjugate operation that depends on the tensor type:

  • For dense tensors (TensorDynLen): element-wise complex conjugate
  • For symmetric tensors: tensor conjugate considering symmetry sectors

This operation is essential for computing inner products and overlaps in tensor network algorithms like fitting.

§Returns

A new tensor representing the tensor conjugate.

Source

fn direct_sum( &self, other: &Self, pairs: &[(<Self as TensorIndex>::Index, <Self as TensorIndex>::Index)], ) -> Result<DirectSumResult<Self>>

Direct sum of two tensors along specified index pairs.

For tensors A and B with indices to be summed specified as pairs, creates a new tensor C where each paired index has dimension = dim_A + dim_B. Non-paired indices must match exactly between A and B (same ID).

§Arguments
  • other - Second tensor
  • pairs - Pairs of (self_index, other_index) to be summed. Each pair creates a new index in the result with dimension = dim(self_index) + dim(other_index).
§Returns

A DirectSumResult containing the result tensor and new indices created for the summed dimensions (one per pair).

§Example
// A has indices [i, j] with dims [2, 3]
// B has indices [i, k] with dims [2, 4]
// If we pair (j, k), result has indices [i, m] with dims [2, 7]
// where m is a new index with dim = 3 + 4 = 7
let result = a.direct_sum(&b, &[(j, k)])?;
Source

fn outer_product(&self, other: &Self) -> Result<Self>

Outer product (tensor product) of two tensors.

Computes the tensor product of self and other, resulting in a tensor with all indices from both tensors. No indices are contracted.

§Arguments
  • other - The other tensor to compute outer product with
§Returns

A new tensor representing the outer product.

§Errors

Returns an error if the tensors have common indices (by ID). Use tensordot for contraction when indices overlap.

Source

fn norm_squared(&self) -> f64

Compute the squared Frobenius norm of the tensor.

The squared Frobenius norm is defined as the sum of squared absolute values of all tensor elements: ||T||_F^2 = sum_i |T_i|^2.

This is used for computing norms in tensor network algorithms, convergence checks, and normalization.

§Returns

The squared Frobenius norm as a non-negative f64.

Source

fn permuteinds( &self, new_order: &[<Self as TensorIndex>::Index], ) -> Result<Self>

Permute tensor indices to match the specified order.

This reorders the tensor’s axes to match the order specified by new_order. The indices in new_order are matched by ID with the tensor’s current indices.

§Arguments
  • new_order - The desired order of indices (matched by ID)
§Returns

A new tensor with permuted indices.

§Errors

Returns an error if:

  • The number of indices doesn’t match
  • An index ID in new_order is not found in the tensor
Source

fn contract(tensors: &[&Self], allowed: AllowedPairs<'_>) -> Result<Self>

Contract multiple tensors over their contractable indices.

This method contracts 2 or more tensors. Pairs of indices that satisfy is_contractable() (same ID, same dimension, compatible ConjState) are contracted based on the allowed parameter.

Handles disconnected tensor graphs automatically by:

  1. Finding connected components based on contractable indices
  2. Contracting each connected component separately
  3. Combining results using outer product
§Arguments
  • tensors - Slice of tensor references to contract (must have length >= 1)
  • allowed - Specifies which tensor pairs can have their indices contracted:
    • AllowedPairs::All: Contract all contractable index pairs (default behavior)
    • AllowedPairs::Specified(&[(i, j)]): Only contract indices between specified tensor pairs
§Returns

A new tensor representing the contracted result. If tensors form disconnected components, they are combined via outer product.

§Behavior by N
  • N=0: Error
  • N=1: Clone of input
  • N>=2: Contract connected components, combine with outer product
§Errors

Returns an error if:

  • No tensors are provided
  • AllowedPairs::Specified contains a pair with no contractable indices
§Example
// Contract all contractable pairs
let result = T::contract(&[&a, &b, &c], AllowedPairs::All)?;

// Only contract between tensor pairs (0,1) and (1,2)
let result = T::contract(&[&a, &b, &c], AllowedPairs::Specified(&[(0, 1), (1, 2)]))?;
Source

fn contract_connected( tensors: &[&Self], allowed: AllowedPairs<'_>, ) -> Result<Self>

Contract multiple tensors that must form a connected graph.

This is the core contraction method that requires all tensors to be connected through contractable indices. Use Self::contract if you want automatic handling of disconnected components via outer product.

§Arguments
  • tensors - Slice of tensor references to contract (must form a connected graph)
  • allowed - Specifies which tensor pairs can have their indices contracted
§Returns

A new tensor representing the contracted result.

§Errors

Returns an error if:

  • No tensors are provided
  • The tensors form a disconnected graph
§Example
// All tensors must be connected through contractable indices
let result = T::contract_connected(&[&a, &b, &c], AllowedPairs::All)?;
Source

fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>

Compute a linear combination: a * self + b * other.

This is the fundamental vector space operation.

Source

fn scale(&self, scalar: AnyScalar) -> Result<Self>

Scalar multiplication.

Source

fn inner_product(&self, other: &Self) -> Result<AnyScalar>

Inner product (dot product) of two tensors.

Computes ⟨self, other⟩ = Σ conj(self)_i * other_i.

Source

fn maxabs(&self) -> f64

Maximum absolute value of all elements (L-infinity norm).

Source

fn diagonal( input_index: &<Self as TensorIndex>::Index, output_index: &<Self as TensorIndex>::Index, ) -> Result<Self>

Create a diagonal (Kronecker delta) tensor for a single index pair.

Creates a 2D tensor T[i, o] where T[i, o] = δ_{i,o} (1 if i==o, 0 otherwise).

§Arguments
  • input_index - Input index
  • output_index - Output index (must have same dimension as input)
§Returns

A 2D tensor with shape [dim, dim] representing the identity matrix.

§Errors

Returns an error if dimensions don’t match.

§Example

For dimension 2:

diagonal(i, o) = [[1, 0], [0, 1]]
Source

fn scalar_one() -> Result<Self>

Create a scalar tensor with value 1.0.

This is used as the identity element for outer products.

Source

fn ones(indices: &[<Self as TensorIndex>::Index]) -> Result<Self>

Create a tensor filled with 1.0 for the given indices.

This is useful for adding indices to tensors via outer product without changing tensor values (since multiplying by 1 is identity).

§Example

To add a dummy index l to tensor T:

let ones = T::ones(&[l])?;
let t_with_l = t.outer_product(&ones)?;
Source

fn onehot(index_vals: &[(<Self as TensorIndex>::Index, usize)]) -> Result<Self>

Create a one-hot tensor with value 1.0 at the specified index positions.

Similar to ITensors.jl’s onehot(i => 1, j => 2).

§Arguments
  • index_vals - Pairs of (Index, 0-indexed position)
§Errors

Returns error if any value >= corresponding index dimension.

Provided Methods§

Source

fn norm(&self) -> f64

Compute the Frobenius norm of the tensor.

Source

fn sub(&self, other: &Self) -> Result<Self>

Element-wise subtraction: self - other.

Indices are automatically permuted to match self’s order via axpby.

Source

fn neg(&self) -> Result<Self>

Negate all elements: -self.

Source

fn isapprox(&self, other: &Self, atol: f64, rtol: f64) -> bool

Approximate equality check (Julia isapprox semantics).

Returns true if ||self - other|| <= max(atol, rtol * max(||self||, ||other||)).

Source

fn validate(&self) -> Result<()>

Validate structural consistency of this tensor.

The default implementation does nothing (always succeeds). Types with internal structure (e.g., [BlockTensor]) can override this to check invariants such as index sharing between blocks.

Source

fn delta( input_indices: &[<Self as TensorIndex>::Index], output_indices: &[<Self as TensorIndex>::Index], ) -> Result<Self>

Create a delta (identity) tensor as outer product of diagonals.

For paired indices (i1, o1), (i2, o2), ..., creates a tensor where: T[i1, o1, i2, o2, ...] = δ_{i1,o1} × δ_{i2,o2} × ...

This is computed as the outer product of individual diagonal tensors.

§Arguments
  • input_indices - Input indices
  • output_indices - Output indices (must have same length and matching dimensions)
§Returns

A tensor representing the identity operator on the given index space.

§Errors

Returns an error if:

  • Number of input and output indices don’t match
  • Dimensions of paired indices don’t match
§Example

For a single index pair with dimension 2:

delta([i], [o]) = [[1, 0], [0, 1]]

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§