Sorry for not coming back to this earlier.
The real question is: what do you mean with "random" when talking about an MPS?
When you draw a "random" state uniformly from the Hilbert space, it has a volume law entanglement; in fact it is almost maximally entangled!
Therefore, it won't work for large systems to draw a random vector uniformly from the Hilbertspace and convert it into an MPS.
You might want to a get an MPS with fixed (maximal) bond dimensions and "random" entries. But this is problematic as well:
A big point of TenPy is also to exploit symmetries, and these symmetries imply that certain entries of your tensors cannot be non-zero. To initialize an MPS compatible with the symmetries of your Hamiltonian, you need to specify the "LegCharge"s for these symmetries on the bonds of the MPS.
If you are willing to do that, you can use these LegCharges to initialize "B" matrices (using npc.Array.from_frunc, if you want to provide e.g. np.random.gaussian), and just initialize the MPS with them. However, specifying these charges is not really trivial...
I think the best way is with the RandomUnitaryEvolution you mentioned:
You can first initialize a product state, and then apply a few random two-site unitaries to it (which is a very well defined thing).
Be aware that this generates a state with only short-range entanglement (depending on how many steps you do with the random unitary evolution),
and that the bond dimension grows exponentially with the number of steps you do, so you might need to truncate strongly.
Since this is a simple TEBD-like scheme, the truncation will completely destroy the "canonical form", so you need to bring the state back into canonical form (assuming that you need that).
Here's an example code:
Code: Select all
# assuming that "M" is a model
# first initialize a product state
product_state = (["up", "down"] * (M.lat.N_sites))[:M.lat.N_sites] # assuming you have spin sites
psi = MPS.from_product_state(M.lat.mps_sites(), product_state, bc=M.lat.bc_MPS)
TEBD_params = {'N_steps': 10, 'trunc_params':{'chi_max': 20}, 'verbose': 0}
eng = tebd.RandomUnitaryEvolution(psi, TEBD_params)
eng.run()
psi.canonical_form() # important if you truncate strongly during the random evolution!!!
# now psi has somewhat random entries
It's your responsibility to choose the initial state in a sensible way, e.g. if you have Sz conservation, choosing all up spins would be a bad idea...
Disclaimer: no guarantees whatsoever about the randomness / random properties of the generated state