import torch
from torch.utils.checkpoint import checkpoint
from config import ctm_args
from tn_interface import contract
from tn_interface import view, permute, contiguous, conj
#####################################################################
# functions building pair of 4x2 (or 2x4) halves of 4x4 TN
#####################################################################
[docs]def halves_of_4x4_CTM_MOVE_UP(coord, state, env, mode='sl', verbosity=0):
r"""
:param coord: site for which to build two halfs of 2x2 subsystem embedded
in environment
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:return: right and left half of the system as matrices
:rtype: torch.Tensor, torch.Tensor
Builds right and left half of 2x2 subsystem embedded into environment.
The `coord` specifies the upper-right site of the 2x2 subsystem.
Performs following contraction and then reshaping the resulting tensors into matrices::
C T T C = C2x2_LU(coord+(-1,0)) C2x2(coord)
T A B(coord) T C2x2_LD(coord+(-1,1)) C2x2(coord+(0,1))
T C D T
C T T C
C2x2--1->0 0--C2x2(coord) = _0 0_
|0 1| | |
|0 0| half2 half1
C2x2--1 1--C2x2 |_1 1_|
"""
# RU, RD, LU, LD
tensors= c2x2_RU_t(coord,state,env) + c2x2_RD_t((coord[0], coord[1]+1),state,env) \
+ c2x2_LU_t((coord[0]-1, coord[1]),state,env) + c2x2_LD_t((coord[0]-1, coord[1]+1),state,env)
if mode in ['sl']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_halves:
return checkpoint(halves_of_4x4_CTM_MOVE_UP_c,*tensors)
else:
return halves_of_4x4_CTM_MOVE_UP_c(*tensors)
def halves_of_4x4_CTM_MOVE_UP_t(coord, state, env):
# RU, RD, LU, LD
tensors= c2x2_RU_t(coord,state,env) + c2x2_RD_t((coord[0], coord[1]+1),state,env) \
+ c2x2_LU_t((coord[0]-1, coord[1]),state,env) + c2x2_LD_t((coord[0]-1, coord[1]+1),state,env)
return tensors
def halves_of_4x4_CTM_MOVE_UP_c(*tensors):
# C T T C = C2x2_LU(coord+(-1,0)) C2x2(coord)
# T A B(coord) T C2x2_LD(coord+(-1,1)) C2x2(coord+(0,1))
# T C D T
# C T T C
# C2x2--1->0 0--C2x2(coord) = _0 0_
# |0 1| | |
# |0 0| half2 half1
# C2x2--1 1--C2x2 |_1 1_|
# C_1, T1_1, T2_1, A_1= tensors[0:4]
# C_2, T1_2, T2_2, A_2= tensors[4:8]
# C_3, T1_3, T2_3, A_3= tensors[8:12]
# C_4, T1_4, T2_4, A_4= tensors[12:16]
if tensors[-1]: # mode
return contract(c2x2_RU_sl_c(*tensors[0:4]),c2x2_RD_sl_c(*tensors[4:8]),([1],[0])), \
contract(c2x2_LU_sl_c(*tensors[8:12]),c2x2_LD_sl_c(*tensors[12:16]),([0],[0]))
else:
return contract(c2x2_RU_c(*tensors[0:4]),c2x2_RD_c(*tensors[4:8]),([1],[0])), \
contract(c2x2_LU_c(*tensors[8:12]),c2x2_LD_c(*tensors[12:16]),([0],[0]))
[docs]def halves_of_4x4_CTM_MOVE_LEFT(coord, state, env, mode='sl', verbosity=0):
r"""
:param coord: site for which to build two halfs of 2x2 subsystem embedded
in environment
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:return: upper and lower half of the system as matrices
:rtype: torch.Tensor, torch.Tensor
Builds upper and lower half of 2x2 subsystem embedded into environment.
The `coord` specifies the upper-left site of the 2x2 subsystem.
Performs following contraction and then reshaping the resulting tensors into matrices::
C T T C = C2x2_LU(coord) C2x2(coord+(1,0))
T A(coord) B T C2x2_LD(coord+(0,1)) C2x2(coord+(1,1))
T C D T
C T T C
C2x2(coord)--1 0--C2x2 = half1
|0 1| |0 |1
|0 1<-0| |0 |1
C2x2--1 1---------C2x2 half2
"""
# LU, RU, LS, RD
tensors= c2x2_LU_t(coord,state,env) + c2x2_RU_t((coord[0]+1, coord[1]),state,env) \
+ c2x2_LD_t((coord[0], coord[1]+1),state,env) + c2x2_RD_t((coord[0]+1, coord[1]+1),state,env)
if mode in ['sl']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_halves:
return checkpoint(halves_of_4x4_CTM_MOVE_LEFT_c,*tensors)
else:
return halves_of_4x4_CTM_MOVE_LEFT_c(*tensors)
def halves_of_4x4_CTM_MOVE_LEFT_t(coord, state, env):
# LU, RU, LS, RD
tensors= c2x2_LU_t(coord,state,env) + c2x2_RU_t((coord[0]+1, coord[1]),state,env) \
+ c2x2_LD_t((coord[0], coord[1]+1),state,env) + c2x2_RD_t((coord[0]+1, coord[1]+1),state,env)
return tensors
def halves_of_4x4_CTM_MOVE_LEFT_c(*tensors):
# C T T C = C2x2_LU(coord) C2x2(coord+(1,0))
# T A(coord) B T C2x2_LD(coord+(0,1)) C2x2(coord+(1,1))
# T C D T
# C T T C
# C2x2(coord)--1 0--C2x2 = half1
# |0 1| |0 |1
#
# |0 1<-0| |0 |1
# C2x2--1 1---------C2x2 half2
if tensors[-1]: # mode
return contract(c2x2_LU_sl_c(*tensors[0:4]),c2x2_RU_sl_c(*tensors[4:8]),([1],[0])), \
contract(c2x2_LD_sl_c(*tensors[8:12]),c2x2_RD_sl_c(*tensors[12:16]),([1],[1]))
else:
return contract(c2x2_LU_c(*tensors[0:4]),c2x2_RU_c(*tensors[4:8]),([1],[0])), \
contract(c2x2_LD_c(*tensors[8:12]),c2x2_RD_c(*tensors[12:16]),([1],[1]))
[docs]def halves_of_4x4_CTM_MOVE_DOWN(coord, state, env, mode='sl', verbosity=0):
r"""
:param coord: site for which to build two halfs of 2x2 subsystem embedded
in environment
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:return: left and right half of the system as matrices
:rtype: torch.Tensor, torch.Tensor
Builds left and right half of 2x2 subsystem embedded into environment.
The `coord` specifies the lower-left site of the 2x2 subsystem.
Performs following contraction and then reshaping the resulting tensors into matrices::
C T T C = C2x2_LU(coord+(0,-1)) C2x2(coord+(1,-1))
T A B T C2x2_LD(coord) C2x2(coord+(1,0))
T C(coord) D T
C T T C
C2x2---------1 1<-0--C2x2 = _1 1_
|0 |1 | |
|0 |0 half1 half2
C2x2(coord)--1->0 0<-1--C2x2 |_0 0_|
"""
# LD, LU, RD, RU
tensors= c2x2_LD_t(coord,state,env) + c2x2_LU_t((coord[0], coord[1]-1),state,env) \
+ c2x2_RD_t((coord[0]+1, coord[1]),state,env) + c2x2_RU_t((coord[0]+1, coord[1]-1),state,env)
if mode in ['sl']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_halves:
return checkpoint(halves_of_4x4_CTM_MOVE_DOWN_c,*tensors)
else:
return halves_of_4x4_CTM_MOVE_DOWN_c(*tensors)
def halves_of_4x4_CTM_MOVE_DOWN_t(coord, state, env):
# LD, LU, RD, RU
tensors= c2x2_LD_t(coord,state,env) + c2x2_LU_t((coord[0], coord[1]-1),state,env) \
+ c2x2_RD_t((coord[0]+1, coord[1]),state,env) + c2x2_RU_t((coord[0]+1, coord[1]-1),state,env)
return tensors
def halves_of_4x4_CTM_MOVE_DOWN_c(*tensors):
# C T T C = C2x2_LU(coord+(0,-1)) C2x2(coord+(1,-1))
# T A B T C2x2_LD(coord) C2x2(coord+(1,0))
# T C(coord) D T
# C T T C
# C2x2---------1 1<-0--C2x2 = _1 1_
# |0 |1 | |
# |0 |0 half1 half2
# C2x2(coord)--1->0 0<-1--C2x2 |_0 0_|
if tensors[-1]: # mode
return contract(c2x2_LD_sl_c(*tensors[0:4]),c2x2_LU_sl_c(*tensors[4:8]),([0],[0])), \
contract(c2x2_RD_sl_c(*tensors[8:12]),c2x2_RU_sl_c(*tensors[12:16]),([0],[1]))
else:
return contract(c2x2_LD_c(*tensors[0:4]),c2x2_LU_c(*tensors[4:8]),([0],[0])), \
contract(c2x2_RD_c(*tensors[8:12]),c2x2_RU_c(*tensors[12:16]),([0],[1]))
[docs]def halves_of_4x4_CTM_MOVE_RIGHT(coord, state, env, mode='sl', verbosity=0):
r"""
:param coord: site for which to build two halfs of 2x2 subsystem embedded
in environment
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:return: upper and lower half of the system as matrices
:rtype: torch.Tensor, torch.Tensor
Builds uoper and lower half of 2x2 subsystem embedded into environment.
The `coord` specifies the lower-right site of the 2x2 subsystem.
Performs following contraction and then reshaping the resulting tensors into matrices::
C T T C = C2x2_LU(coord+(-1,-1)) C2x2(coord+(0,-1))
T A B T C2x2_LD(coord+(-1,0)) C2x2(coord)
T C D(coord) T
C T T C
C2x2--1 0--C2x2 = half2
|0->1 |1->0 |1 |0
|0->1 |0 |1 |0
C2x2--1 1--C2x2(coord) half1
"""
# RD, LD, RU, LU
tensors= c2x2_RD_t(coord,state,env) + c2x2_LD_t((coord[0]-1, coord[1]),state,env) \
+ c2x2_RU_t((coord[0], coord[1]-1),state,env) + c2x2_LU_t((coord[0]-1, coord[1]-1),state,env)
if mode in ['sl']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_halves:
return checkpoint(halves_of_4x4_CTM_MOVE_RIGHT_c,*tensors)
else:
return halves_of_4x4_CTM_MOVE_RIGHT_c(*tensors)
def halves_of_4x4_CTM_MOVE_RIGHT_t(coord, state, env):
# RD, LD, RU, LU
tensors= c2x2_RD_t(coord,state,env) + c2x2_LD_t((coord[0]-1, coord[1]),state,env) \
+ c2x2_RU_t((coord[0], coord[1]-1),state,env) + c2x2_LU_t((coord[0]-1, coord[1]-1),state,env)
return tensors
def halves_of_4x4_CTM_MOVE_RIGHT_c(*tensors):
# C T T C = C2x2_LU(coord+(-1,-1)) C2x2(coord+(0,-1))
# T A B T C2x2_LD(coord+(-1,0)) C2x2(coord)
# T C D(coord) T
# C T T C
# C2x2--1 0--C2x2 = half2
# |0->1 |1->0 |1 |0
#
# |0->1 |0 |1 |0
# C2x2--1 1--C2x2(coord) half1
if tensors[-1]: # mode
return contract(c2x2_RD_sl_c(*tensors[0:4]),c2x2_LD_sl_c(*tensors[4:8]),([1],[1])), \
contract(c2x2_RU_sl_c(*tensors[8:12]),c2x2_LU_sl_c(*tensors[12:16]),([0],[1]))
else:
return contract(c2x2_RD_c(*tensors[0:4]),c2x2_LD_c(*tensors[4:8]),([1],[1])), \
contract(c2x2_RU_c(*tensors[8:12]),c2x2_LU_c(*tensors[12:16]),([0],[1]))
#####################################################################
# functions building 2x2 Corner
#####################################################################
[docs]def c2x2_LU(coord, state, env, mode='dl', verbosity=0):
r"""
:param coord: site for which to build enlarged upper-left corner
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:param mode: single ``'sl'`` or double-layer ``'dl'`` contraction
:type mode: str
:return: enlarged upper-left corner
:rtype: torch.Tensor
Builds upper-left corner at site `coord` by performing following
contraction and then reshaping the resulting tensor into matrix::
C----T1--2 => C2x2--(2,3)->1
| | |
| | (0,1)->0
T2----A(coord)--3
| |
0 1
"""
# tensors= C, T1, T2, A
tensors= c2x2_LU_t(coord,state,env)
_f_c2x2= c2x2_LU_c if mode in ['dl','dl-open'] else c2x2_LU_sl_c
if mode in ['dl-open', 'sl-open']:
tensors += (torch.ones(1, dtype=torch.bool),)
else:
tensors += (torch.zeros(1, dtype=torch.bool),)
if ctm_args.fwd_checkpoint_c2x2:
C2x2= checkpoint(_f_c2x2,*tensors)
else:
C2x2= _f_c2x2(*tensors)
if verbosity>0:
print("C2X2 LU "+str(coord)+"->"+str(state.vertexToSite(coord))+" (-1,-1)")
if verbosity>1:
print(C2x2)
return C2x2
def c2x2_LU_t(coord, state, env):
tensors= env.C[(state.vertexToSite(coord),(-1,-1))], \
env.T[(state.vertexToSite(coord),(0,-1))], \
env.T[(state.vertexToSite(coord),(-1,0))], \
state.site(coord)
return tensors
def c2x2_LU_c(*tensors):
C, T1, T2, A, mode= tensors if len(tensors)==5 else tensors+(None,)
# flops \chi x (D^2 \chi^2)
#
# C--10--T1--2
# 0 1
C2x2 = contract(C, T1, ([1],[0]))
# flops \chi x (D^4 \chi^2)
#
# C------T1--2->1
# 0 1->0
# 0
# T2--2->3
# 1->2
C2x2 = contract(C2x2, T2, ([0],[0]))
# C-------T1--1->0
# | 0
# | 0
# T2--3 1 A--3
# 2->1 2
if not mode:
# flops D^4 x (D^4 \chi^2)
#
C2x2 = contract(C2x2, A, ([0,3],[0,1]))
# permute 0123->1203
# reshape (12)(03)->01
C2x2 = contiguous(permute(C2x2,(1,2,0,3)))
C2x2 = view(C2x2,(T2.size(1)*A.size(2),T1.size(2)*A.size(3)))
else:
# flops D^4 x (D^4 \chi^2 p^2)
#
# C-------T1--1->0
# | 0
# | 2/0->2
# T2--3 3 A--5->5
# 2->1 4\1->3
# ->4
C2x2 = contract(C2x2, A, ([0,3],[2,3]))
# permute 012345->140523
# reshape (14)(05)23->0123
C2x2 = contiguous(permute(C2x2,(1,4,0,5,2,3)))
C2x2 = view(C2x2,(T2.size(1)*A.size(4),T1.size(2)*A.size(5),\
A.size(0),A.size(1)))
# C2x2--1
# |\
# 0 optionally(2,3)
return C2x2
def c2x2_LU_sl_c(*tensors):
C, T1, T2, a, mode= tensors if len(tensors)==5 else tensors+(None,)
# flops \chi x (D^2 \chi^2)
#
# C--1 0--T1--2
# 0 1
C2x2 = contract(C, T1, ([1],[0]))
# flops \chi x (D^4 \chi^2)
#
# C------T1--2->1
# 0 1->0
# 0
# T2--2->3
# 1->2
C2x2 = contract(C2x2, T2, ([0],[0]))
C2x2 = view(C2x2, (a.size(1),a.size(1),T1.size(2),\
T2.size(1),a.size(2),a.size(2)) )
# flops D^2 x (D^4 \chi^2 p)
#
# C---------T1--2->1
# | 0,1->0
# | 1
# T2--4 2---a--4->6
# | 5->3 3\0->4
# 3->2 ->5
#
# C---------T1--0
# | |
# | |
# T2-------a*a--3,5
# | |
# 1 2,4
C2x2 = contract(C2x2, a, ([0,4],[1,2]))
if not mode:
# flops (D^2 p) x (D^4 \chi^2)
#
C2x2 = contract(C2x2, conj(a), ([0,3,4],[1,2,0]))
# permute 012345->124035
# reshape (124)(035)->01
C2x2 = contiguous(permute(C2x2,(1,2,4,0,3,5)))
C2x2 = view(C2x2,(T2.size(1)*(a.size(3)**2),T1.size(2)*(a.size(4)**2)))
else:
# flops D^2 x (D^4 \chi^2 p^2)
#
# C---------T1--0
# | |
# | |/2,5
# T2-------a*a--4,7
# | |
# 1 3,6
C2x2 = contract(C2x2, conj(a), ([0,3],[1,2]))
# permute 01234567->13604725
# reshape (136)(047)25->0123
C2x2 = contiguous(permute(C2x2,(1,3,6,0,4,7,2,5)))
C2x2 = view(C2x2,(T2.size(1)*(a.size(3)**2),T1.size(2)*(a.size(4)**2),
a.size(0),a.size(0)))
# C2x2--1
# |\
# 0 optionally(2,3)
return C2x2
[docs]def c2x2_RU(coord, state, env, mode='dl', verbosity=0):
r"""
:param coord: site for which to build enlarged upper-right corner
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:param mode: single ``'sl'`` or double-layer ``'dl'`` contraction
:type mode: str
:return: enlarged upper-left corner
:rtype: torch.Tensor
Builds upper-right corner at site `coord` by performing following
contraction and then reshaping the resulting tensor into matrix::
0--T2--------C => 0<-(0,1)--C2x2
| | |
| | 1<-(2,3)
1--A(coord)--T1
3 2
"""
# tensors= C, T1, T2, A
tensors= c2x2_RU_t(coord,state,env)
_f_c2x2= c2x2_RU_c if mode in ['dl','dl-open'] else c2x2_RU_sl_c
if mode in ['dl-open', 'sl-open']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_c2x2:
C2x2= checkpoint(_f_c2x2,*tensors)
else:
C2x2= _f_c2x2(*tensors)
if verbosity>0:
print("C2X2 RU "+str(coord)+"->"+str(state.vertexToSite(coord))+" (1,-1)")
if verbosity>1:
print(C2x2)
return C2x2
def c2x2_RU_t(coord, state, env):
tensors= env.C[(state.vertexToSite(coord),(1,-1))], \
env.T[(state.vertexToSite(coord),(1,0))], \
env.T[(state.vertexToSite(coord),(0,-1))], \
state.site(coord)
return tensors
def c2x2_RU_c(*tensors):
C, T1, T2, A, mode= tensors if len(tensors)==5 else tensors+(None,)
# 0--C
# 1
# 0
# 1--T1
# 2
C2x2 = contract(C, T1, ([1],[0]))
# 2<-0--T2--2 0--C
# 3<-1 |
# 0<-1--T1
# 1<-2
C2x2 = contract(C2x2, T2, ([0],[2]))
if not mode:
# 1<-2--T2------C
# 3 |
# 0 |
# 2<-1--A--3 0--T1
# 3<-2 0<-1
C2x2 = contract(C2x2, A, ([0,3],[3,0]))
# permute 0123->1203
# reshape (12)(03)->01
C2x2 = contiguous(permute(C2x2,(1,2,0,3)))
C2x2 = view(C2x2,(T2.size(0)*A.size(1),T1.size(2)*A.size(2)))
else:
# 1<-2--T2------C
# 3 |
# 2,3<-0,1\2 |
# 4<-3--A--5 0--T1
# 5<-4 0<-1
C2x2 = contract(C2x2, A, ([0,3],[5,2]))
# permute 012345->140523
# reshape (14)(05)23->0123
C2x2 = contiguous(permute(C2x2,(1,4,0,5,2,3)))
C2x2 = view(C2x2,(T2.size(0)*A.size(3),T1.size(2)*A.size(4),\
A.size(0),A.size(1)))
# 0--C2x2
# |\
# 1 optionally(2,3)
return C2x2
def c2x2_RU_sl_c(*tensors):
C, T1, T2, a, mode= tensors if len(tensors)==5 else tensors+(None,)
# 0--C
# 1
# 0
# 1--T1
# 2
C2x2 = contract(C, T1, ([1],[0]))
# 2<-0--T2--2 0--C
# 3<-1 |
# 0<-1--T1
# 1<-2
C2x2 = contract(C2x2, T2, ([0],[2]))
C2x2 = view(C2x2, (a.size(4),a.size(4),T1.size(2),T2.size(0),\
a.size(1),a.size(1)) )
# 2<-3--T2------C
# 4,5 |
# 1 ->3 |
# 5<-2--a--4 0--T1
# 4<-0/3 0<-1 |
# 6<- 1<-2
#
# 1--T2------C
# | |
# | |
# 2,4-a*a------T1
# | |
# 3,5 0
C2x2 = contract(C2x2, a, ([0,4],[4,1]))
if not mode:
C2x2 = contract(C2x2, conj(a), ([0,3,4],[4,1,0]))
# permute 012345->124035
# reshape (124)(035)->01
C2x2 = contiguous(permute(C2x2,(1,2,4,0,3,5)))
C2x2 = view(C2x2,(T2.size(0)*(a.size(2)**2),T1.size(2)*(a.size(3)**2)))
else:
# 1--T2------C
# | |
# 2,5\| |
# 3,6-a*a------T1
# | |
# 4,7 0
C2x2 = contract(C2x2, conj(a), ([0,3],[4,1]))
# permute 01234567->12603745
# reshape (136)(047)25->0123
C2x2 = contiguous(permute(C2x2,(1,3,6,0,4,7,2,5)))
C2x2 = view(C2x2,(T2.size(0)*(a.size(2)**2),T1.size(2)*(a.size(3)**2),
a.size(0),a.size(0)))
# 0--C2x2
# |\
# 1 optionally(2,3)
return C2x2
[docs]def c2x2_RD(coord, state, env, mode='dl', verbosity=0):
r"""
:param coord: site for which to build enlarged lower-right corner
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:param mode: single ``'sl'`` or double-layer ``'dl'`` contraction
:type mode: str
:return: enlarged upper-left corner
:rtype: torch.Tensor
Builds lower-right corner at site `coord` by performing following
contraction and then reshaping the resulting tensor into matrix::
1 0
3--A(coord)--T2 => 0<-(0,1)
| | |
| | 1<-(2,3)--C2x2
2--T1--------C
"""
# tensors= C, T1, T2, A
tensors= c2x2_RD_t(coord,state,env)
_f_c2x2= c2x2_RD_c if mode in ['dl','dl-open'] else c2x2_RD_sl_c
if mode in ['dl-open', 'sl-open']:
tensors += (torch.ones(1, dtype=torch.bool),)
else:
tensors += (torch.zeros(1, dtype=torch.bool),)
if ctm_args.fwd_checkpoint_c2x2:
C2x2= checkpoint(_f_c2x2,*tensors)
else:
C2x2= _f_c2x2(*tensors)
if verbosity>0:
print("C2X2 RD "+str(coord)+"->"+str(state.vertexToSite(coord))+" (1,1)")
if verbosity>1:
print(C2x2)
return C2x2
def c2x2_RD_t(coord, state, env):
tensors= env.C[(state.vertexToSite(coord),(1,1))], \
env.T[(state.vertexToSite(coord),(0,1))], \
env.T[(state.vertexToSite(coord),(1,0))], \
state.site(coord)
return tensors
def c2x2_RD_c(*tensors):
C, T1, T2, A, mode= tensors if len(tensors)==5 else tensors+(None,)
# 1<-0 0
# 2<-1--T1--2 1--C
C2x2 = contract(C, T1, ([1],[2]))
# 2<-0
# 3<-1--T2
# 2
# 0<-1 0
# 1<-2--T1---C
C2x2 = contract(C2x2, T2, ([0],[2]))
# 2<-0 1<-2
# 3<-1--A--3 3--T2
# 2 |
# 0 |
# 0<-1--T1------C
if not mode:
C2x2 = contract(C2x2, A, ([0,3],[2,3]))
# permute 0123->1203
# reshape (12)(03)->01
C2x2 = contiguous(permute(C2x2,(1,2,0,3)))
C2x2 = view(C2x2,(T2.size(0)*A.size(0),T1.size(1)*A.size(1)))
else:
# 4<-2 1<-2
# 5<-3--A--5 3--T2
# 2,3<-0,1/4 |
# 0 |
# 0<-1--T1------C
C2x2 = contract(C2x2, A, ([0,3],[4,5]))
# permute 012345->140523
# reshape (14)(05)23->0123
C2x2 = contiguous(permute(C2x2,(1,4,0,5,2,3)))
C2x2 = view(C2x2,(T2.size(0)*A.size(2),T1.size(1)*A.size(3),\
A.size(0),A.size(1)))
# 0 optionally(2,3)
# |/
# 1--C2x2
return C2x2
def c2x2_RD_sl_c(*tensors):
C, T1, T2, a, mode= tensors if len(tensors)==5 else tensors+(None,)
# 1<-0 0
# 2<-1--T1--2 1--C
C2x2 = contract(C, T1, ([1],[2]))
# 2<-0
# 3<-1--T2
# 2
# 0<-1 0
# 1<-2--T1---C
C2x2 = contract(C2x2, T2, ([0],[2]))
C2x2 = view(C2x2, (a.size(3),a.size(3),T1.size(1),\
T2.size(0), a.size(4), a.size(4)) )
# 5<-1 2<-3
# 6<-2--a--4 4--T2
# 4<-0/3 3<-5 |
# 0,1->0 |
# 1<-2--T1------C
#
# 2,4 1
# 3,5-a*a------T2
# | |
# | |
# 0--T1------C
C2x2 = contract(C2x2, a, ([0,4],[3,4]))
if not mode:
C2x2 = contract(C2x2, conj(a), ([0,3,4],[3,4,0]))
# permute 012345->124035
# reshape (124)(035)->01
C2x2 = contiguous(permute(C2x2,(1,2,4,0,3,5)))
C2x2 = view(C2x2,(T2.size(0)*(a.size(1)**2),T1.size(1)*(a.size(2)**2)))
else:
# 3,6 1
# 4,7-a*a------T2
# 2,5/| |
# | |
# 0--T1------C
C2x2 = contract(C2x2, conj(a), ([0,3],[3,4]))
# permute 01234567->13604725
# reshape (136)(047)25->0123
C2x2 = contiguous(permute(C2x2,(1,3,6,0,4,7,2,5)))
C2x2 = view(C2x2,(T2.size(0)*(a.size(1)**2),T1.size(1)*(a.size(2)**2),
a.size(0),a.size(0)))
# 0 optionally(2,3)
# |/
# 1--C2x2
return C2x2
[docs]def c2x2_LD(coord, state, env, mode='dl', verbosity=0):
r"""
:param coord: site for which to build enlarged lower-right corner
:type coord: tuple(int,int)
:param state: wavefunction
:type state: IPEPS
:param env: environment
:type env: ENV
:param mode: single ``'sl'`` or double-layer ``'dl'`` contraction
:type mode: str
:return: enlarged upper-left corner
:rtype: torch.Tensor
Builds lower-right corner at site `coord` by performing following
contraction and then reshaping the resulting tensor into matrix::
0 1
T1--A(coord)--3
| | (0,1)->0(+)
| | |
C---T2--------2 => C2x2--(2,3)->1(-)
"""
#tensors= C, T1, T2, A
tensors= c2x2_LD_t(coord,state,env)
_f_c2x2= c2x2_LD_c if mode in ['dl','dl-open'] else c2x2_LD_sl_c
if mode in ['dl-open', 'sl-open']:
tensors += (torch.ones(1,dtype=torch.bool),)
else:
tensors += (torch.zeros(1,dtype=torch.bool),)
if ctm_args.fwd_checkpoint_c2x2:
C2x2= checkpoint(_f_c2x2,*tensors)
else:
C2x2= _f_c2x2(*tensors)
if verbosity>0:
print("C2X2 LD "+str(coord)+"->"+str(state.vertexToSite(coord))+" (-1,1)")
if verbosity>1:
print(C2x2)
return C2x2
def c2x2_LD_t(coord, state, env):
tensors= env.C[(state.vertexToSite(coord),(-1,1))], \
env.T[(state.vertexToSite(coord),(-1,0))], \
env.T[(state.vertexToSite(coord),(0,1))], \
state.site(coord)
return tensors
def c2x2_LD_c(*tensors):
C, T1, T2, A, mode= tensors if len(tensors)==5 else tensors+(None,)
# 0->1
# T1--2
# 1
# 0
# C--1->0
C2x2 = contract(C, T1, ([0],[1]))
# 1->0
# T1--2->1
# |
# | 0->2
# C--0 1--T2--2->3
C2x2 = contract(C2x2, T2, ([0],[1]))
# 0 0->2
# T1--1 1--A--3
# | 2
# | 2
# C--------T2--3->1
if not mode:
C2x2 = contract(C2x2, A, ([1,2],[1,2]))
# permute 0123->0213
# reshape (02)(13)->01
C2x2 = contiguous(permute(C2x2,(0,2,1,3)))
C2x2 = view(C2x2,(T1.size(0)*A.size(0),T2.size(2)*A.size(3)))
else:
# 0 2->4
# T1--1 3--A--5
# | 4\0,1->2,3
# | 2
# C--------T2--3->1
C2x2 = contract(C2x2, A, ([1,2],[3,4]))
# permute 012345->041523
# reshape (04)(15)23->0123
C2x2 = contiguous(permute(C2x2,(0,4,1,5,2,3)))
C2x2 = view(C2x2,(T1.size(0)*A.size(2),T2.size(2)*A.size(5),
A.size(0),A.size(1)))
# 0 optionally(2,3)
# |/
# C2x2--1
return C2x2
def c2x2_LD_sl_c(*tensors):
C, T1, T2, a, mode= tensors if len(tensors)==5 else tensors+(None,)
# 0->1
# T1--2
# 1
# 0
# C--1->0
C2x2 = contract(C, T1, ([0],[1]))
# 1->0
# T1--2->1
# |
# | 0->2
# C--0 1--T2--2->3
C2x2 = contract(C2x2, T2, ([0],[1]))
C2x2 = view(C2x2, (T1.size(0),a.size(2),a.size(2),
a.size(3),a.size(3),T2.size(2)) )
# 0 1->5
# T1--1 2--a--4->6
# | 2->1 3\0->4
# | 3,4->2
# C--------T2--5->3
#
# 0 2,4
# T1------a*a--3,5
# | |
# | |
# C--------T2--1
C2x2 = contract(C2x2, a, ([1,3],[2,3]))
if not mode:
C2x2 = contract(C2x2, conj(a), ([1,2,4],[2,3,0]))
# permute 012345->024135
# reshape (024)(135)->01
C2x2 = contiguous(permute(C2x2,(0,2,4,1,3,5)))
C2x2 = view(C2x2,(T1.size(0)*(a.size(1)**2),T2.size(2)*(a.size(4)**2)))
else:
# 0 3,6
# T1------a*a--4,7
# | |\2,5
# | |
# C--------T2--1
C2x2 = contract(C2x2, conj(a), ([1,2],[2,3]))
# permute 01234567->03614725
# reshape (036)(147)25->0123
C2x2 = contiguous(permute(C2x2,(0,3,6,1,4,7,2,5)))
C2x2 = view(C2x2,(T1.size(0)*(a.size(1)**2),T2.size(2)*(a.size(4)**2),
a.size(0),a.size(0)))
# 0 optionally(2,3)
# |/
# C2x2--1
return C2x2