# Uniqueness/convention for MPS truncation with maxdim

Hi,

I want to clarify a confusion regarding the uniqueness of MPS truncation with maxdim set, and if not unique, how to know which convention is employed when. First, I’ll explain and then share full working code at the bottom.

Given a pure state |\phi \rangle as a vector phi, I constructed its full MPS and a truncated MPS using

psi = MPS(phi, sites)
psi_trunc1 = MPS(phi,sites;maxdim=1)


Out of curiosity, I then tried truncating differently using

psi_trunc2 = truncate(psi; maxdim=1)
psi_trunc3 = truncate(psi_trunc1; maxdim=1)


which yields

norm(psi_trunc1 - psi_trunc2) == 0.16173304677093372 # true
norm(normalize(psi_trunc1) - normalize(psi_trunc2)) == 0.2795589946197962 # true


showing they are different. They are still different when compared to original psi as we see here

norm(psi - normalize(psi_trunc1)) == 0.920470267476006 # true
norm(psi - normalize(psi_trunc2)) == 0.9161358132015018 # true


Showing that—in this sense— psi_trunc2 is a better truncated approximation of psi then psi_trunc1. At the same time,

norm(psi_trun1 - psi_trunc3) == 2.31492981972618e-16 # true


so truncate does not improve any pre-truncated MPS.

My questions are as follows

1. Is this non-uniqueness intended? My guess is that psi_trunc1 is truncated “on the fly” as MPS is being built whereas psi_trunc2 has a different convention since its pre-built. It’s not totally obvious these should be different, but it is believable.
2. If (1) is true, how do I know which convention is being employed when I call truncate?

Thanks for any help! I will continue to investigate, but I wanted to go ahead and ask a question in case diving into source code gets my head spinning.

Full code now shared

using RandomMatrices, ITensors

# form random pure state
n = 5
d = 2^n
u = rand(Haar(2), d)
phi = zeros(d)
phi[1] = 1.0
phi = u * phi

# for reproroducibility, just hard-code phi as mine like this
phi = ComplexF64[0.02082573551834055 - 0.011486940165270298im, -0.2209176466147129 + 0.14816797059292863im, 0.1904930195782806 + 0.20009461043825688im, -0.03695721322295389 - 0.12055214694742081im, 0.11413886371841545 + 0.22280207052268539im, -0.07005961574810946 - 0.12168592757238036im, 0.0782150912211017 + 0.07564564577407752im, -0.014237075147016814 + 0.0332819161182519im, -0.020029723418169963 - 0.03126543581612971im, 0.05916327854104368 - 0.12211287691683469im, -0.11449570927724294 + 0.0770756665654759im, -0.3443895945692257 - 0.12475781451160668im, -0.0007183900070949906 - 0.04456470829809399im, -0.0594125322384794 - 0.1165167655251047im, 0.07203368525918435 + 0.16017081679131456im, -0.03898051396853872 - 0.06801691967269073im, -0.17641138849666008 - 0.11775259193972928im, -0.03716007094152457 + 0.3109832551976374im, -0.03335159670380818 - 0.011845017761382111im, -0.14999890976471794 + 0.03660844117005592im, 0.1500551129063466 - 0.006042945034976571im, 0.10527627885655418 - 0.05181822327637im, 0.1280788988900208 + 0.061264981456989415im, 0.035503129122248164 - 0.03382504210110942im, 0.0959318299558157 + 0.031605012897989386im, 0.1668068223126639 + 0.12579753067096974im, -0.03888604840428345 + 0.13506435105185532im, -0.28933580176893675 + 0.043137765686808924im, -0.1009587769017696 - 0.09855299909683869im, 0.02905982650685869 + 0.16738610563855635im, -0.12115355412340761 + 0.19409738468496976im, -0.12080327793602866 - 0.09938303044950068im]

# get matrix product state representation from above
sites = siteinds(2, n)
psi = MPS(phi, sites)
psi_trunc1 = MPS(phi,sites;maxdim=1)
psi_trunc2 = truncate(psi; maxdim=1)
psi_trunc3 = truncate(psi_trunc1; maxdim=1)


Thanks for the detailed question. I’m fairly certain this behavior is not intended. Rather we just wrote the code inside of truncate versus the code inside the MPS constructor in slightly different ways, so that the results end up being similar but not exactly the same. How important is it for your application that you get the optimal product state (maxdim=1) approximation of your state? This mismatch of approximations could be a good improvement for ITensor, so if you’d like to file an issue on Github or even better contribute a change to the code (pull request) you’d be welcome.

1 Like

Yeah this looks like a bug, maybe we aren’t gauging the state properly in one of those functions.

1 Like

Thanks for your input. I don’t have an specific downstream application in mind, but indeed, that is a good way to phrase it (i.e. optimal product state is not consistent) for a Github issue and potential future pull request on ITensor.

Instead, I was just curious (on an implementation level) how bond truncation and subsequent normalization was actually performed as a precise equation/ algorithm. In particular because normalization is not a unique procedure and being a novice to MPS, I wasn’t certain if bond-truncation was unique or not either. From my understanding, the truncation should be unique, so upon finding it wasn’t in the code, I raised this issue first.

Bond truncation should be unique, it is implement as a series of SVDs.

1 Like