Skip to main content

tnc/builders/
peps.rs

1use itertools::iproduct;
2
3use crate::tensornetwork::tensor::{CompositeTensor, LeafTensor};
4
5/// Generate the initial state for an `length` x `depth` PEPS.
6///
7/// # Arguments
8/// * `length` - length of the PEPS
9/// * `depth` - depth of the PEPS
10/// * `physical_dim` - physical dimension of the PEPs
11/// * `virtual_dim` - virtual bond dimension between lattice sites in the PEPs
12///
13/// # Returns
14/// [`CompositeTensor`] of initial state of PEPS
15fn peps_init(length: usize, depth: usize, physical_dim: u64, virtual_dim: u64) -> CompositeTensor {
16    let physical_up = length * depth;
17    let virtual_vertical = (length - 1) * depth;
18    let virtual_horizontal = (depth - 1) * length;
19    let total_edges = physical_up + virtual_vertical + virtual_horizontal;
20
21    let mut tensors = vec![LeafTensor::default(); length * depth];
22
23    // Consider the corners
24    tensors[0] = LeafTensor::new(
25        vec![0, physical_up, physical_up + virtual_vertical],
26        vec![physical_dim, virtual_dim, virtual_dim],
27    );
28    tensors[length - 1] = LeafTensor::new(
29        vec![
30            length - 1,
31            physical_up + length - 2,
32            physical_up + virtual_vertical + length - 1,
33        ],
34        vec![physical_dim, virtual_dim, virtual_dim],
35    );
36    tensors[length * (depth - 1)] = LeafTensor::new(
37        vec![
38            length * (depth - 1),
39            physical_up + (length - 1) * (depth - 1),
40            physical_up + virtual_vertical + length * (depth - 2),
41        ],
42        vec![physical_dim, virtual_dim, virtual_dim],
43    );
44    tensors[length * depth - 1] = LeafTensor::new(
45        vec![
46            length * depth - 1,
47            physical_up + (length - 1) * depth - 1,
48            physical_up + virtual_vertical + length * (depth - 1) - 1,
49        ],
50        vec![physical_dim, virtual_dim, virtual_dim],
51    );
52
53    // Consider the horizontal edges
54    for j in 1..(length - 1) {
55        tensors[j] = LeafTensor::new(
56            vec![
57                j,
58                physical_up + j - 1,
59                physical_up + j,
60                physical_up + virtual_vertical + j,
61            ],
62            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
63        );
64
65        tensors[physical_up - j - 1] = LeafTensor::new(
66            vec![
67                physical_up - j - 1,
68                physical_up + virtual_vertical - j - 1,
69                physical_up + virtual_vertical - j,
70                total_edges - j - 1,
71            ],
72            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
73        );
74    }
75
76    // Consider the vertical edges
77    for i in 1..(depth - 1) {
78        tensors[i * length] = LeafTensor::new(
79            vec![
80                i * length,
81                physical_up + i * (length - 1),
82                physical_up + virtual_vertical + (i - 1) * length,
83                physical_up + virtual_vertical + i * length,
84            ],
85            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
86        );
87
88        tensors[(i + 1) * length - 1] = LeafTensor::new(
89            vec![
90                (i + 1) * length - 1,
91                physical_up + (i + 1) * (length - 1) - 1,
92                physical_up + virtual_vertical + i * length - 1,
93                physical_up + virtual_vertical + (i + 1) * length - 1,
94            ],
95            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
96        );
97    }
98
99    // Consider the remaining bulk not on the edges
100    for (i, j) in iproduct!(1..(depth - 1), 1..(length - 1)) {
101        let index = i * length + j;
102        tensors[index] = LeafTensor::new(
103            vec![
104                index,
105                physical_up + i * (length - 1) + j - 1,
106                physical_up + i * (length - 1) + j,
107                physical_up + virtual_vertical + (i - 1) * length + j,
108                physical_up + virtual_vertical + i * length + j,
109            ],
110            vec![
111                physical_dim,
112                virtual_dim,
113                virtual_dim,
114                virtual_dim,
115                virtual_dim,
116            ],
117        );
118    }
119
120    CompositeTensor::new(tensors)
121}
122
123/// Generate an intermediate PEP-operator an n x n PEPs with shared bond dimension of `dimension`.
124///
125/// # Arguments
126/// * `peps` - [`CompositeTensor`] representing initial PEPS and successive PEPOs
127/// * `length` - length of the PEPS
128/// * `depth` - depth of the PEPS
129/// * `layer` - layer of PEPO to be applied
130/// * `physical_dim` - physical dimension of the PEPs
131/// * `virtual_dim` - virtual bond dimension between lattice sites in the PEPs
132///
133/// # Returns
134/// Updated PEPS [`CompositeTensor`] with `layer`th PEPO applied.
135fn pepo(
136    mut peps: CompositeTensor,
137    length: usize,
138    depth: usize,
139    layer: usize,
140    physical_dim: u64,
141    virtual_dim: u64,
142) -> CompositeTensor {
143    let physical_up = length * depth;
144    let virtual_vertical = (length - 1) * depth;
145    let virtual_horizontal = (depth - 1) * length;
146    let total_edges = physical_up + virtual_vertical + virtual_horizontal;
147    let last = total_edges * layer;
148    let start = total_edges * (layer + 1);
149
150    let mut tensors = vec![LeafTensor::default(); length * depth];
151
152    // Consider the corners
153    tensors[0] = LeafTensor::new(
154        vec![
155            last,
156            start,
157            start + physical_up,
158            start + physical_up + virtual_vertical,
159        ],
160        vec![physical_dim, physical_dim, virtual_dim, virtual_dim],
161    );
162    tensors[length - 1] = LeafTensor::new(
163        vec![
164            last + length - 1,
165            start + length - 1,
166            start + physical_up + length - 2,
167            start + physical_up + virtual_vertical + length - 1,
168        ],
169        vec![physical_dim, physical_dim, virtual_dim, virtual_dim],
170    );
171    tensors[length * (depth - 1)] = LeafTensor::new(
172        vec![
173            last + length * (depth - 1),
174            start + length * (depth - 1),
175            start + physical_up + (length - 1) * (depth - 1),
176            start + physical_up + virtual_vertical + length * (depth - 2),
177        ],
178        vec![physical_dim, physical_dim, virtual_dim, virtual_dim],
179    );
180    tensors[length * depth - 1] = LeafTensor::new(
181        vec![
182            last + length * depth - 1,
183            start + length * depth - 1,
184            start + physical_up + (length - 1) * depth - 1,
185            start + physical_up + virtual_vertical + length * (depth - 1) - 1,
186        ],
187        vec![physical_dim, physical_dim, virtual_dim, virtual_dim],
188    );
189
190    // Consider the horizontal edges
191    for j in 1..(length - 1) {
192        tensors[j] = LeafTensor::new(
193            vec![
194                last + j,
195                start + j,
196                start + physical_up + j - 1,
197                start + physical_up + j,
198                start + physical_up + virtual_vertical + j,
199            ],
200            vec![
201                physical_dim,
202                physical_dim,
203                virtual_dim,
204                virtual_dim,
205                virtual_dim,
206            ],
207        );
208
209        tensors[physical_up - j - 1] = LeafTensor::new(
210            vec![
211                last + physical_up - j - 1,
212                start + physical_up - j - 1,
213                start + physical_up + virtual_vertical - j - 1,
214                start + physical_up + virtual_vertical - j,
215                start + total_edges - j - 1,
216            ],
217            vec![
218                physical_dim,
219                physical_dim,
220                virtual_dim,
221                virtual_dim,
222                virtual_dim,
223            ],
224        );
225    }
226
227    // Consider the vertical edges
228    for i in 1..(depth - 1) {
229        tensors[i * length] = LeafTensor::new(
230            vec![
231                last + i * length,
232                start + i * length,
233                start + physical_up + i * (length - 1),
234                start + physical_up + virtual_vertical + (i - 1) * length,
235                start + physical_up + virtual_vertical + i * length,
236            ],
237            vec![
238                physical_dim,
239                physical_dim,
240                virtual_dim,
241                virtual_dim,
242                virtual_dim,
243            ],
244        );
245
246        tensors[(i + 1) * length - 1] = LeafTensor::new(
247            vec![
248                last + (i + 1) * length - 1,
249                start + (i + 1) * length - 1,
250                start + physical_up + (i + 1) * (length - 1) - 1,
251                start + physical_up + virtual_vertical + i * length - 1,
252                start + physical_up + virtual_vertical + (i + 1) * length - 1,
253            ],
254            vec![
255                physical_dim,
256                physical_dim,
257                virtual_dim,
258                virtual_dim,
259                virtual_dim,
260            ],
261        );
262    }
263
264    // Consider the remaining bulk not on the edges
265    for (i, j) in iproduct!(1..(depth - 1), 1..(length - 1)) {
266        let index = i * length + j;
267        tensors[index] = LeafTensor::new(
268            vec![
269                last + index,
270                start + index,
271                start + physical_up + i * (length - 1) + j - 1,
272                start + physical_up + i * (length - 1) + j,
273                start + physical_up + virtual_vertical + (i - 1) * length + j,
274                start + physical_up + virtual_vertical + i * length + j,
275            ],
276            vec![
277                physical_dim,
278                physical_dim,
279                virtual_dim,
280                virtual_dim,
281                virtual_dim,
282                virtual_dim,
283            ],
284        );
285    }
286    peps.push_tensors(tensors);
287    peps
288}
289
290/// Applies the final state in a PEPS.
291///
292/// # Arguments
293/// * `peps` - [`CompositeTensor`] representing initial PEPS and successive PEPOs
294/// * `length` - length of the PEPS
295/// * `depth` - depth of the PEPS
296/// * `physical_dim` - physical dimension of the PEPs
297/// * `virtual_dim` - virtual bond dimension between lattice sites in the PEPs
298///
299/// # Returns
300/// Updated PEPS [`CompositeTensor`] with final PEPS applied
301fn peps_final(
302    mut peps: CompositeTensor,
303    length: usize,
304    depth: usize,
305    physical_dim: u64,
306    virtual_dim: u64,
307    layers: usize,
308) -> CompositeTensor {
309    let physical_up = length * depth;
310    let virtual_vertical = (length - 1) * depth;
311    let virtual_horizontal = (depth - 1) * length;
312    let mut total_edges = physical_up + virtual_vertical + virtual_horizontal;
313    let last = total_edges * layers;
314    let start = total_edges * (layers + 1);
315    total_edges -= physical_up;
316
317    let mut tensors = vec![LeafTensor::default(); length * depth];
318
319    // Consider the corners
320    tensors[0] = LeafTensor::new(
321        vec![last, start, start + virtual_vertical],
322        vec![physical_dim, virtual_dim, virtual_dim],
323    );
324    tensors[length - 1] = LeafTensor::new(
325        vec![
326            last + length - 1,
327            start + length - 2,
328            start + virtual_vertical + length - 1,
329        ],
330        vec![physical_dim, virtual_dim, virtual_dim],
331    );
332    tensors[length * (depth - 1)] = LeafTensor::new(
333        vec![
334            last + length * (depth - 1),
335            start + (length - 1) * (depth - 1),
336            start + virtual_vertical + length * (depth - 2),
337        ],
338        vec![physical_dim, virtual_dim, virtual_dim],
339    );
340    tensors[length * depth - 1] = LeafTensor::new(
341        vec![
342            last + length * depth - 1,
343            start + (length - 1) * depth - 1,
344            start + virtual_vertical + length * (depth - 1) - 1,
345        ],
346        vec![physical_dim, virtual_dim, virtual_dim],
347    );
348
349    // Consider the horizontal edges
350    for j in 1..(length - 1) {
351        tensors[j] = LeafTensor::new(
352            vec![
353                last + j,
354                start + j - 1,
355                start + j,
356                start + virtual_vertical + j,
357            ],
358            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
359        );
360
361        tensors[physical_up - j - 1] = LeafTensor::new(
362            vec![
363                last + physical_up - j - 1,
364                start + virtual_vertical - j - 1,
365                start + virtual_vertical - j,
366                start + total_edges - j - 1,
367            ],
368            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
369        );
370    }
371
372    // Consider the vertical edges
373    for i in 1..(depth - 1) {
374        tensors[i * length] = LeafTensor::new(
375            vec![
376                last + i * length,
377                start + i * (length - 1),
378                start + virtual_vertical + (i - 1) * length,
379                start + virtual_vertical + i * length,
380            ],
381            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
382        );
383
384        tensors[(i + 1) * length - 1] = LeafTensor::new(
385            vec![
386                last + (i + 1) * length - 1,
387                start + (i + 1) * (length - 1) - 1,
388                start + virtual_vertical + i * length - 1,
389                start + virtual_vertical + (i + 1) * length - 1,
390            ],
391            vec![physical_dim, virtual_dim, virtual_dim, virtual_dim],
392        );
393    }
394
395    // Consider the remaining bulk not on the edges
396    for (i, j) in iproduct!(1..(depth - 1), 1..(length - 1)) {
397        let index = i * length + j;
398        tensors[index] = LeafTensor::new(
399            vec![
400                last + index,
401                start + i * (length - 1) + j - 1,
402                start + i * (length - 1) + j,
403                start + virtual_vertical + (i - 1) * length + j,
404                start + virtual_vertical + i * length + j,
405            ],
406            vec![
407                physical_dim,
408                virtual_dim,
409                virtual_dim,
410                virtual_dim,
411                virtual_dim,
412            ],
413        );
414    }
415    peps.push_tensors(tensors);
416    peps
417}
418
419/// Generates the structure for a PEPS with `length` x `depth` dimensions and with `layers` layers.
420///
421/// The `EdgeIndex` in the PEPS `bond_dims` for each layer is ordered as `physical bonds to previous layer,
422/// physical bonds to next layer, vertical virtual bonds, horizontal virtual bonds`.
423///
424/// Each new layer other than the final layer adds:
425/// * p = length * depth physical bonds
426/// * vv = (length - 1) * depth vertical virtual bonds
427/// * vh = (depth - 1) * length horizontal virtual bonds
428///
429/// Bonds for the `k`th layer, where k is not the initial or final layer, then run from:
430/// * physical bonds to previous layer: (k-1) * (p+vv+vh): (kp) + (k-1) * (vv+vh)
431/// * physical bonds to next layer: k * (p+vv+vh)
432///
433/// # Arguments
434/// * `length` - length of the PEPS
435/// * `depth` - depth of the PEPS
436/// * `physical_dim` - physical dimension of the PEPs
437/// * `virtual_dim` - virtual bond dimension between lattice sites in the PEPs
438/// * `layers` - number of operator layers in PEPS, 0 layers returns an inner product of two states.
439///
440/// # Returns
441/// [`CompositeTensor`] representing a PEPS.
442///
443/// # Panics
444/// Panics if `length < 2` or `depth < 2`.
445#[must_use]
446pub fn peps(
447    length: usize,
448    depth: usize,
449    physical_dim: u64,
450    virtual_dim: u64,
451    layers: usize,
452) -> CompositeTensor {
453    assert!(length > 1, "PEPS should have length greater than 1");
454    assert!(depth > 1, "PEPS should have depth greater than 1");
455    let mut new_peps = peps_init(length, depth, physical_dim, virtual_dim);
456    for layer in 0..layers {
457        new_peps = pepo(new_peps, length, depth, layer, physical_dim, virtual_dim);
458    }
459    peps_final(new_peps, length, depth, physical_dim, virtual_dim, layers)
460}
461
462#[cfg(test)]
463mod tests {
464    use super::*;
465
466    use std::iter::zip;
467
468    use rustc_hash::FxHashMap;
469
470    #[test]
471    fn test_pep_init() {
472        let length = 3;
473        let depth = 3;
474        let physical_dim = 4;
475        let virtual_dim = 10;
476
477        let bond_dims = FxHashMap::from_iter([
478            (0, 4),
479            (1, 4),
480            (2, 4),
481            (3, 4),
482            (4, 4),
483            (5, 4),
484            (6, 4),
485            (7, 4),
486            (8, 4),
487            (9, 10),
488            (10, 10),
489            (11, 10),
490            (12, 10),
491            (13, 10),
492            (14, 10),
493            (15, 10),
494            (16, 10),
495            (17, 10),
496            (18, 10),
497            (19, 10),
498            (20, 10),
499        ]);
500        let tensors = vec![
501            LeafTensor::new_from_map(vec![0, 9, 15], &bond_dims),
502            LeafTensor::new_from_map(vec![1, 9, 10, 16], &bond_dims),
503            LeafTensor::new_from_map(vec![2, 10, 17], &bond_dims),
504            LeafTensor::new_from_map(vec![3, 11, 15, 18], &bond_dims),
505            LeafTensor::new_from_map(vec![4, 11, 12, 16, 19], &bond_dims),
506            LeafTensor::new_from_map(vec![5, 12, 17, 20], &bond_dims),
507            LeafTensor::new_from_map(vec![6, 13, 18], &bond_dims),
508            LeafTensor::new_from_map(vec![7, 13, 14, 19], &bond_dims),
509            LeafTensor::new_from_map(vec![8, 14, 20], &bond_dims),
510        ];
511        let ref_tensor = CompositeTensor::new(tensors);
512
513        let new_peps = peps_init(length, depth, physical_dim, virtual_dim);
514        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
515            let t1 = t1.as_leaf().unwrap();
516            let t2 = t2.as_leaf().unwrap();
517            assert_eq!(t1.legs(), t2.legs());
518            assert_eq!(t1.bond_dims(), t2.bond_dims());
519        }
520    }
521
522    #[test]
523    fn test_pepo() {
524        let length = 3;
525        let depth = 3;
526        let physical_dim = 4;
527        let virtual_dim = 10;
528        let layers = 1;
529
530        let bond_dims = FxHashMap::from_iter([
531            (0, 4),
532            (1, 4),
533            (2, 4),
534            (3, 4),
535            (4, 4),
536            (5, 4),
537            (6, 4),
538            (7, 4),
539            (8, 4),
540            (9, 10),
541            (10, 10),
542            (11, 10),
543            (12, 10),
544            (13, 10),
545            (14, 10),
546            (15, 10),
547            (16, 10),
548            (17, 10),
549            (18, 10),
550            (19, 10),
551            (20, 10),
552            (21, 4),
553            (22, 4),
554            (23, 4),
555            (24, 4),
556            (25, 4),
557            (26, 4),
558            (27, 4),
559            (28, 4),
560            (29, 4),
561            (30, 10),
562            (31, 10),
563            (32, 10),
564            (33, 10),
565            (34, 10),
566            (35, 10),
567            (36, 10),
568            (37, 10),
569            (38, 10),
570            (39, 10),
571            (40, 10),
572            (41, 10),
573        ]);
574        let tensors = vec![
575            LeafTensor::new_from_map(vec![0, 9, 15], &bond_dims),
576            LeafTensor::new_from_map(vec![1, 9, 10, 16], &bond_dims),
577            LeafTensor::new_from_map(vec![2, 10, 17], &bond_dims),
578            LeafTensor::new_from_map(vec![3, 11, 15, 18], &bond_dims),
579            LeafTensor::new_from_map(vec![4, 11, 12, 16, 19], &bond_dims),
580            LeafTensor::new_from_map(vec![5, 12, 17, 20], &bond_dims),
581            LeafTensor::new_from_map(vec![6, 13, 18], &bond_dims),
582            LeafTensor::new_from_map(vec![7, 13, 14, 19], &bond_dims),
583            LeafTensor::new_from_map(vec![8, 14, 20], &bond_dims),
584            LeafTensor::new_from_map(vec![0, 21, 30, 36], &bond_dims),
585            LeafTensor::new_from_map(vec![1, 22, 30, 31, 37], &bond_dims),
586            LeafTensor::new_from_map(vec![2, 23, 31, 38], &bond_dims),
587            LeafTensor::new_from_map(vec![3, 24, 32, 36, 39], &bond_dims),
588            LeafTensor::new_from_map(vec![4, 25, 32, 33, 37, 40], &bond_dims),
589            LeafTensor::new_from_map(vec![5, 26, 33, 38, 41], &bond_dims),
590            LeafTensor::new_from_map(vec![6, 27, 34, 39], &bond_dims),
591            LeafTensor::new_from_map(vec![7, 28, 34, 35, 40], &bond_dims),
592            LeafTensor::new_from_map(vec![8, 29, 35, 41], &bond_dims),
593        ];
594        let ref_tensor = CompositeTensor::new(tensors);
595
596        let mut new_peps = peps_init(length, depth, physical_dim, virtual_dim);
597        for layer in 0..layers {
598            new_peps = pepo(new_peps, length, depth, layer, physical_dim, virtual_dim);
599        }
600
601        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
602            let t1 = t1.as_leaf().unwrap();
603            let t2 = t2.as_leaf().unwrap();
604            assert_eq!(t1.legs(), t2.legs());
605            assert_eq!(t1.bond_dims(), t2.bond_dims());
606        }
607    }
608
609    #[test]
610    fn test_peps_final() {
611        let length = 3;
612        let depth = 3;
613        let physical_dim = 4;
614        let virtual_dim = 10;
615        let layers = 1;
616
617        let bond_dims = FxHashMap::from_iter([
618            (0, 4),
619            (1, 4),
620            (2, 4),
621            (3, 4),
622            (4, 4),
623            (5, 4),
624            (6, 4),
625            (7, 4),
626            (8, 4),
627            (9, 10),
628            (10, 10),
629            (11, 10),
630            (12, 10),
631            (13, 10),
632            (14, 10),
633            (15, 10),
634            (16, 10),
635            (17, 10),
636            (18, 10),
637            (19, 10),
638            (20, 10),
639            (21, 4),
640            (22, 4),
641            (23, 4),
642            (24, 4),
643            (25, 4),
644            (26, 4),
645            (27, 4),
646            (28, 4),
647            (29, 4),
648            (30, 10),
649            (31, 10),
650            (32, 10),
651            (33, 10),
652            (34, 10),
653            (35, 10),
654            (36, 10),
655            (37, 10),
656            (38, 10),
657            (39, 10),
658            (40, 10),
659            (41, 10),
660            (42, 10),
661            (43, 10),
662            (44, 10),
663            (45, 10),
664            (46, 10),
665            (47, 10),
666            (48, 10),
667            (49, 10),
668            (50, 10),
669            (51, 10),
670            (52, 10),
671            (53, 10),
672        ]);
673        let tensors = vec![
674            LeafTensor::new_from_map(vec![0, 9, 15], &bond_dims),
675            LeafTensor::new_from_map(vec![1, 9, 10, 16], &bond_dims),
676            LeafTensor::new_from_map(vec![2, 10, 17], &bond_dims),
677            LeafTensor::new_from_map(vec![3, 11, 15, 18], &bond_dims),
678            LeafTensor::new_from_map(vec![4, 11, 12, 16, 19], &bond_dims),
679            LeafTensor::new_from_map(vec![5, 12, 17, 20], &bond_dims),
680            LeafTensor::new_from_map(vec![6, 13, 18], &bond_dims),
681            LeafTensor::new_from_map(vec![7, 13, 14, 19], &bond_dims),
682            LeafTensor::new_from_map(vec![8, 14, 20], &bond_dims),
683            LeafTensor::new_from_map(vec![0, 21, 30, 36], &bond_dims),
684            LeafTensor::new_from_map(vec![1, 22, 30, 31, 37], &bond_dims),
685            LeafTensor::new_from_map(vec![2, 23, 31, 38], &bond_dims),
686            LeafTensor::new_from_map(vec![3, 24, 32, 36, 39], &bond_dims),
687            LeafTensor::new_from_map(vec![4, 25, 32, 33, 37, 40], &bond_dims),
688            LeafTensor::new_from_map(vec![5, 26, 33, 38, 41], &bond_dims),
689            LeafTensor::new_from_map(vec![6, 27, 34, 39], &bond_dims),
690            LeafTensor::new_from_map(vec![7, 28, 34, 35, 40], &bond_dims),
691            LeafTensor::new_from_map(vec![8, 29, 35, 41], &bond_dims),
692            LeafTensor::new_from_map(vec![21, 42, 48], &bond_dims),
693            LeafTensor::new_from_map(vec![22, 42, 43, 49], &bond_dims),
694            LeafTensor::new_from_map(vec![23, 43, 50], &bond_dims),
695            LeafTensor::new_from_map(vec![24, 44, 48, 51], &bond_dims),
696            LeafTensor::new_from_map(vec![25, 44, 45, 49, 52], &bond_dims),
697            LeafTensor::new_from_map(vec![26, 45, 50, 53], &bond_dims),
698            LeafTensor::new_from_map(vec![27, 46, 51], &bond_dims),
699            LeafTensor::new_from_map(vec![28, 46, 47, 52], &bond_dims),
700            LeafTensor::new_from_map(vec![29, 47, 53], &bond_dims),
701        ];
702        let ref_tensor = CompositeTensor::new(tensors);
703
704        let mut new_peps = peps_init(length, depth, physical_dim, virtual_dim);
705        for layer in 0..layers {
706            new_peps = pepo(new_peps, length, depth, layer, physical_dim, virtual_dim);
707        }
708        let new_peps = peps_final(new_peps, length, depth, physical_dim, virtual_dim, layers);
709        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
710            let t1 = t1.as_leaf().unwrap();
711            let t2 = t2.as_leaf().unwrap();
712            assert_eq!(t1.legs(), t2.legs());
713            assert_eq!(t1.bond_dims(), t2.bond_dims());
714        }
715    }
716
717    #[test]
718    fn test_peps() {
719        let length = 3;
720        let depth = 3;
721        let physical_dim = 4;
722        let virtual_dim = 10;
723        let layers = 1;
724
725        let bond_dims = FxHashMap::from_iter([
726            (0, 4),
727            (1, 4),
728            (2, 4),
729            (3, 4),
730            (4, 4),
731            (5, 4),
732            (6, 4),
733            (7, 4),
734            (8, 4),
735            (9, 10),
736            (10, 10),
737            (11, 10),
738            (12, 10),
739            (13, 10),
740            (14, 10),
741            (15, 10),
742            (16, 10),
743            (17, 10),
744            (18, 10),
745            (19, 10),
746            (20, 10),
747            (21, 4),
748            (22, 4),
749            (23, 4),
750            (24, 4),
751            (25, 4),
752            (26, 4),
753            (27, 4),
754            (28, 4),
755            (29, 4),
756            (30, 10),
757            (31, 10),
758            (32, 10),
759            (33, 10),
760            (34, 10),
761            (35, 10),
762            (36, 10),
763            (37, 10),
764            (38, 10),
765            (39, 10),
766            (40, 10),
767            (41, 10),
768            (42, 10),
769            (43, 10),
770            (44, 10),
771            (45, 10),
772            (46, 10),
773            (47, 10),
774            (48, 10),
775            (49, 10),
776            (50, 10),
777            (51, 10),
778            (52, 10),
779            (53, 10),
780        ]);
781        let tensors = vec![
782            LeafTensor::new_from_map(vec![0, 9, 15], &bond_dims),
783            LeafTensor::new_from_map(vec![1, 9, 10, 16], &bond_dims),
784            LeafTensor::new_from_map(vec![2, 10, 17], &bond_dims),
785            LeafTensor::new_from_map(vec![3, 11, 15, 18], &bond_dims),
786            LeafTensor::new_from_map(vec![4, 11, 12, 16, 19], &bond_dims),
787            LeafTensor::new_from_map(vec![5, 12, 17, 20], &bond_dims),
788            LeafTensor::new_from_map(vec![6, 13, 18], &bond_dims),
789            LeafTensor::new_from_map(vec![7, 13, 14, 19], &bond_dims),
790            LeafTensor::new_from_map(vec![8, 14, 20], &bond_dims),
791            LeafTensor::new_from_map(vec![0, 21, 30, 36], &bond_dims),
792            LeafTensor::new_from_map(vec![1, 22, 30, 31, 37], &bond_dims),
793            LeafTensor::new_from_map(vec![2, 23, 31, 38], &bond_dims),
794            LeafTensor::new_from_map(vec![3, 24, 32, 36, 39], &bond_dims),
795            LeafTensor::new_from_map(vec![4, 25, 32, 33, 37, 40], &bond_dims),
796            LeafTensor::new_from_map(vec![5, 26, 33, 38, 41], &bond_dims),
797            LeafTensor::new_from_map(vec![6, 27, 34, 39], &bond_dims),
798            LeafTensor::new_from_map(vec![7, 28, 34, 35, 40], &bond_dims),
799            LeafTensor::new_from_map(vec![8, 29, 35, 41], &bond_dims),
800            LeafTensor::new_from_map(vec![21, 42, 48], &bond_dims),
801            LeafTensor::new_from_map(vec![22, 42, 43, 49], &bond_dims),
802            LeafTensor::new_from_map(vec![23, 43, 50], &bond_dims),
803            LeafTensor::new_from_map(vec![24, 44, 48, 51], &bond_dims),
804            LeafTensor::new_from_map(vec![25, 44, 45, 49, 52], &bond_dims),
805            LeafTensor::new_from_map(vec![26, 45, 50, 53], &bond_dims),
806            LeafTensor::new_from_map(vec![27, 46, 51], &bond_dims),
807            LeafTensor::new_from_map(vec![28, 46, 47, 52], &bond_dims),
808            LeafTensor::new_from_map(vec![29, 47, 53], &bond_dims),
809        ];
810        let ref_tensor = CompositeTensor::new(tensors);
811
812        let new_peps = peps(length, depth, physical_dim, virtual_dim, layers);
813        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
814            let t1 = t1.as_leaf().unwrap();
815            let t2 = t2.as_leaf().unwrap();
816            assert_eq!(t1.legs(), t2.legs());
817            assert_eq!(t1.bond_dims(), t2.bond_dims());
818        }
819    }
820
821    #[test]
822    fn test_inner_product() {
823        let length = 2;
824        let depth = 2;
825        let physical_dim = 4;
826        let virtual_dim = 10;
827        let layers = 0;
828
829        let bond_dims = FxHashMap::from_iter([
830            (0, 4),
831            (1, 4),
832            (2, 4),
833            (3, 4),
834            (4, 10),
835            (5, 10),
836            (6, 10),
837            (7, 10),
838            (8, 10),
839            (9, 10),
840            (10, 10),
841            (11, 10),
842        ]);
843        let tensors = vec![
844            LeafTensor::new_from_map(vec![0, 4, 6], &bond_dims),
845            LeafTensor::new_from_map(vec![1, 4, 7], &bond_dims),
846            LeafTensor::new_from_map(vec![2, 5, 6], &bond_dims),
847            LeafTensor::new_from_map(vec![3, 5, 7], &bond_dims),
848            LeafTensor::new_from_map(vec![0, 8, 10], &bond_dims),
849            LeafTensor::new_from_map(vec![1, 8, 11], &bond_dims),
850            LeafTensor::new_from_map(vec![2, 9, 10], &bond_dims),
851            LeafTensor::new_from_map(vec![3, 9, 11], &bond_dims),
852        ];
853        let ref_tensor = CompositeTensor::new(tensors);
854
855        let mut new_peps = peps_init(length, depth, physical_dim, virtual_dim);
856        for layer in 0..layers {
857            new_peps = pepo(new_peps, length, depth, layer, physical_dim, virtual_dim);
858        }
859        let new_peps = peps_final(new_peps, length, depth, physical_dim, virtual_dim, layers);
860        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
861            let t1 = t1.as_leaf().unwrap();
862            let t2 = t2.as_leaf().unwrap();
863            assert_eq!(t1.legs(), t2.legs());
864            assert_eq!(t1.bond_dims(), t2.bond_dims());
865        }
866    }
867
868    #[test]
869    #[should_panic(expected = "PEPS should have length greater than 1")]
870    fn test_mps() {
871        let length = 1;
872        let depth = 2;
873        let physical_dim = 4;
874        let virtual_dim = 10;
875        let layers = 0;
876
877        let bond_dims = FxHashMap::from_iter([(0, 4), (1, 4), (2, 10)]);
878        let tensors = vec![
879            LeafTensor::new_from_map(vec![0, 2], &bond_dims),
880            LeafTensor::new_from_map(vec![1, 2], &bond_dims),
881        ];
882        let ref_tensor = CompositeTensor::new(tensors);
883
884        let new_peps = peps(length, depth, physical_dim, virtual_dim, layers);
885        for (t1, t2) in zip(new_peps.tensors().iter(), ref_tensor.tensors().iter()) {
886            let t1 = t1.as_leaf().unwrap();
887            let t2 = t2.as_leaf().unwrap();
888            assert_eq!(t1.legs(), t2.legs());
889            assert_eq!(t1.bond_dims(), t2.bond_dims());
890        }
891    }
892}