Skip to main content

LinearOperator

Struct LinearOperator 

Source
pub struct LinearOperator<T, V>
where T: TensorLike, V: Clone + Hash + Eq + Send + Sync + Debug,
{ pub mpo: TreeTN<T, V>, pub input_mapping: HashMap<V, IndexMapping<T::Index>>, pub output_mapping: HashMap<V, IndexMapping<T::Index>>, }
Expand description

LinearOperator: Wraps an MPO with index mapping for automatic transformations.

§Type Parameters

  • T - Tensor type implementing TensorLike
  • V - Node name type

§Examples

A LinearOperator is typically obtained from a constructor function rather than built directly. The mpo field contains the underlying TreeTN:

use tensor4all_treetn::LinearOperator;
use tensor4all_core::{DynIndex, TensorDynLen, TensorLike};
use tensor4all_treetn::TreeTN;
use std::collections::HashMap;

// Build a trivial single-node LinearOperator wrapping a 2x2 identity
let s_in = DynIndex::new_dyn(2);
let s_out = DynIndex::new_dyn(2);
let t = TensorDynLen::from_dense(
    vec![s_in.clone(), s_out.clone()],
    vec![1.0_f64, 0.0, 0.0, 1.0],
).unwrap();

let mpo = TreeTN::<_, usize>::from_tensors(vec![t], vec![0]).unwrap();
assert_eq!(mpo.node_count(), 1);

Fields§

§mpo: TreeTN<T, V>

The MPO with internal index IDs

§input_mapping: HashMap<V, IndexMapping<T::Index>>

Input index mapping: node -> (true s_in, internal s_in_tmp)

§output_mapping: HashMap<V, IndexMapping<T::Index>>

Output index mapping: node -> (true s_out, internal s_out_tmp)

Implementations§

Source§

impl<T, V> LinearOperator<T, V>
where T: TensorLike, T::Index: IndexLike, <T::Index as IndexLike>::Id: Clone + Hash + Eq + Ord + Debug + Send + Sync, V: Clone + Hash + Eq + Ord + Send + Sync + Debug,

Source

pub fn new( mpo: TreeTN<T, V>, input_mapping: HashMap<V, IndexMapping<T::Index>>, output_mapping: HashMap<V, IndexMapping<T::Index>>, ) -> Self

Create a new LinearOperator from an MPO and index mappings.

§Arguments
  • mpo - The MPO with internal index IDs
  • input_mapping - Mapping from true input indices to internal indices
  • output_mapping - Mapping from true output indices to internal indices
§Examples
use std::collections::HashMap;
use tensor4all_core::{DynIndex, TensorDynLen, TensorLike};
use tensor4all_treetn::{IndexMapping, LinearOperator, TreeTN};

// Build a 2x2 identity operator (single node)
let site = DynIndex::new_dyn(2);
let s_in = DynIndex::new_dyn(2);
let s_out = DynIndex::new_dyn(2);
let mpo_tensor = TensorDynLen::from_dense(
    vec![s_in.clone(), s_out.clone()],
    vec![1.0_f64, 0.0, 0.0, 1.0],
).unwrap();
let mpo = TreeTN::<_, usize>::from_tensors(vec![mpo_tensor], vec![0]).unwrap();

let mut input_mapping = HashMap::new();
input_mapping.insert(0usize, IndexMapping { true_index: site.clone(), internal_index: s_in });
let mut output_mapping = HashMap::new();
output_mapping.insert(0usize, IndexMapping { true_index: site.clone(), internal_index: s_out });

let op = LinearOperator::new(mpo, input_mapping, output_mapping);
assert_eq!(op.mpo().node_count(), 1);
Source

pub fn from_mpo_and_state( mpo: TreeTN<T, V>, state: &TreeTN<T, V>, ) -> Result<Self>

Create a LinearOperator from an MPO and a reference state.

This assumes:

  • The MPO has site indices that we need to map
  • The state’s site indices define the true input space
  • For A * x = b with space(x) = space(b), the output space equals input space
§Arguments
  • mpo - The MPO (operator A)
  • state - Reference state (defines the true site index space)
§Returns

A LinearOperator with proper index mappings, or an error if structure is incompatible.

Source

pub fn apply_local(&self, local_tensor: &T, region: &[V]) -> Result<T>

Apply the operator to a local tensor at a specific region.

This is used during the sweep for local updates.

§Arguments
  • local_tensor - The local tensor (merged tensors from the region)
  • region - The nodes in the current region
§Returns

The result of applying the operator to the local tensor.

Source

pub fn mpo(&self) -> &TreeTN<T, V>

Get the internal MPO.

Source

pub fn get_input_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>

