Closed JustinS6626 closed 3 years ago
I think it would help if you detailed a bit what are trying to do overall? For instance, a MERA can be thought of as a circuit in both directions, could be added to the end of the circuit or could be also be the input to a circuit. Are you trying to measure and then continue evolving? Or do you just need measurements at the end?
Thank you very much again for your help! My preferred order of operations in this case would be to evolve and then measure. In terms of which configuration would work (i.e. MERA as output or MERA as input), I am not sure yet which would be preferable for my application, so I would be interested to know the evolution and measurement process for both.
Actually, I was particularly wondering about the case in which the MERA is the end of the circuit. What are the steps that I would use to evolve and measure it given the object class?
I guess I'm still not certain what exactly what you are trying to do:
Maybe writing some high level pseudo-code describing roughly your application and what you want to feed into your simulation and what you want to get out would help?
What I am hoping to do can be described using the following pseudocode:
Input: psi_0 (4-qubit state-vector)
Circuit Operation with output psi
CNOT(psi_0[0, 1]) CNOT(psi_0[1, 2]) CNOT(psi_0[2, 3]) U(psi_0) #Where U is an unspecified 4-qubit unitary operator
Give psi as input to MERA at open indices Measure resulting MERA with Pauli-Z operator
OK I see. So one thing is that the version of a MERA
implemented in quimb
is just as a wavefunction, i.e. it just has one set of open indices - the 'physical' indices at the bottom. If you 'input' a circuit wavefunction to these then what you have is a scalar - an overlap between the two wavefunctions. I.e. there is nothing to measure (unless you set dangle=True
then you will have a single output index of size max_bond
).
You can think of the isometries in a MERA as projecting/measuring the zero state out of unitaries, or in reverse, inputting the zero state. Is it this view of MERA you are interested in?
In other words, what does 'measuring the MERA' mean for you? sampling bitstrings / a single maybe non-qubit index? or computing an expectation?
The type of MERA that I had in mind was not so much a computationally parsimonious expression for a large wavefunction as a hierarchy of operations on the input state vector. Is there a way to do this just with a Quimb circuit structure in a way that is outside the capabilities of a standard quantum circuit? What I am trying to say is, I want to implement something structurally similar to the MERA, but which can carry out quantum algorithms on 1D, and ideally 2D many-body states. Would the circuit class allow me to do something like that?
OK yeah I suspect so - the circuit class is '1D' only in reference to how the qubits are labelled/enumerated, but there is no limits on applying gates at long range, mimicking the tensors higher up in a MERA. The main difference is that in a normal MERA the bonds can grow so you can't think of everything as qubit operations.
But if you just wanted to apply a pattern of ever fewer but more long range gates, then quimb
is very suited to that, the fiddly part is really just denoting the structure to use. Here's an example of a binary 'MERA circuit':
%config InlineBackend.figure_formats = ['svg']
import quimb as qu
import quimb.tensor as qtn
L = 6
N = 2**L
circ = qtn.Circuit(2**L)
for l in range(L):
scale = 2**l
for i in range(0, 1 << (L - l), 2):
circ.su4(*qu.randn(15), scale * i, scale * (i + 1) % N)
for i in range(1, 1 << (L - l), 2):
circ.su4(*qu.randn(15), scale * i, scale * (i + 1) % N)
circ.psi.draw(color=circ.psi.site_tags, legend=False)
You can see there are now 'output' indices throughout the MERA.
Despite being 64 qubits, quimb
can still efficiently sample from it, even without invoking a high quality contraction path optimizer:
for b in circ.sample(10, group_size=8):
print(b)
# 0101111101111100111001010000010110111100011010001111111100100100
# 1100001001001100100011101000100011001000011100101110110111100010
# 1110110100000000001001010111111001011000101010001101100100100101
# 0111111111010010000111100000110000000110000100000101000000100000
# 1101010001110011000000101111000110010100001101000100110010100001
# 0100011010010111001110001011100000011101111100001101111111100100
# 1110011011011101001100010010110100001100000111000101101000100010
# 1010100000010011000111011000000001010000000100010101010011010100
# 0100101101101010101101110000111110010101010110000110011111110100
# 0011010100110011000000111111100110110010100000001100110000101110
Just to follow up (and because pictures of MERA are always enjoyable), to build the circuit in the opposite direction is simply a matter of putting in:
for l in reversed(range(L)):
...
circ.psi.draw(
color='PSI0',
highlight_inds=circ.psi.site_inds,
legend=False,
)
Sorry about the delay. Thank you very much for your help! I managed to get the MERA circuit set up. Those are some really beautiful MERA graph examples!
This is related to my earlier question about applying gates to a MERA architecture: https://github.com/jcmgray/quimb/issues/75 When I use the circuit approach, the object that is created is an instance of the TensorNetwork1D class, but is not a MERA or a MatrixProductState. I am now wondering how to evolve this state (assuming the the application of the application of the gates and the MERA tensors does not evolve the state automatically), and how to convert it to state vector or density matrix form in order to call the quimb.calc.measure function on the state.