jcmgray / quimb

A python library for quantum information and many-body calculations including tensor networks.
http://quimb.readthedocs.io
Other
455 stars 107 forks source link

Contraction strategy "swap+split" conflict with swap gate #134

Closed sergimasot closed 1 year ago

sergimasot commented 1 year ago

What happened?

I encountered an error message when trying to contract a circuit with lots of manually added SWAP gates using the option "swap+split". I managed to reproduce it with the short code shown in the example, which represents a very simple quantum circuit with common gates.

What did you expect to happen?

The expected output is an MPS that encodes the output state of the given circuit.

Minimal Complete Verifiable Example

# initialize the circuit
test = quimb.tensor.Circuit(8,psi0=qtn.MPS_computational_state("00000000"),gate_opts={'contract':"swap+split"})

# create some entanglement
test.apply_gate('H',1)
test.apply_gate('CNOT',1,4)
test.apply_gate('CNOT',1,5)

v1 = 1

if v1:    # v1 of the error
    test.apply_gate('SWAP',0,6)
    test.apply_gate('CNOT',1,6)
    test.apply_gate('SWAP',0,6)
else:     # v2 of the error (this error message was the one I actually encountered in my original code)
    test.apply_gate('SWAP',0,6)
    test.apply_gate('CNOT',1,0)

Relevant log output

# v1
ValueError: 'output_inds' must be permutation of the current tensor indices, but {'k0', '_f88ed6AAABB', 'k5', '_f88ed6AAABD'} != {'_f88ed6AAABD', 'k6', '_f88ed6AAABB', 'k0', 'k5'}

# v2
ValueError: axes don't match array

Anything else we need to know?

I apologise if this is not a bug but a consequence of how "swap+split" works internally, but I see no reason it should stop working when the circuit already has some manually added swaps.

Environment

Tested in an empty environment with only Quimb's dependencies on 1.4.0 (latest); also happened with 1.3.0 but the second error was "repeated axis in transpose" instead.

jcmgray commented 1 year ago

Hi @sergimasot, thanks for the issue! It should just be a matter of allowing MatrixProductState.swap_sites_with_compress to handle the case when the sites aren't adjacent. I'll look into it.

jcmgray commented 1 year ago

This should be fixed by https://github.com/jcmgray/quimb/commit/335b1d6d4214e63831e232f0d0e76c59f1c850e0. Let me know if you still have any problems!

sergimasot commented 1 year ago

Thanks for fixing it so fast! The code snippet I prepared works now, although I had to make some extra changes to my original code to get it to work.

The reason is that if you initialize a circuit explicitly with an MPS (through psi0=qtn.MPS_computational_state("00000000"), for example), "swap+split" is recognized as a valid contraction option. However, for a generic quimb.tensor.Circuit without a psi0 initialization, this same option is not available anymore, so that adding "gate_opts=dict(contract="swap+split")" gives the error "ValueError: Option contract should be one of {False, True, 'swap-split-gate', 'auto-split-gate', 'reduce-split', 'split-gate', 'split'}, but got 'swap+split'.". Let me know if this is an inconsistency, as it seems!

jcmgray commented 1 year ago

Maybe it is not well documented, but if you want to use an MPS and this strategy, then the relevant class to use is CircuitMPS. Circuit I think casts psi0 as a TensorNetworkGenVector, which doesn't have the swap+split method, since there is no guarantee that the TN will remain in 1D form.

CircuitMPS on the other hand, keeps psi as an MPS and uses this gating method by default.

sergimasot commented 1 year ago

That makes a ton of sense; thank you for the clarification.