Skip to content
Open
26 changes: 22 additions & 4 deletions example/DMRG/dmrg_two_sites_U1.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,15 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
return psivec, energy[0].item()


## Initialiaze MPO
## Initialize MPO
##>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
d = 2
s = 0.5
bd_inner = cytnx.Bond(cytnx.BD_KET,[[0],[-2],[2],[0]],[1,1,1,1])
bd_phys = cytnx.Bond(cytnx.BD_KET,[[1],[-1]],[1,1])

M = cytnx.UniTensor([bd_inner,bd_inner.redirect(),bd_phys, bd_phys.redirect()],rowrank=2)
M.set_name("MPO")

# I
M.set_elem([0,0,0,0],1);
Expand All @@ -69,7 +70,9 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
VbdL = cytnx.Bond(cytnx.BD_KET,[[0]],[1])
VbdR = cytnx.Bond(cytnx.BD_KET,[[q]],[1])
L0 = cytnx.UniTensor([bd_inner.redirect(),VbdL.redirect(),VbdL],rowrank=1) #Left boundary
L0.set_name("L0")
R0 = cytnx.UniTensor([bd_inner,VbdR,VbdR.redirect()],rowrank=1) #Right boundary
R0.set_name("R0")
L0.set_elem([0,0,0],1)
R0.set_elem([3,0,0],1)

Expand All @@ -83,6 +86,7 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):

A[0] = cytnx.UniTensor([VbdL,bd_phys.redirect(),cytnx.Bond(cytnx.BD_BRA,[[qcntr]],[1])],rowrank=2)
A[0].get_block_()[0] = 1
A[0].set_name("A0")

lbls = []
lbls.append(["0","1","2"]) # store the labels for later convinience.
Expand All @@ -96,6 +100,7 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
B3 = cytnx.Bond(cytnx.BD_BRA,[[qcntr]],[1])

A[k] = cytnx.UniTensor([B1,B2,B3],rowrank=2)
A[k].set_name(f"A{k}")

