jcmgray / quimb

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

Problem with default backend #130

Closed steve-jeffrey closed 2 years ago

steve-jeffrey commented 2 years ago

What happened?

In some situations a backend cannot be provided and the default None results in an AttributeError.

For example, when calling sample() there are a couple of function calls in the call tree:

quimb.tensor.circuit.sample()
  ⤷ quimb.tensor.circuit.compute_marginal()
      ⤷ quimb.tensor.circuit.get_rdm_lightcone_simplified()
          ⤷ quimb.tensor.tensor_core.full_simplify()
              ⤷ quimb.tensor.tensor_core.rank_simplify()
                  ⤷ quimb.tensor.tensor_core.contract()
                      ⤷ quimb.tensor.tensor_core.tensor_contract()
                          ⤷ quimb.tensor.contraction.get_contract_backend()

where the backend is not passed through (either explicitly, or included in **kwargs). Consequently the backend defaults to None and an AttributeError is raised when the ContractExpression is evaluated (the exception is raised when opt-einsum checks if the backend is available; see the call to backends.has_backend(backend) here.

If the quantum circuit example:

import random
import quimb as qu
import quimb.tensor as qtn

N = 5  # Original example had N = 80
circ = qtn.Circuit(N)

regs = list(range(N))
random.shuffle(regs)

circ.apply_gate('H', regs[0])

for i in range(N - 1):
    circ.apply_gate('CNOT', regs[i], regs[i + 1])

for b in circ.sample(1):
    print(b)

is run, the truncated stack trace is:

File "/test-area/quimb_env/lib/python3.7/site-packages/opt_einsum/backends/dispatch.py", line 145, in has_backend
    return backend.lower() in CONVERT_BACKENDS
AttributeError: 'NoneType' object has no attribute 'lower'

The problem appears to have been introduced in commit 830b71d

What did you expect to happen?

The call to quimb.tensor.contraction.get_contract_backend() should return a usable backend.

Minimal Complete Verifiable Example

python3 -m venv quimb_env
. ./quimb_env/bin/activate
pip3 install opt-einsum jax jaxlib numba autoray kahypar mypy optax psutil tqdm

mkdir src
cd src
git clone https://github.com/jcmgray/quimb.git
cd quimb
export PYTHONPATH=<path to your test area>/src/quimb

git checkout 8f6a681
python example.py --> fails (example.py is the circuit simulation example shown above)

git checkout 5bced56
python example.py  --> succeeds

Relevant log output

Traceback (most recent call last):
  File "example.py", line 16, in <module>
    for b in circ.sample(1):
  File "/test-area/src/quimb/quimb/tensor/circuit.py", line 2077, in sample
    target_size=target_size,
  File "/test-area/src/quimb/quimb/tensor/circuit.py", line 1785, in compute_marginal
    nm_lc = self.get_rdm_lightcone_simplified(region, **fs_opts)
  File "/test-area/src/quimb/quimb/tensor/circuit.py", line 1310, in get_rdm_lightcone_simplified
    equalize_norms=equalize_norms)
  File "/test-area/src/quimb/quimb/tensor/tensor_core.py", line 7928, in full_simplify
    **rank_simplify_opts)
  File "/test-area/src/quimb/quimb/tensor/tensor_core.py", line 7122, in rank_simplify
    tab = ta.contract(tb, output_inds=out_ab)
  File "/test-area/src/quimb/quimb/tensor/tensor_core.py", line 1950, in contract
    return tensor_contract(self, *others, output_inds=output_inds, **opts) 
  File "/test-area/src/quimb/quimb/tensor/tensor_core.py", line 235, in tensor_contract
    data_out = expression(*arrays, backend=backend)
  File "/test-area/quimb_env/lib/python3.7/site-packages/opt_einsum/contract.py", line 760, in __call__
    if backends.has_backend(backend) and all(isinstance(x, np.ndarray) for x in arrays):
  File "/test-area/quimb_env/lib/python3.7/site-packages/opt_einsum/backends/dispatch.py", line 145, in has_backend
    return backend.lower() in CONVERT_BACKENDS
AttributeError: 'NoneType' object has no attribute 'lower'

Anything else we need to know?

No response

Environment

Python 3.7 and 3.8 Fedora 35 Quimb commits as noted above

jcmgray commented 2 years ago

Thanks - should be fixed by latest commit, and long-term I've opened a PR on opt_einsum to allow backend=None as its tripped me a few times.