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

`tensor.Circuit.local_expectation` breaks with only 1 observable #187

Closed phyjoon closed 9 months ago

phyjoon commented 1 year ago

What happened?

The following code snippet executes well:

import quimb
circ = quimb.tensor.Circuit(1)
circ.apply_gate("H", 0, gate_round=0)
circ.local_expectation([quimb.pauli("X"), quimb.pauli("Y"), quimb.pauli("Z")], (0,))

while

import quimb
circ = quimb.tensor.Circuit(1)
circ.apply_gate("H", 0, gate_round=0)
circ.local_expectation([quimb.pauli("X")], (0,))

breaks with the following error message:

.../lib/python3.10/site-packages/quimb/tensor/circuit.py in ?(self, G, where, optimize, simplify_sequence, simplify_atol, simplify_equalize_norms, backend, dtype, target_size, rehearse)
   1741         TG = Tensor(data=G_data, inds=output_inds + b_inds + k_inds)
   1742 
   1743         rhoG = rho | TG
   1744 
-> 1745         rhoG.full_simplify_(output_inds=output_inds, **fs_opts)
   1746         rhoG.astype_(dtype)
   1747 
   1748         if rehearse == "tn":

.../lib/python3.10/site-packages/quimb/tensor/tensor_core.py in ?(self, seq, output_inds, atol, equalize_norms, cache, inplace, progbar, rank_simplify_opts, loop_simplify_opts, split_simplify_opts, custom_methods, split_method)
   9570                 elif meth == 'D':
   9571                     tn.diagonal_reduce_(output_inds=ix_o, atol=atol,
   9572                                         cache=cache)
   9573                 elif meth == 'R':
-> 9574                     tn.rank_simplify_(output_inds=ix_o, cache=cache,
   9575                                       equalize_norms=equalize_norms,
   9576                                       **rank_simplify_opts)
   9577                 elif meth == 'A':

.../lib/python3.10/site-packages/quimb/tensor/tensor_core.py in ?(self, output_inds, equalize_norms, cache, max_combinations, inplace)
   8603         def rank_weight(ind):
   8604             return (tn.ind_size(ind), -sum(tn.tensor_map[tid].ndim
   8605                                            for tid in tn.ind_map[ind]))
   8606 
-> 8607         queue = oset(sorted(count, key=rank_weight))
   8608 
   8609         # number of tensors for which there will be more pairwise combinations
   8610         # than max_combinations

.../lib/python3.10/site-packages/quimb/tensor/tensor_core.py in ?(ind)
   8603         def rank_weight(ind):
-> 8604             return (tn.ind_size(ind), -sum(tn.tensor_map[tid].ndim
   8605                                            for tid in tn.ind_map[ind]))

.../lib/python3.10/site-packages/quimb/tensor/tensor_core.py in ?(self, ind)
   8132     def ind_size(self, ind):
   8133         """Find the size of ``ind``.
   8134         """
-> 8135         tid = next(iter(self.ind_map[ind]))
   8136         return self.tensor_map[tid].ind_size(ind)

KeyError: '_2f1465AAAAQ'

What did you expect to happen?

No response

Minimal Complete Verifiable Example

import quimb
circ = quimb.tensor.Circuit(1)
circ.apply_gate("H", 0, gate_round=0)
circ.local_expectation([quimb.pauli("X")], (0,))

Relevant log output

No response

Anything else we need to know?

No response

Environment

Yes. It's 1.5.0

jcmgray commented 9 months ago

Thanks for raising the issue, sorry to be slow getting to it! The problem appears to be that during simplification the squeeze removes the size 1 stacked index despite it being marked in output_inds. Fix incoming.