tensor4all_simplett/mpo/
site_mpo.rs1use super::error::{MPOError, Result};
7use super::mpo::MPO;
8use super::types::{Tensor4, Tensor4Ops};
9use crate::traits::TTScalar;
10
11#[derive(Debug, Clone)]
16pub struct SiteMPO<T: TTScalar> {
17 tensors: Vec<Tensor4<T>>,
19 center: usize,
21}
22
23impl<T: TTScalar> SiteMPO<T> {
24 pub fn from_mpo(mpo: MPO<T>, center: usize) -> Result<Self> {
26 if mpo.is_empty() {
27 return Err(MPOError::Empty);
28 }
29 if center >= mpo.len() {
30 return Err(MPOError::InvalidCenter {
31 center,
32 max: mpo.len(),
33 });
34 }
35
36 let tensors = mpo.site_tensors().to_vec();
37 let mut result = Self { tensors, center: 0 };
38
39 result.set_center(center)?;
41
42 Ok(result)
43 }
44
45 #[allow(dead_code)]
47 pub(crate) fn from_tensors_unchecked(tensors: Vec<Tensor4<T>>, center: usize) -> Self {
48 Self { tensors, center }
49 }
50
51 pub fn center(&self) -> usize {
53 self.center
54 }
55
56 pub fn len(&self) -> usize {
58 self.tensors.len()
59 }
60
61 pub fn is_empty(&self) -> bool {
63 self.tensors.is_empty()
64 }
65
66 pub fn site_tensor(&self, i: usize) -> &Tensor4<T> {
68 &self.tensors[i]
69 }
70
71 pub fn site_tensor_mut(&mut self, i: usize) -> &mut Tensor4<T> {
73 &mut self.tensors[i]
74 }
75
76 pub fn site_tensors(&self) -> &[Tensor4<T>] {
78 &self.tensors
79 }
80
81 pub fn site_tensors_mut(&mut self) -> &mut [Tensor4<T>] {
83 &mut self.tensors
84 }
85
86 pub fn link_dims(&self) -> Vec<usize> {
88 if self.len() <= 1 {
89 return Vec::new();
90 }
91 (1..self.len())
92 .map(|i| self.tensors[i].left_dim())
93 .collect()
94 }
95
96 pub fn site_dims(&self) -> Vec<(usize, usize)> {
98 self.tensors
99 .iter()
100 .map(|t| (t.site_dim_1(), t.site_dim_2()))
101 .collect()
102 }
103
104 pub fn rank(&self) -> usize {
106 let lds = self.link_dims();
107 if lds.is_empty() {
108 1
109 } else {
110 *lds.iter().max().unwrap_or(&1)
111 }
112 }
113
114 pub fn move_center_left(&mut self) -> Result<()> {
116 if self.center == 0 {
117 return Err(MPOError::InvalidOperation {
118 message: "Cannot move center left from position 0".to_string(),
119 });
120 }
121
122 self.center -= 1;
125 Ok(())
126 }
127
128 pub fn move_center_right(&mut self) -> Result<()> {
130 if self.center >= self.len() - 1 {
131 return Err(MPOError::InvalidOperation {
132 message: "Cannot move center right from last position".to_string(),
133 });
134 }
135
136 self.center += 1;
139 Ok(())
140 }
141
142 pub fn set_center(&mut self, target: usize) -> Result<()> {
144 if target >= self.len() {
145 return Err(MPOError::InvalidCenter {
146 center: target,
147 max: self.len(),
148 });
149 }
150
151 while self.center < target {
152 self.move_center_right()?;
153 }
154 while self.center > target {
155 self.move_center_left()?;
156 }
157
158 Ok(())
159 }
160
161 pub fn into_mpo(self) -> MPO<T> {
163 MPO::from_tensors_unchecked(self.tensors)
164 }
165}
166
167#[cfg(test)]
168mod tests;