pub struct LinearOperator<T, V>{
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 implementingTensorLikeV- 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>
impl<T, V> LinearOperator<T, V>
Sourcepub fn new(
mpo: TreeTN<T, V>,
input_mapping: HashMap<V, IndexMapping<T::Index>>,
output_mapping: HashMap<V, IndexMapping<T::Index>>,
) -> Self
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 IDsinput_mapping- Mapping from true input indices to internal indicesoutput_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);Sourcepub fn from_mpo_and_state(
mpo: TreeTN<T, V>,
state: &TreeTN<T, V>,
) -> Result<Self>
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 = bwithspace(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.
Sourcepub fn apply_local(&self, local_tensor: &T, region: &[V]) -> Result<T>
pub fn apply_local(&self, local_tensor: &T, region: &[V]) -> Result<T>
Sourcepub fn get_input_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>
pub fn get_input_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>
Get input mapping for a node.
Sourcepub fn get_output_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>
pub fn get_output_mapping(&self, node: &V) -> Option<&IndexMapping<T::Index>>
Get output mapping for a node.
Sourcepub fn set_input_space_from_state(&mut self, state: &TreeTN<T, V>) -> Result<()>
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.
Sourcepub fn set_output_space_from_state(
&mut self,
state: &TreeTN<T, V>,
) -> Result<()>
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.
Sourcepub fn align_to_state(&mut self, state: &TreeTN<T, V>) -> Result<()>
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));Sourcepub fn transpose(self) -> Self
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>
impl<T, V> LinearOperator<T, V>
Sourcepub fn input_site_indices(&self) -> HashSet<T::Index>
pub fn input_site_indices(&self) -> HashSet<T::Index>
Get all input site indices (true indices from state space).
Sourcepub fn output_site_indices(&self) -> HashSet<T::Index>
pub fn output_site_indices(&self) -> HashSet<T::Index>
Get all output site indices (true indices from result space).
Sourcepub fn input_mappings(&self) -> &HashMap<V, IndexMapping<T::Index>>
pub fn input_mappings(&self) -> &HashMap<V, IndexMapping<T::Index>>
Get all input mappings.
Sourcepub fn output_mappings(&self) -> &HashMap<V, IndexMapping<T::Index>>
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>
impl<T, V> Clone for LinearOperator<T, V>
Source§fn clone(&self) -> LinearOperator<T, V>
fn clone(&self) -> LinearOperator<T, V>
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<T, V> Debug for LinearOperator<T, V>
impl<T, V> Debug for LinearOperator<T, V>
Source§impl<T, V> Operator<T, V> for LinearOperator<T, V>
impl<T, V> Operator<T, V> for LinearOperator<T, V>
Source§fn site_indices(&self) -> HashSet<T::Index>
fn site_indices(&self) -> HashSet<T::Index>
Source§fn site_index_network(&self) -> &SiteIndexNetwork<V, T::Index>
fn site_index_network(&self) -> &SiteIndexNetwork<V, T::Index>
Source§fn node_names(&self) -> HashSet<V>
fn node_names(&self) -> HashSet<V>
Source§impl<T, V> TensorIndex for LinearOperator<T, V>
impl<T, V> TensorIndex for LinearOperator<T, V>
Source§fn external_indices(&self) -> Vec<Self::Index>
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>
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>
fn replaceinds( &self, old_indices: &[Self::Index], new_indices: &[Self::Index], ) -> Result<Self>
Replace multiple external indices.
Source§fn num_external_indices(&self) -> usize
fn num_external_indices(&self) -> usize
§fn replaceinds_pairs(
&self,
pairs: &[(Self::Index, Self::Index)],
) -> Result<Self, Error>
fn replaceinds_pairs( &self, pairs: &[(Self::Index, Self::Index)], ) -> Result<Self, Error>
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>
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§
§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