Get input mapping for a node.

Source

pub fn get_output_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>

Get output mapping for a node.

Source

pub fn set_input_space_from_state(&mut self, state: &TreeTN<T, V>) -> Result<()>

Reset true input indices to match the given state’s site space.

This only rewrites the external mapping. The internal MPO indices are unchanged.

Source

pub fn set_output_space_from_state( &mut self, state: &TreeTN<T, V>, ) -> Result<()>

Reset true output indices to match the given state’s site space.

This only rewrites the external mapping. The internal MPO indices are unchanged.

Source

pub fn align_to_state(&mut self, state: &TreeTN<T, V>) -> Result<()>

Align this operator’s input and output site index mappings to match a target state.

For each node in the operator’s input and output mappings, the true_index is updated to the corresponding site index from the target state. The internal MPO indices remain unchanged.

This is useful when an operator (e.g., from shift_operator or affine_operator) was constructed with its own site indices, but needs to be applied to a state that has different site index IDs. After calling align_to_state, the operator’s true_index fields will reference the state’s site indices, enabling correct index contraction during apply_local.

§Arguments
  • state - The target state whose site indices define the true index space. Each node in the operator’s mappings must exist in the state with exactly one site index of matching dimension.
§Errors

Returns an error if:

  • A node in the operator’s mapping is not found in the state
  • A node in the state has more than one site index
  • The dimension of the state’s site index does not match the operator’s internal index
§Examples
use std::collections::HashMap;

use tensor4all_core::{DynIndex, IndexLike, TensorDynLen};
use tensor4all_treetn::{IndexMapping, LinearOperator, TreeTN};

let state_index = DynIndex::new_dyn(2);
let state_tensor = TensorDynLen::from_dense(vec![state_index.clone()], vec![1.0, 2.0]).unwrap();
let state = TreeTN::<TensorDynLen, usize>::from_tensors(vec![state_tensor], vec![0]).unwrap();

let input_internal = DynIndex::new_dyn(2);
let output_internal = DynIndex::new_dyn(2);
let mpo_tensor = TensorDynLen::from_dense(
    vec![input_internal.clone(), output_internal.clone()],
    vec![1.0, 0.0, 0.0, 1.0],
).unwrap();
let mpo = TreeTN::<TensorDynLen, usize>::from_tensors(vec![mpo_tensor], vec![0]).unwrap();

let mut input_mapping = HashMap::new();
input_mapping.insert(
    0usize,
    IndexMapping {
        true_index: DynIndex::new_dyn(2),
        internal_index: input_internal,
    },
);
let mut output_mapping = HashMap::new();
output_mapping.insert(
    0usize,
    IndexMapping {
        true_index: DynIndex::new_dyn(2),
        internal_index: output_internal,
    },
);

let mut op = LinearOperator::new(mpo, input_mapping, output_mapping);
op.align_to_state(&state).unwrap();

assert!(op.input_mappings()[&0].true_index.same_id(&state_index));
assert!(op.output_mappings()[&0].true_index.same_id(&state_index));
Source

pub fn transpose(self) -> Self

Returns the transposed operator by swapping input and output mappings.

The pullback of a forward operator is its transpose: if the forward operator realizes the matrix M_{y,x}, the transposed operator realizes M_{x,y}. This method swaps input_mapping and output_mapping without copying the underlying MPO tensors — it is an O(1) operation.

.transpose().transpose() yields an operator equivalent to the original (mappings restored, MPO unchanged).

§Examples
use std::collections::HashMap;
use tensor4all_core::{DynIndex, IndexLike, TensorDynLen};
use tensor4all_treetn::{IndexMapping, LinearOperator, TreeTN};

let site_in = DynIndex::new_dyn(2);
let site_out = DynIndex::new_dyn(3);
let s_in_tmp = DynIndex::new_dyn(2);
let s_out_tmp = DynIndex::new_dyn(3);

let mpo_tensor = TensorDynLen::from_dense(
    vec![s_in_tmp.clone(), s_out_tmp.clone()],
    vec![1.0_f64, 0.0, 0.0, 0.0, 1.0, 0.0],
).unwrap();
let mpo = TreeTN::<_, usize>::from_tensors(vec![mpo_tensor], vec![0]).unwrap();

let mut input_mapping = HashMap::new();
input_mapping.insert(
    0usize,
    IndexMapping { true_index: site_in.clone(), internal_index: s_in_tmp.clone() },
);
let mut output_mapping = HashMap::new();
output_mapping.insert(
    0usize,
    IndexMapping { true_index: site_out.clone(), internal_index: s_out_tmp.clone() },
);

let op = LinearOperator::new(mpo, input_mapping, output_mapping);
let t = op.transpose();

