Skip to content

Commit 5ceb5ad

Browse files
author
Roberto Losada
committed
Implement horizontal and vertical 2-site density matrices analogue constructions.
1 parent 24d5380 commit 5ceb5ad

File tree

1 file changed

+368
-0
lines changed

1 file changed

+368
-0
lines changed

varipeps/expectation/helpers.py

Lines changed: 368 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,3 +389,371 @@ def partially_traced_four_site_density_matrices(
389389
density_bottom_left,
390390
density_bottom_right,
391391
)
392+
393+
394+
def partially_traced_horizontal_two_site_density_matrices(
395+
peps_tensors: Sequence[jnp.ndarray],
396+
peps_tensor_objs: Sequence[PEPS_Tensor],
397+
real_physical_dimension: int,
398+
num_coarse_grained_physical_indices: int,
399+
open_physical_indices: Tuple[Tuple[int], Tuple[int]],
400+
) -> Tuple[jnp.ndarray, jnp.ndarray]:
401+
402+
if not all(
403+
all(isinstance(open_idx, int) for open_idx in tup) or len(tup) == 0
404+
for tup in open_physical_indices
405+
):
406+
raise TypeError(
407+
"All elements of each tuple must be integers (or the tuple may be empty)."
408+
)
409+
if not all(
410+
len(tup) <= num_coarse_grained_physical_indices for tup in open_physical_indices
411+
):
412+
raise ValueError(
413+
f"At least one tuple in `open_physical_indices` {open_physical_indices} has length greater"
414+
f"than the number of coarse-grained physical sites {num_coarse_grained_physical_indices}"
415+
)
416+
peps_tensors = [
417+
t.reshape(
418+
t.shape[0],
419+
t.shape[1],
420+
*((real_physical_dimension,) * num_coarse_grained_physical_indices),
421+
t.shape[3],
422+
t.shape[4],
423+
)
424+
for t in peps_tensors
425+
]
426+
t_left, t_right = peps_tensors
427+
t_obj_left, t_obj_right = peps_tensor_objs
428+
left_i, right_i = open_physical_indices
429+
430+
if any(
431+
not hasattr(
432+
Definitions,
433+
(
434+
f"partially_traced_horizontal_two_site_density_matrices_{pos_name}_"
435+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{pos_idx}"
436+
),
437+
)
438+
for pos_idx, pos_name in zip(
439+
open_physical_indices, ["left", "right"], strict=True
440+
)
441+
):
442+
443+
phys_contraction_i_left = list(
444+
range(11, 11 + num_coarse_grained_physical_indices - len(left_i))
445+
)
446+
phys_contraction_i_conj_left = list(
447+
range(11, 11 + num_coarse_grained_physical_indices - len(left_i))
448+
)
449+
for pos, i in enumerate(left_i):
450+
phys_contraction_i_left.insert(i - 1, -(pos + 1))
451+
phys_contraction_i_conj_left.insert(i - 1, -len(left_i) - (pos + 1))
452+
phys_contraction_i_left = tuple(phys_contraction_i_left)
453+
phys_contraction_i_conj_left = tuple(phys_contraction_i_conj_left)
454+
455+
contraction_left = {
456+
"tensors": [["tensor", "tensor_conj", "C1", "T1", "T3", "C4", "T4"]],
457+
"network": [
458+
[
459+
(5, 9)
460+
+ phys_contraction_i_left
461+
+ (-2 * len(left_i) - 2, 4), # tensor
462+
(7, 10)
463+
+ phys_contraction_i_conj_left
464+
+ (-2 * len(left_i) - 3, 6), # tensor_conj
465+
(1, 3), # C1
466+
(3, 4, 6, -2 * len(left_i) - 1), # T1
467+
(2, -2 * len(left_i) - 4, 10, 9), # T3
468+
(2, 8), # C4
469+
(8, 7, 5, 1), # T4
470+
]
471+
],
472+
}
473+
Definitions._process_def(
474+
contraction_left,
475+
(
476+
f"partially_traced_horizontal_two_site_density_matrices_left_"
477+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{left_i}"
478+
),
479+
)
480+
setattr(
481+
Definitions,
482+
(
483+
f"partially_traced_horizontal_two_site_density_matrices_left_"
484+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{left_i}"
485+
),
486+
contraction_left,
487+
)
488+
489+
phys_contraction_i_right = list(
490+
range(11, 11 + num_coarse_grained_physical_indices - len(right_i))
491+
)
492+
phys_contraction_i_conj_right = list(
493+
range(11, 11 + num_coarse_grained_physical_indices - len(right_i))
494+
)
495+
for pos, i in enumerate(right_i):
496+
phys_contraction_i_right.insert(i - 1, -4 - (pos + 1))
497+
phys_contraction_i_conj_right.insert(i - 1, -4 - len(right_i) - (pos + 1))
498+
phys_contraction_i_right = tuple(phys_contraction_i_right)
499+
phys_contraction_i_conj_right = tuple(phys_contraction_i_conj_right)
500+
501+
contraction_right = {
502+
"tensors": [["tensor", "tensor_conj", "T1", "C2", "T2", "T3", "C3"]],
503+
"network": [
504+
[
505+
(-2, 8) + phys_contraction_i_right + (5, 4), # tensor
506+
(-3, 9) + phys_contraction_i_conj_right + (7, 6), # tensor_conj
507+
(-1, 4, 6, 3), # T1
508+
(3, 1), # C2
509+
(5, 7, 10, 1), # T2
510+
(-4, 2, 9, 8), # T3
511+
(2, 10), # C3
512+
]
513+
],
514+
}
515+
Definitions._process_def(
516+
contraction_right,
517+
(
518+
f"partially_traced_horizontal_two_site_density_matrices_right_"
519+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{right_i}"
520+
),
521+
)
522+
setattr(
523+
Definitions,
524+
(
525+
f"partially_traced_horizontal_two_site_density_matrices_right_"
526+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{right_i}"
527+
),
528+
contraction_right,
529+
)
530+
531+
density_left = apply_contraction(
532+
(
533+
f"partially_traced_horizontal_two_site_density_matrices_left_"
534+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{left_i}"
535+
),
536+
[t_left],
537+
[t_obj_left],
538+
[],
539+
disable_identity_check=True,
540+
)
541+
if len(left_i) > 0:
542+
density_left = density_left.reshape(
543+
real_physical_dimension ** len(left_i),
544+
real_physical_dimension ** len(left_i),
545+
density_left.shape[-4],
546+
density_left.shape[-3],
547+
density_left.shape[-2],
548+
density_left.shape[-1],
549+
)
550+
551+
density_right = apply_contraction(
552+
(
553+
f"partially_traced_horizontal_two_site_density_matrices_right_"
554+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{right_i}"
555+
),
556+
[t_right],
557+
[t_obj_right],
558+
[],
559+
disable_identity_check=True,
560+
)
561+
if len(right_i) > 0:
562+
# Physical indices are at the end (ket, bra), for consistency with _two_site_workhorse
563+
density_right = density_right.reshape(
564+
density_right.shape[0],
565+
density_right.shape[1],
566+
density_right.shape[2],
567+
density_right.shape[3],
568+
real_physical_dimension ** len(right_i),
569+
real_physical_dimension ** len(right_i),
570+
)
571+
572+
return (
573+
density_left,
574+
density_right,
575+
)
576+
577+
578+
def partially_traced_vertical_two_site_density_matrices(
579+
peps_tensors: Sequence[jnp.ndarray],
580+
peps_tensor_objs: Sequence[PEPS_Tensor],
581+
real_physical_dimension: int,
582+
num_coarse_grained_physical_indices: int,
583+
open_physical_indices: Tuple[Tuple[int], Tuple[int]],
584+
) -> Tuple[jnp.ndarray, jnp.ndarray]:
585+
586+
if not all(
587+
all(isinstance(open_idx, int) for open_idx in tup) or len(tup) == 0
588+
for tup in open_physical_indices
589+
):
590+
raise TypeError(
591+
"All elements of each tuple must be integers (or the tuple may be empty)."
592+
)
593+
if not all(
594+
len(tup) <= num_coarse_grained_physical_indices for tup in open_physical_indices
595+
):
596+
raise ValueError(
597+
f"At least one tuple in `open_physical_indices` {open_physical_indices} has length greater"
598+
f"than the number of coarse-grained physical sites {num_coarse_grained_physical_indices}"
599+
)
600+
peps_tensors = [
601+
t.reshape(
602+
t.shape[0],
603+
t.shape[1],
604+
*((real_physical_dimension,) * num_coarse_grained_physical_indices),
605+
t.shape[3],
606+
t.shape[4],
607+
)
608+
for t in peps_tensors
609+
]
610+
t_top, t_bottom = peps_tensors
611+
t_obj_top, t_obj_bottom = peps_tensor_objs
612+
top_i, bottom_i = open_physical_indices
613+
614+
if any(
615+
not hasattr(
616+
Definitions,
617+
(
618+
f"partially_traced_vertical_two_site_density_matrices_{pos_name}_"
619+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{pos_idx}"
620+
),
621+
)
622+
for pos_idx, pos_name in zip(
623+
open_physical_indices, ["top", "bottom"], strict=True
624+
)
625+
):
626+
627+
phys_contraction_i_top = list(
628+
range(11, 11 + num_coarse_grained_physical_indices - len(top_i))
629+
)
630+
phys_contraction_i_conj_top = list(
631+
range(11, 11 + num_coarse_grained_physical_indices - len(top_i))
632+
)
633+
for pos, i in enumerate(top_i):
634+
phys_contraction_i_top.insert(i - 1, -(pos + 1))
635+
phys_contraction_i_conj_top.insert(i - 1, -len(top_i) - (pos + 1))
636+
phys_contraction_i_top = tuple(phys_contraction_i_top)
637+
phys_contraction_i_conj_top = tuple(phys_contraction_i_conj_top)
638+
639+
contraction_top = {
640+
"tensors": [["tensor", "tensor_conj", "C1", "T1", "C2", "T2", "T4"]],
641+
"network": [
642+
[
643+
(8, -2 * len(top_i) - 2)
644+
+ phys_contraction_i_top
645+
+ (4, 5), # tensor
646+
(9, -2 * len(top_i) - 3)
647+
+ phys_contraction_i_conj_top
648+
+ (6, 7), # tensor_conj
649+
(2, 10), # C1
650+
(10, 5, 7, 1), # T1
651+
(1, 3), # C2
652+
(4, 6, -2 * len(top_i) - 4, 3), # T2
653+
(-2 * len(top_i) - 1, 9, 8, 2), # T4
654+
]
655+
],
656+
}
657+
Definitions._process_def(
658+
contraction_top,
659+
(
660+
f"partially_traced_vertical_two_site_density_matrices_top_"
661+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{top_i}"
662+
),
663+
)
664+
setattr(
665+
Definitions,
666+
(
667+
f"partially_traced_vertical_two_site_density_matrices_top_"
668+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{top_i}"
669+
),
670+
contraction_top,
671+
)
672+
673+
phys_contraction_i_bottom = list(
674+
range(11, 11 + num_coarse_grained_physical_indices - len(bottom_i))
675+
)
676+
phys_contraction_i_conj_bottom = list(
677+
range(11, 11 + num_coarse_grained_physical_indices - len(bottom_i))
678+
)
679+
for pos, i in enumerate(bottom_i):
680+
phys_contraction_i_bottom.insert(i - 1, -4 - (pos + 1))
681+
phys_contraction_i_conj_bottom.insert(i - 1, -4 - len(bottom_i) - (pos + 1))
682+
phys_contraction_i_bottom = tuple(phys_contraction_i_bottom)
683+
phys_contraction_i_conj_bottom = tuple(phys_contraction_i_conj_bottom)
684+
685+
contraction_bottom = {
686+
"tensors": [["tensor", "tensor_conj", "T2", "C3", "T3", "C4", "T4"]],
687+
"network": [
688+
[
689+
(4, 5) + phys_contraction_i_bottom + (8, -2), # tensor
690+
(6, 7) + phys_contraction_i_conj_bottom + (9, -3), # tensor_conj
691+
(8, 9, 2, -4), # T2
692+
(10, 2), # C3
693+
(1, 10, 7, 5), # T3
694+
(1, 3), # C4
695+
(3, 6, 4, -1), # T4
696+
]
697+
],
698+
}
699+
Definitions._process_def(
700+
contraction_bottom,
701+
(
702+
f"partially_traced_vertical_two_site_density_matrices_bottom_"
703+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{bottom_i}"
704+
),
705+
)
706+
setattr(
707+
Definitions,
708+
(
709+
f"partially_traced_vertical_two_site_density_matrices_bottom_"
710+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{bottom_i}"
711+
),
712+
contraction_bottom,
713+
)
714+
715+
density_top = apply_contraction(
716+
(
717+
f"partially_traced_vertical_two_site_density_matrices_top_"
718+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{top_i}"
719+
),
720+
[t_top],
721+
[t_obj_top],
722+
[],
723+
disable_identity_check=True,
724+
)
725+
if len(top_i) > 0:
726+
density_top = density_top.reshape(
727+
real_physical_dimension ** len(top_i),
728+
real_physical_dimension ** len(top_i),
729+
density_top.shape[-4],
730+
density_top.shape[-3],
731+
density_top.shape[-2],
732+
density_top.shape[-1],
733+
)
734+
735+
density_bottom = apply_contraction(
736+
(
737+
f"partially_traced_vertical_two_site_density_matrices_bottom_"
738+
f"{real_physical_dimension}_{num_coarse_grained_physical_indices}_{bottom_i}"
739+
),
740+
[t_bottom],
741+
[t_obj_bottom],
742+
[],
743+
disable_identity_check=True,
744+
)
745+
if len(bottom_i) > 0:
746+
# Physical indices are at the end (ket, bra), for consistency with _two_site_workhorse
747+
density_bottom = density_bottom.reshape(
748+
density_bottom.shape[0],
749+
density_bottom.shape[1],
750+
density_bottom.shape[2],
751+
density_bottom.shape[3],
752+
real_physical_dimension ** len(bottom_i),
753+
real_physical_dimension ** len(bottom_i),
754+
)
755+
756+
return (
757+
density_top,
758+
density_bottom,
759+
)

0 commit comments

Comments
 (0)