lbl = [str(2*k),str(2*k+1),str(2*k+2)]
A[k].set_labels(lbl)
Expand All @@ -114,8 +119,10 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
"A_Conj: -3,-5,2",\
"TOUT: 0;1,2"])
for p in range(Nsites - 1):
anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Dagger(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

Ekeep = []
for k in range(1, numsweeps+1):
Expand All @@ -138,15 +145,20 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
A[p] = cytnx.Contract(A[p],s) # absorb s into next neighbor
A[p].relabels_(lbls[p]); # set the label back to be consistent

A[p].set_name(f"A{p}")
A[p+1].set_name(f"A{p+1}")

# update LR from right to left:
anet = cytnx.Network()
anet.FromString(["R: -2,-1,-3",\
"B: 1,-4,-1",\
"M: 0,-2,-4,-5",\
"B_Conj: 2,-5,-3",\
"TOUT: 0;1,2"])
anet.PutUniTensors(["R","B","M","B_Conj"],[LR[p+2],A[p+1],M,A[p+1].Dagger()])
anet.PutUniTensors(["R","B","M","B_Conj"], \
[LR[p+2],A[p+1],M,A[p+1].Dagger().permute_(A[p+1].labels())])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

print('Sweep[r->l]: %d/%d, Loc: %d,Energy: %f' % (k, numsweeps, p, Ekeep[-1]))

Expand All @@ -172,21 +184,27 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
A[p+1] = cytnx.Contract(s,A[p+1]) ## absorb s into next neighbor.
A[p+1].relabels_(lbls[p+1]); #set the label back to be consistent

A[p].set_name(f"A{p}")
A[p+1].set_name(f"A{p+1}")

# update LR from left to right:
anet = cytnx.Network()
anet.FromString(["L: -2,-1,-3",\
"A: -1,-4,1",\
"M: -2,0,-4,-5",\
"A_Conj: -3,-5,2",\
"TOUT: 0;1,2"])
anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Dagger(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

print('Sweep[l->r]: %d/%d, Loc: %d,Energy: %f' % (k, numsweeps, p, Ekeep[-1]))

A[-1].set_rowrank_(2)
_,A[-1] = cytnx.linalg.Gesvd(A[-1],is_U=True,is_vT=False) ## last one.
A[-1].relabels_(lbls[-1]); #set the label back to be consistent
A[-1].set_name(f"A{Nsites-1}")

return Ekeep

Expand Down
41 changes: 33 additions & 8 deletions example/DMRG/dmrg_two_sites_dense.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,32 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
M[0,1] = M[2,3] = 2**0.5*sp.real()
M[0,2] = M[1,3] = 2**0.5*sm.real()
M = cytnx.UniTensor(M,0)
M.set_name("MPO")

L0 = cytnx.UniTensor(cytnx.zeros([4,1,1]), rowrank = 0) #Left boundary
R0 = cytnx.UniTensor(cytnx.zeros([4,1,1]), rowrank = 0) #Right boundary
L0[0,0,0] = 1.; R0[3,0,0] = 1.
L0.set_name("L0")
R0.set_name("R0")
L0[0,0,0] = 1.
R0[3,0,0] = 1.

lbls = [] # List for storing the MPS labels
A = [None for i in range(Nsites)]
A[0] = cytnx.UniTensor(cytnx.random.normal([1, d, min(chi, d)], 0., 1.), rowrank = 2)
A[0].relabels_(["0","1","2"])
lbls.append(["0","1","2"]) # store the labels for later convinience.
A[0].set_name("A0")

lbls = [] # List for storing the MPS labels
lbls.append(["0","1","2"]) # store the labels for later convenience.

for k in range(1,Nsites):
dim1 = A[k-1].shape()[2]; dim2 = d
dim3 = min(min(chi, A[k-1].shape()[2] * d), d ** (Nsites - k - 1))
A[k] = cytnx.UniTensor(cytnx.random.normal([dim1, dim2, dim3],0.,1.), rowrank = 2)
A[k].set_name(f"A{k}")

lbl = [str(2*k),str(2*k+1),str(2*k+2)]
A[k].relabels_(lbl)
lbls.append(lbl) # store the labels for later convinience.
lbls.append(lbl) # store the labels for later convenience.

LR = [None for i in range(Nsites+1)]
LR[0] = L0
Expand All @@ -84,23 +91,29 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
s, A[p] ,vt = cytnx.linalg.Gesvd(A[p])
A[p+1] = cytnx.Contract(cytnx.Contract(s,vt),A[p+1])

## Calculate enviroments:
A[p].set_name(f"A{p}")
A[p+1].set_name(f"A{p+1}")

## Calculate environments:
anet = cytnx.Network()
anet.FromString(["L: -2,-1,-3",\
"A: -1,-4,1",\
"M: -2,0,-4,-5",\
"A_Conj: -3,-5,2",\
"TOUT: 0,1,2"])
# or you can do: anet = cytnx.Network("L_AMAH.net")
anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Conj(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

# Recover the original MPS labels
A[p].relabels_(lbls[p])
A[p+1].relabels_(lbls[p+1])

_,A[-1] = cytnx.linalg.Gesvd(A[-1],is_U=True,is_vT=False) ## last one.
A[-1].relabels_(lbls[-1]) # Recover the original MPS labels
A[-1].set_name(f"A{Nsites-1}")

Ekeep = []
for k in range(1, numsweeps+1):
Expand All @@ -123,6 +136,9 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
A[p] = cytnx.Contract(A[p],s) # absorb s into next neighbor
A[p].relabels_(lbls[p]); # set the label back to be consistent

A[p].set_name(f"A{p}")
A[p+1].set_name(f"A{p+1}")

# update LR from right to left:
anet = cytnx.Network()
anet.FromString(["R: -2,-1,-3",\
Expand All @@ -131,14 +147,17 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
"B_Conj: 2,-5,-3",\
"TOUT: 0;1,2"])
# or you can do: anet = cytnx.Network("R_AMAH.net")
anet.PutUniTensors(["R","B","M","B_Conj"],[LR[p+2],A[p+1],M,A[p+1].Conj()])
anet.PutUniTensors(["R","B","M","B_Conj"], \
[LR[p+2],A[p+1],M,A[p+1].Dagger().permute_(A[p+1].labels())])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

print('Sweep[r->l]: %d/%d, Loc: %d,Energy: %f' % (k, numsweeps, p, Ekeep[-1]))

A[0].set_rowrank_(1)
_,A[0] = cytnx.linalg.Gesvd(A[0],is_U=False, is_vT=True)
A[0].relabels_(lbls[0]); #set the label back to be consistent
A[0].set_name("A0")

for p in range(Nsites-1):
dim_l = A[p].shape()[0]
Expand All @@ -158,6 +177,9 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
A[p+1] = cytnx.Contract(s,A[p+1]) ## absorb s into next neighbor.
A[p+1].relabels_(lbls[p+1]); #set the label back to be consistent

A[p].set_name(f"A{p}")
A[p+1].set_name(f"A{p+1}")

# update LR from left to right:
anet = cytnx.Network()
anet.FromString(["L: -2,-1,-3",\
Expand All @@ -167,14 +189,17 @@ def optimize_psi(psi, functArgs, maxit=2, krydim=4):
"TOUT: 0,1,2"])
# or you can do: anet = cytnx.Network("L_AMAH.net")

anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Conj(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
LR[p+1] = anet.Launch()
LR[p+1].set_name(f"LR{p+1}")

print('Sweep[l->r]: %d/%d, Loc: %d,Energy: %f' % (k, numsweeps, p, Ekeep[-1]))

A[-1].set_rowrank_(2)
_,A[-1] = cytnx.linalg.Gesvd(A[-1],is_U=True,is_vT=False) ## last one.
A[-1].relabels_(lbls[-1]); #set the label back to be consistent
A[-1].set_name(f"A{Nsites-1}")
return Ekeep

if __name__ == '__main__':
Expand Down
18 changes: 12 additions & 6 deletions example/TDVP/tdvp1_dense.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def get_energy(A, M):
"TOUT: 0,1,2"])
# or you can do: anet = cytnx.Network("L_AMAH.net")
for p in range(0, N):
anet.PutUniTensors(["L","A","A_Conj","M"],[L,A[p],A[p].Conj(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[L,A[p],A[p].Dagger().permute_(A[p].labels()),M])
L = anet.Launch()
E = cytnx.Contract(L, R0).item()
print('energy:', E)
Expand Down Expand Up @@ -138,7 +139,8 @@ def get_energy(A, M):
"A_Conj: -3,-5,2",\
"TOUT: 0,1,2"])
# or you can do: anet = cytnx.Network("L_AMAH.net")
anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Conj(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
LR[p+1] = anet.Launch()

# Recover the original MPS labels
Expand Down Expand Up @@ -175,7 +177,8 @@ def get_energy(A, M):
"B_Conj: 2,-5,-3",\
"TOUT: ;0,1,2"])
# or you can do: anet = cytnx.Network("R_AMAH.net")
anet.PutUniTensors(["R","B","M","B_Conj"],[LR[p+1],A[p],M,A[p].Conj()])
anet.PutUniTensors(["R","B","M","B_Conj"], \
[LR[p+1],A[p],M,A[p].Dagger().permute_(A[p].labels())])
old_LR = LR[p].clone()
if p != 0:
LR[p] = anet.Launch()
Expand Down Expand Up @@ -215,7 +218,8 @@ def get_energy(A, M):
"A_Conj: -3,-5,2",\
"TOUT: 0,1,2"])