// Input/output mappings are swapped.
assert!(t.input_mapping[&0].true_index.same_id(&site_out));
assert!(t.output_mapping[&0].true_index.same_id(&site_in));
Source§

impl<T, V> LinearOperator<T, V>
where T: TensorLike, T::Index: IndexLike, V: Clone + Hash + Eq + Send + Sync + Debug,

Source

pub fn input_site_indices(&self) -> HashSet<T::Index>

Get all input site indices (true indices from state space).

Source

pub fn output_site_indices(&self) -> HashSet<T::Index>

Get all output site indices (true indices from result space).

Source

pub fn input_mappings(&self) -> &HashMap<V, IndexMapping<T::Index>>

Get all input mappings.

Source

pub fn output_mappings(&self) -> &HashMap<V, IndexMapping<T::Index>>

Get all output mappings.

Trait Implementations§

Source§

impl<T, V> Clone for LinearOperator<T, V>
where T: TensorLike + Clone, V: Clone + Hash + Eq + Send + Sync + Debug + Clone, T::Index: Clone,

Source§

fn clone(&self) -> LinearOperator<T, V>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T, V> Debug for LinearOperator<T, V>
where T: TensorLike + Debug, V: Clone + Hash + Eq + Send + Sync + Debug + Debug, T::Index: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T, V> Operator<T, V> for LinearOperator<T, V>
where T: TensorLike, T::Index: IndexLike + Clone + Hash + Eq, V: Clone + Hash + Eq + Send + Sync + Debug,

Source§

fn site_indices(&self) -> HashSet<T::Index>

Get all site indices this operator acts on. Read more
Source§

fn site_index_network(&self) -> &SiteIndexNetwork<V, T::Index>

Get the site index network describing this operator’s structure. Read more
Source§

fn node_names(&self) -> HashSet<V>

Get the set of node names this operator covers. Read more
Source§

impl<T, V> TensorIndex for LinearOperator<T, V>
where T: TensorLike, T::Index: IndexLike + Clone + Hash + Eq + Debug, <T::Index as IndexLike>::Id: Clone + Hash + Eq + Ord + Debug + Send + Sync, V: Clone + Hash + Eq + Ord + Send + Sync + Debug,

Source§

fn external_indices(&self) -> Vec<Self::Index>

Return all external indices (true input and output indices).

Source§

fn replaceind( &self, old_index: &Self::Index, new_index: &Self::Index, ) -> Result<Self>

Replace an external index (true index) in this operator.

This updates the mapping but does NOT modify the internal MPO tensors.

Source§

fn replaceinds( &self, old_indices: &[Self::Index], new_indices: &[Self::Index], ) -> Result<Self>

Replace multiple external indices.

Source§

type Index = <T as TensorIndex>::Index

The index type used by this object.
Source§

fn num_external_indices(&self) -> usize

Number of external indices. Read more
§

fn replaceinds_pairs( &self, pairs: &[(Self::Index, Self::Index)], ) -> Result<Self, Error>

Replace indices using pairs of (old, new). Read more

Auto Trait Implementations§

§

impl<T, V> Freeze for LinearOperator<T, V>

§

impl<T, V> RefUnwindSafe for LinearOperator<T, V>
where V: RefUnwindSafe, <T as TensorIndex>::Index: RefUnwindSafe, <<T as TensorIndex>::Index as IndexLike>::Id: RefUnwindSafe, T: RefUnwindSafe,

§

impl<T, V> Send for LinearOperator<T, V>

§

impl<T, V> Sync for LinearOperator<T, V>

§

impl<T, V> Unpin for LinearOperator<T, V>
where V: Unpin, <T as TensorIndex>::Index: Unpin, <<T as TensorIndex>::Index as IndexLike>::Id: Unpin, T: Unpin,

§

impl<T, V> UnsafeUnpin for LinearOperator<T, V>

§

impl<T, V> UnwindSafe for LinearOperator<T, V>
where V: UnwindSafe, <T as TensorIndex>::Index: UnwindSafe, <<T as TensorIndex>::Index as IndexLike>::Id: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<U> As for U

§

fn as_<T>(self) -> T
where T: CastFrom<U>,

Casts 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 more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

§

impl<T> ByRef<T> for T

§

fn by_ref(&self) -> &T

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
§

impl<T> DistributionExt for T
where T: ?Sized,

§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

§

impl<T> DistributionExt for T
where T: ?Sized,

§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

§

impl<T> DistributionExt for T
where T: ?Sized,

§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

§

impl<T> MaybeSend for T

§

impl<T> MaybeSendSync for T

§

impl<T> MaybeSync for T