pub struct TensorTrain { /* private fields */ }Expand description
Tensor Train with orthogonality tracking.
This type represents a tensor train as a sequence of tensors with tracked orthogonality limits. It is inspired by ITensorMPS.jl but uses 0-indexed sites (Rust convention).
Unlike traditional MPS which assumes one physical index per site, this implementation allows each site to have multiple site indices.
§Orthogonality Tracking
The tensor train tracks orthogonality using ortho_region from the underlying TreeTN:
- When
ortho_regionis empty, no orthogonality is assumed - When
ortho_regioncontains a single site, that site is the orthogonality center
§Implementation
Internally wraps TreeTN<TensorDynLen, usize> where node names are site indices.
This allows reuse of TreeTN’s canonicalization and contraction algorithms.
§Examples
Build a 2-site tensor train and query its properties:
use tensor4all_itensorlike::TensorTrain;
use tensor4all_core::{DynIndex, TensorDynLen, Index};
use tensor4all_core::DynId;
// Site indices and link index
let s0 = Index::new_with_size(DynId(0), 2);
let link = Index::new_with_size(DynId(1), 3);
let s1 = Index::new_with_size(DynId(2), 2);
let t0 = TensorDynLen::from_dense(
vec![s0.clone(), link.clone()],
(0..6).map(|i| i as f64).collect(),
).unwrap();
let t1 = TensorDynLen::from_dense(
vec![link.clone(), s1.clone()],
(0..6).map(|i| i as f64).collect(),
).unwrap();
let tt = TensorTrain::new(vec![t0, t1]).unwrap();
assert_eq!(tt.len(), 2);
assert_eq!(tt.maxbonddim(), 3);
assert!(!tt.is_empty());Implementations§
Source§impl TensorTrain
impl TensorTrain
Sourcepub fn contract(&self, other: &Self, options: &ContractOptions) -> Result<Self>
pub fn contract(&self, other: &Self, options: &ContractOptions) -> Result<Self>
Contract two tensor trains, returning a new tensor train.
This performs element-wise contraction of corresponding sites, similar to MPO-MPO contraction in ITensor.
§Arguments
other- The other tensor train to contract withoptions- Contraction options (method, max_rank, rtol, nhalfsweeps)
§Returns
A new tensor train resulting from the contraction.
§Errors
Returns an error if:
- Either tensor train is empty
- The tensor trains have different lengths
- The contraction algorithm fails
Source§impl TensorTrain
impl TensorTrain
Sourcepub fn linsolve(
&self,
rhs: &Self,
init: Self,
options: &LinsolveOptions,
) -> Result<Self>
pub fn linsolve( &self, rhs: &Self, init: Self, options: &LinsolveOptions, ) -> Result<Self>
Solve (a₀ + a₁ * A) * x = b for x.
self is the operator A, rhs is b, init is the initial guess.
See linsolve for details.
Source§impl TensorTrain
impl TensorTrain
Sourcepub fn new(tensors: Vec<TensorDynLen>) -> Result<Self>
pub fn new(tensors: Vec<TensorDynLen>) -> Result<Self>
Create a new tensor train from a vector of tensors.
The tensor train is created with no assumed orthogonality.
§Arguments
tensors- Vector of tensors representing the tensor train
§Returns
A new tensor train with no orthogonality.
§Errors
Returns an error if the tensors have inconsistent bond dimensions (i.e., the link indices between adjacent tensors don’t match).
Sourcepub fn with_ortho(
tensors: Vec<TensorDynLen>,
llim: i32,
rlim: i32,
canonical_form: Option<CanonicalForm>,
) -> Result<Self>
pub fn with_ortho( tensors: Vec<TensorDynLen>, llim: i32, rlim: i32, canonical_form: Option<CanonicalForm>, ) -> Result<Self>
Create a new tensor train with specified orthogonality center.
This is useful when constructing a tensor train that is already in canonical form.
§Arguments
tensors- Vector of tensors representing the tensor trainllim- Left orthogonality limit (for compatibility; only used to compute center)rlim- Right orthogonality limit (for compatibility; only used to compute center)canonical_form- The method used for canonicalization (if any)
Sourcepub fn llim(&self) -> i32
pub fn llim(&self) -> i32
Left orthogonality limit.
Sites 0..llim are guaranteed to be left-orthogonal.
Returns -1 if no sites are left-orthogonal.
Sourcepub fn rlim(&self) -> i32
pub fn rlim(&self) -> i32
Right orthogonality limit.
Sites rlim..len() are guaranteed to be right-orthogonal.
Returns len() + 1 if no sites are right-orthogonal.
Sourcepub fn ortho_lims(&self) -> Range<usize>
pub fn ortho_lims(&self) -> Range<usize>
Get the orthogonality center range.
Returns the range of sites that may not be orthogonal. If the tensor train is fully left-orthogonal, returns an empty range at the end. If the tensor train is fully right-orthogonal, returns an empty range at the beginning.
Sourcepub fn isortho(&self) -> bool
pub fn isortho(&self) -> bool
Check if the tensor train has a single orthogonality center.
Returns true if there is exactly one site that is not guaranteed to be orthogonal.
Sourcepub fn orthocenter(&self) -> Option<usize>
pub fn orthocenter(&self) -> Option<usize>
Get the orthogonality center (0-indexed).
Returns Some(site) if the tensor train has a single orthogonality center,
None otherwise.
Sourcepub fn canonical_form(&self) -> Option<CanonicalForm>
pub fn canonical_form(&self) -> Option<CanonicalForm>
Get the canonicalization method used.
Sourcepub fn set_canonical_form(&mut self, method: Option<CanonicalForm>)
pub fn set_canonical_form(&mut self, method: Option<CanonicalForm>)
Set the canonicalization method.
Sourcepub fn tensor(&self, site: usize) -> &TensorDynLen
pub fn tensor(&self, site: usize) -> &TensorDynLen
Sourcepub fn tensor_checked(&self, site: usize) -> Result<&TensorDynLen>
pub fn tensor_checked(&self, site: usize) -> Result<&TensorDynLen>
Get a reference to the tensor at the given site.
Returns Err if site >= len().
Sourcepub fn tensor_mut(&mut self, site: usize) -> &mut TensorDynLen
pub fn tensor_mut(&mut self, site: usize) -> &mut TensorDynLen
Sourcepub fn tensors(&self) -> Vec<&TensorDynLen>
pub fn tensors(&self) -> Vec<&TensorDynLen>
Get a reference to all tensors.
Sourcepub fn tensors_mut(&mut self) -> Vec<&mut TensorDynLen>
pub fn tensors_mut(&mut self) -> Vec<&mut TensorDynLen>
Get a mutable reference to all tensors.
Sourcepub fn linkind(&self, i: usize) -> Option<DynIndex>
pub fn linkind(&self, i: usize) -> Option<DynIndex>
Get the link index between sites i and i+1.
Returns None if i >= len() - 1 or if no common index exists.
Sourcepub fn linkinds(&self) -> Vec<DynIndex> ⓘ
pub fn linkinds(&self) -> Vec<DynIndex> ⓘ
Get all link indices.
Returns a vector of length len() - 1 containing the link indices.
Sourcepub fn sim_linkinds(&self) -> Self
pub fn sim_linkinds(&self) -> Self
Create a copy with all link indices replaced by new unique IDs.
This is useful for computing inner products where two tensor trains share link indices. By simulating (replacing) the link indices in one of the tensor trains, they can be contracted over site indices only.
Sourcepub fn siteinds(&self) -> Vec<Vec<DynIndex>>
pub fn siteinds(&self) -> Vec<Vec<DynIndex>>
Get the site indices (non-link indices) for all sites.
For each site, returns a vector of indices that are not shared with adjacent tensors (i.e., the “physical” or “site” indices).
Sourcepub fn bond_dim(&self, i: usize) -> Option<usize>
pub fn bond_dim(&self, i: usize) -> Option<usize>
Get the bond dimension at link i (between sites i and i+1).
Returns None if i >= len() - 1.
Sourcepub fn bond_dims(&self) -> Vec<usize>
pub fn bond_dims(&self) -> Vec<usize>
Get all bond dimensions.
Returns a vector of length len() - 1.
Sourcepub fn maxbonddim(&self) -> usize
pub fn maxbonddim(&self) -> usize
Get the maximum bond dimension.
Sourcepub fn set_tensor(&mut self, site: usize, tensor: TensorDynLen)
pub fn set_tensor(&mut self, site: usize, tensor: TensorDynLen)
Replace the tensor at the given site.
This invalidates orthogonality tracking.
Sourcepub fn orthogonalize(&mut self, site: usize) -> Result<()>
pub fn orthogonalize(&mut self, site: usize) -> Result<()>
Orthogonalize the tensor train to have orthogonality center at the given site.
This function performs a series of factorizations to make the tensor train
canonical with orthogonality center at site.
§Arguments
site- The target site for the orthogonality center (0-indexed)
§Errors
Returns an error if the factorization fails or if the site is out of bounds.
§Examples
use tensor4all_itensorlike::TensorTrain;
use tensor4all_core::{DynIndex, TensorDynLen, Index, DynId};
let s0 = Index::new_with_size(DynId(0), 2);
let link = Index::new_with_size(DynId(1), 3);
let s1 = Index::new_with_size(DynId(2), 2);
let t0 = TensorDynLen::from_dense(
vec![s0.clone(), link.clone()],
(0..6).map(|i| i as f64).collect(),
).unwrap();
let t1 = TensorDynLen::from_dense(
vec![link.clone(), s1.clone()],
(0..6).map(|i| i as f64).collect(),
).unwrap();
let mut tt = TensorTrain::new(vec![t0, t1]).unwrap();
assert!(!tt.isortho());
// Orthogonalize to site 0
tt.orthogonalize(0).unwrap();
assert!(tt.isortho());
assert_eq!(tt.orthocenter(), Some(0));Sourcepub fn orthogonalize_with(
&mut self,
site: usize,
form: CanonicalForm,
) -> Result<()>
pub fn orthogonalize_with( &mut self, site: usize, form: CanonicalForm, ) -> Result<()>
Orthogonalize with a specified canonical form.
§Arguments
site- The target site for the orthogonality center (0-indexed)form- The canonical form to use:Unitary: Uses QR decomposition, each tensor is isometricLU: Uses LU decomposition, one factor has unit diagonalCI: Uses Cross Interpolation
Sourcepub fn truncate(&mut self, options: &TruncateOptions) -> Result<()>
pub fn truncate(&mut self, options: &TruncateOptions) -> Result<()>
Truncate the tensor train bond dimensions.
This delegates to the TreeTN’s truncate_mut method, which performs a two-site sweep with Euler tour traversal for optimal truncation.
Note: The site_range option in TruncateOptions is currently ignored
as the underlying TreeTN truncation operates on the full network.
§Examples
use tensor4all_itensorlike::{TensorTrain, TruncateOptions};
use tensor4all_core::{DynIndex, TensorDynLen, Index, DynId};
// Build a 3-site tensor train with bond dimension 4
let s0 = Index::new_with_size(DynId(0), 2);
let l01 = Index::new_with_size(DynId(1), 4);
let s1 = Index::new_with_size(DynId(2), 2);
let l12 = Index::new_with_size(DynId(3), 4);
let s2 = Index::new_with_size(DynId(4), 2);
let t0 = TensorDynLen::from_dense(
vec![s0.clone(), l01.clone()],
(0..8).map(|i| i as f64).collect(),
).unwrap();
let t1 = TensorDynLen::from_dense(
vec![l01.clone(), s1.clone(), l12.clone()],
(0..32).map(|i| i as f64).collect(),
).unwrap();
let t2 = TensorDynLen::from_dense(
vec![l12.clone(), s2.clone()],
(0..8).map(|i| i as f64).collect(),
).unwrap();
let mut tt = TensorTrain::new(vec![t0, t1, t2]).unwrap();
assert_eq!(tt.maxbonddim(), 4);
// Truncate bond dimension to at most 2
let opts = TruncateOptions::svd().with_max_rank(2);
tt.truncate(&opts).unwrap();
assert!(tt.maxbonddim() <= 2);Sourcepub fn inner(&self, other: &Self) -> AnyScalar
pub fn inner(&self, other: &Self) -> AnyScalar
Compute the inner product (dot product) of two tensor trains.
Computes <self | other> = sum over all indices of conj(self) * other.
Both tensor trains must have the same site indices (same IDs). Link indices may differ between the two tensor trains.
§Examples
use tensor4all_itensorlike::TensorTrain;
use tensor4all_core::{DynIndex, TensorDynLen, Index, DynId, AnyScalar};
// Single-site tensor train with values [1.0, 0.0]
let s0 = Index::new_with_size(DynId(0), 2);
let t = TensorDynLen::from_dense(
vec![s0.clone()],
vec![1.0_f64, 0.0],
).unwrap();
let tt = TensorTrain::new(vec![t]).unwrap();
// <tt | tt> = 1.0^2 + 0.0^2 = 1.0
let result = tt.inner(&tt);
assert!((result.real() - 1.0).abs() < 1e-10);Sourcepub fn norm_squared(&self) -> f64
pub fn norm_squared(&self) -> f64
Compute the squared norm of the tensor train.
Returns <self | self> = ||self||^2.
§Note
For linear tensor trains with one site index per site, this uses a specialized chain contraction instead of the generic inner-product path. Due to numerical errors, the final scalar can be very slightly negative, so the returned value is clamped to be non-negative.
Sourcepub fn norm(&self) -> f64
pub fn norm(&self) -> f64
Compute the norm of the tensor train.
Returns ||self|| = sqrt(<self | self>).
Sourcepub fn to_dense(&self) -> Result<TensorDynLen>
pub fn to_dense(&self) -> Result<TensorDynLen>
Convert the tensor train to a single dense tensor.
This contracts all tensors in the train along their link indices, producing a single tensor with only site indices.
§Warning
This operation can be very expensive for large tensor trains, as the result size grows exponentially with the number of sites.
§Returns
A single tensor containing all site indices, or an error if the tensor train is empty.
§Example
use tensor4all_core::{DynIndex, TensorDynLen};
use tensor4all_itensorlike::TensorTrain;
let s0 = DynIndex::new_dyn(2);
let link = DynIndex::new_dyn(1);
let s1 = DynIndex::new_dyn(2);
let t0 = TensorDynLen::from_dense(vec![s0.clone(), link.clone()], vec![1.0, 2.0])?;
let t1 = TensorDynLen::from_dense(vec![link.clone(), s1.clone()], vec![3.0, 4.0])?;
let tt = TensorTrain::new(vec![t0, t1])?;
let dense = tt.to_dense()?;
assert_eq!(dense.dims(), vec![2, 2]);
assert_eq!(dense.to_vec::<f64>()?, vec![3.0, 6.0, 4.0, 8.0]);Sourcepub fn add(&self, other: &Self) -> Result<Self>
pub fn add(&self, other: &Self) -> Result<Self>
Add two tensor trains using direct-sum construction.
This creates a new tensor train where each tensor is the direct sum of the corresponding tensors from self and other, with bond dimensions merged. The result has bond dimensions equal to the sum of the input bond dimensions.
§Arguments
other- The other tensor train to add
§Returns
A new tensor train representing the sum.
§Errors
Returns an error if the tensor trains have incompatible structures.
Sourcepub fn scale(&self, scalar: AnyScalar) -> Result<Self>
pub fn scale(&self, scalar: AnyScalar) -> Result<Self>
Scale the tensor train by a scalar.
Only one tensor (the first non-empty site) is scaled to avoid scalar^n scaling. This is correct because the tensor train represents a product of tensors, so scaling one factor scales the entire product.
§Arguments
scalar- The scalar to multiply by
§Returns
A new tensor train scaled by the given scalar.
§Example
use tensor4all_core::{AnyScalar, DynIndex, TensorDynLen};
use tensor4all_itensorlike::TensorTrain;
let s0 = DynIndex::new_dyn(2);
let tt = TensorTrain::new(vec![TensorDynLen::from_dense(
vec![s0.clone()],
vec![1.0, 2.0],
)?])?;
let scaled = tt.scale(AnyScalar::new_real(2.0))?;
assert_eq!(scaled.to_dense()?.to_vec::<f64>()?, vec![2.0, 4.0]);Sourcepub fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>
pub fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>
Compute a linear combination: a * self + b * other.
This is equivalent to self.scale(a)?.add(&other.scale(b)?).
§Arguments
a- Scalar coefficient for selfother- The other tensor trainb- Scalar coefficient for other
§Returns
A new tensor train representing a * self + b * other.
§Note
The bond dimension of the result is the sum of the bond dimensions of the two input tensor trains (before any truncation).
Trait Implementations§
Source§impl Clone for TensorTrain
impl Clone for TensorTrain
Source§fn clone(&self) -> TensorTrain
fn clone(&self) -> TensorTrain
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for TensorTrain
impl Debug for TensorTrain
Source§impl Default for TensorTrain
impl Default for TensorTrain
Source§impl TensorIndex for TensorTrain
impl TensorIndex for TensorTrain
Source§fn external_indices(&self) -> Vec<Self::Index>
fn external_indices(&self) -> Vec<Self::Index>
Source§fn num_external_indices(&self) -> usize
fn num_external_indices(&self) -> usize
Source§fn replaceind(&self, old: &Self::Index, new: &Self::Index) -> Result<Self>
fn replaceind(&self, old: &Self::Index, new: &Self::Index) -> Result<Self>
Source§impl TensorLike for TensorTrain
impl TensorLike for TensorTrain
Source§fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>
fn axpby(&self, a: AnyScalar, other: &Self, b: AnyScalar) -> Result<Self>
a * self + b * other. Read moreSource§fn inner_product(&self, other: &Self) -> Result<AnyScalar>
fn inner_product(&self, other: &Self) -> Result<AnyScalar>
Source§fn norm_squared(&self) -> f64
fn norm_squared(&self) -> f64
Source§fn factorize(
&self,
_left_inds: &[Self::Index],
_options: &FactorizeOptions,
) -> Result<FactorizeResult<Self>, FactorizeError>
fn factorize( &self, _left_inds: &[Self::Index], _options: &FactorizeOptions, ) -> Result<FactorizeResult<Self>, FactorizeError>
Source§fn contract(_tensors: &[&Self], _allowed: AllowedPairs<'_>) -> Result<Self>
fn contract(_tensors: &[&Self], _allowed: AllowedPairs<'_>) -> Result<Self>
Source§fn contract_connected(
_tensors: &[&Self],
_allowed: AllowedPairs<'_>,
) -> Result<Self>
fn contract_connected( _tensors: &[&Self], _allowed: AllowedPairs<'_>, ) -> Result<Self>
Source§fn direct_sum(
&self,
_other: &Self,
_pairs: &[(Self::Index, Self::Index)],
) -> Result<DirectSumResult<Self>>
fn direct_sum( &self, _other: &Self, _pairs: &[(Self::Index, Self::Index)], ) -> Result<DirectSumResult<Self>>
Source§fn outer_product(&self, _other: &Self) -> Result<Self>
fn outer_product(&self, _other: &Self) -> Result<Self>
Source§fn permuteinds(&self, _new_order: &[Self::Index]) -> Result<Self>
fn permuteinds(&self, _new_order: &[Self::Index]) -> Result<Self>
Source§fn diagonal(input: &Self::Index, output: &Self::Index) -> Result<Self>
fn diagonal(input: &Self::Index, output: &Self::Index) -> Result<Self>
Source§fn scalar_one() -> Result<Self>
fn scalar_one() -> Result<Self>
Source§fn ones(indices: &[Self::Index]) -> Result<Self>
fn ones(indices: &[Self::Index]) -> Result<Self>
Source§fn onehot(index_vals: &[(Self::Index, usize)]) -> Result<Self>
fn onehot(index_vals: &[(Self::Index, usize)]) -> Result<Self>
Source§fn sub(&self, other: &Self) -> Result<Self, Error>
fn sub(&self, other: &Self) -> Result<Self, Error>
self - other. Read moreSource§fn isapprox(&self, other: &Self, atol: f64, rtol: f64) -> bool
fn isapprox(&self, other: &Self, atol: f64, rtol: f64) -> bool
isapprox semantics). Read moreAuto Trait Implementations§
impl Freeze for TensorTrain
impl RefUnwindSafe for TensorTrain
impl Send for TensorTrain
impl Sync for TensorTrain
impl Unpin for TensorTrain
impl UnsafeUnpin for TensorTrain
impl UnwindSafe for TensorTrain
Blanket Implementations§
§impl<U> As for U
impl<U> As for U
§fn as_<T>(self) -> Twhere
T: CastFrom<U>,
fn as_<T>(self) -> Twhere
T: CastFrom<U>,
self to type T. The semantics of numeric casting with the as operator are followed, so <T as As>::as_::<U> can be used in the same way as T as U for numeric conversions. Read moreSource§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> Twhere
Self: Distribution<T>,
§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> Twhere
Self: Distribution<T>,
§impl<T> DistributionExt for Twhere
T: ?Sized,
impl<T> DistributionExt for Twhere
T: ?Sized,
fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> Twhere
Self: Distribution<T>,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more