anet.PutUniTensors(["L","A","A_Conj","M"],[LR[p],A[p],A[p].Conj(),M])
anet.PutUniTensors(["L","A","A_Conj","M"], \
[LR[p],A[p],A[p].Dagger().permute_(A[p].labels()),M])
old_LR = LR[p+1].clone()


Expand Down Expand Up @@ -246,15 +250,17 @@ def Local_meas(A, B, Op, site):
"TOUT: 2;4"])
for i in range(0, N):
if i != site:
anet.PutUniTensors(["l","A","B"],[l,A[i],B[i].Conj()])
anet.PutUniTensors(["l","A","B"], \
[l,A[i],B[i].Dagger().permute_(B[i].labels())])
l = anet.Launch()
else:
tmp = A[i].relabel(1, "_aux_up")
Op = Op.relabels(["_aux_up", "_aux_low"])
tmp = cytnx.Contract(tmp, Op)
tmp.relabel_("_aux_low", A[i].labels()[1])
tmp.permute_(A[i].labels())
anet.PutUniTensors(["l","A","B"],[l,tmp,B[i].Conj()])
anet.PutUniTensors(["l","A","B"], \
[l,tmp,B[i].Dagger().permute_(B[i].labels())])
l = anet.Launch()

return l.reshape(1).item()
Expand Down
22 changes: 13 additions & 9 deletions include/UniTensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4974,16 +4974,20 @@ namespace cytnx {

/**
@brief Take the transpose of the UniTensor.
@details This function will take the transpose of the UniTensor. If the UniTensor is
tagged (i.e. the Bonds are directional), it will swap the direction of the Bonds but
the rowrank will not change. If the UniTensor is untagged (i.e. the Bonds are
BondType::BD_REG), it will change the rowrank to the opposite side.
For fermionic UniTensors, the index order will be reversed without sign flips, and the
direction of all Bonds will swapped.
@return UniTensor
@details This function takes the transpose of a UniTensor:
1) Swaps the roles of left and right indices: index numbers k < rowrank become k + rowrank,
indices k' >= rowrank become k' - rowrank. For fermions, the order of the indices is
inverted instead.
2) Incoming legs become outgoing onces, and vice versa
3) The rowrank is set to rank - old rowrank, such that left indices become right indices and
vice versa.
@return UniTensor
@note Compared to Transpose_(), this function will return new UniTensor object.
@see Transpose_()
*/
@warning For fermionic UniTensors, the order of the indices is inverted, while for bosonic
UniTensors the role of the left-and right indices is exchanged without inverting the orders in
these two groups.
@see Transpose_()
*/
UniTensor Transpose() const {
UniTensor out;
out._impl = this->_impl->Transpose();
Expand Down
8 changes: 3 additions & 5 deletions src/BlockFermionicUniTensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1895,17 +1895,15 @@ namespace cytnx {
};

void BlockFermionicUniTensor::Transpose_() {
//[21 Aug 2024] This is a copy from BlockUniTensor;
// modify tag
// The index order is reversed without any sign flips!
std::vector<cytnx_int64> idxorder(this->_bonds.size());
std::size_t idxnum = this->bonds().size() - 1;
for (int i = 0; i <= idxnum; i++) {
cytnx_int64 idxnum = this->bonds().size() - 1;
for (cytnx_int64 i = 0; i <= idxnum; i++) {
this->bonds()[i].redirect_();
// this->bonds()[i].qnums() = this->bonds()[i].calc_reverse_qnums();
idxorder[i] = idxnum - i;
}
this->permute_nosignflip_(idxorder);
this->_rowrank = idxnum + 1 - this->_rowrank;
};

void BlockFermionicUniTensor::normalize_() {
Expand Down
14 changes: 11 additions & 3 deletions src/BlockUniTensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1214,11 +1214,19 @@ namespace cytnx {
};

void BlockUniTensor::Transpose_() {
// modify tag
for (int i = 0; i < this->bonds().size(); i++) {
const cytnx_int64 rank = this->bonds().size();
std::vector<cytnx_int64> idxorder(rank);
const cytnx_int64 oldrowrank = this->_rowrank;
this->_rowrank = rank - oldrowrank;
for (cytnx_int64 i = 0; i < this->_rowrank; i++) {
this->bonds()[i].redirect_();
// this->bonds()[i].qnums() = this->bonds()[i].calc_reverse_qnums();
idxorder[i] = i + oldrowrank;
}
for (cytnx_int64 i = this->_rowrank; i < rank; i++) {
this->bonds()[i].redirect_();
idxorder[i] = i - this->_rowrank;
}
this->permute_(idxorder);
};

void BlockUniTensor::normalize_() {
Expand Down
Loading
Loading