Repository: google/TensorNetwork

Issue:
numpy.linalg.LinAlgError: SVD did not converge
Thx for the current repo. 

 I want to use `TensorNetwork` package to simulate time evolution of transverse ising model with itebd algorithm.
but it seems svd throws out error like this,  can anyone give answers or any hints?

- does the `split_node_full_svd` used in `apply_two_site_gate()` has parameter like `max_iter` or something else?
- are there demo code snippets for using `tn.InfiniteMPS` or `tn.FiniteMPS` with tebd algorithm?

thanks~

```shell
$ python evolution.py 
1727.9739590611944
6.306919862739928e-15
0.014427307657060863
7.142939906200455e-15
0.0015813901699260678
7.156663235322543e-15
../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/numpy_backend.py:90: RuntimeWarning: invalid value encountered in sqrt
  return np.sqrt(tensor)

Intel MKL ERROR: Parameter 4 was incorrect on entry to DLASCL.

Intel MKL ERROR: Parameter 4 was incorrect on entry to DLASCL.
Traceback (most recent call last):
  File "evolution.py", line 83, in <module>
    itebd_ising(N=10)
  File "evolution.py", line 76, in itebd_ising
    imps_state.canonicalize()
  File "../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/matrixproductstates/infinite_mps.py", line 276, in canonicalize
    relative=True)
  File "..anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/numpy_backend.py", line 627, in svd
    relative=relative)
  File "../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/decompositions.py", line 36, in svd
    u, s, vh = np.linalg.svd(tensor, full_matrices=False)
  File "<__array_function__ internals>", line 6, in svd
  File "../anaconda3/envs/tf2/lib/python3.7/site-packages/numpy/linalg/linalg.py", line 1636, in svd
    u, s, vh = gufunc(a, signature=signature, extobj=extobj)
  File "../anaconda3/envs/tf2/lib/python3.7/site-packages/numpy/linalg/linalg.py", line 106, in _raise_linalgerror_svd_nonconvergence
    raise LinAlgError("SVD did not converge")
numpy.linalg.LinAlgError: SVD did not converge
```


> code script shown below,
```python
import tensornetwork as tn 
import numpy as np 
import tensorflow as tf
# tn.set_default_backend('numpy')

def itebd_ising(N=1000):
    J=1.0; 
    g=0.5; 
    chi=50
    d=2;  
    delta=0.05;
    # N=3000;

    # two-site Hamiltonian
    H = np.array([[J, -g/2, -g/2,0],
                [-g/2, -J,0,-g/2],
                [-g/2.,0,-J,-g/2.],
                [0,-g/2.,-g/2.,J]])
    w,v=np.linalg.eig(H)
    U=np.reshape(np.dot(np.dot(v,np.diag(np.exp(-delta*w))),np.transpose(v)),(2,2,2,2))

    imps_state=tn.InfiniteMPS.random(d=[2,2], D=[chi,chi,chi], dtype=np.complex128)
    print(imps_state.check_canonical())
    imps_state.canonicalize()
    print(imps_state.check_canonical())
    truncation=[]
    for step in range(N):
        if step%2==0:
            truncation_err = imps_state.apply_two_site_gate(U, site1=0, site2=1,max_singular_values=chi)
        else:
            truncation_err = imps_state.apply_two_site_gate(np.transpose(U,(1,0,3,2)), site1=0, site2=1,max_singular_values=chi)
        truncation.append(np.linalg.norm(truncation_err))
        imps_state.canonicalize()
        print(np.linalg.norm(truncation_err))
        print(imps_state.check_canonical())
        # pdb.set_trace()
    print("-"*20)
    print(sum(truncation))
if __name__ == "__main__":
    itebd_ising(N=10)
```


Discussion:
I think there is a NaN or an Inf somewhere in imps_state

On Fri, Jan 8, 2021, 21:22 Papageno2 <notifications@github.com> wrote:

> Thx for the current repo.
>
> I want to use TensorNetwork package to simulate time evolution of
> transverse ising model with itebd algorithm.
> but it seems svd throws out error like this, can anyone give answers or
> any hints?
>
>    - does the split_node_full_svd used in apply_two_site_gate() has
>    parameter like max_iter or something else?
>    - are there demo code snippets for using tn.InfiniteMPS or tn.FiniteMPS
>    with tebd algorithm?
>
> thanks~
>
> $ python evolution.py
> 1727.9739590611944
> 6.306919862739928e-15
> 0.014427307657060863
> 7.142939906200455e-15
> 0.0015813901699260678
> 7.156663235322543e-15
> ../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/numpy_backend.py:90: RuntimeWarning: invalid value encountered in sqrt
>   return np.sqrt(tensor)
>
> Intel MKL ERROR: Parameter 4 was incorrect on entry to DLASCL.
>
> Intel MKL ERROR: Parameter 4 was incorrect on entry to DLASCL.
> Traceback (most recent call last):
>   File "evolution.py", line 83, in <module>
>     itebd_ising(N=10)
>   File "evolution.py", line 76, in itebd_ising
>     imps_state.canonicalize()
>   File "../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/matrixproductstates/infinite_mps.py", line 276, in canonicalize
>     relative=True)
>   File "..anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/numpy_backend.py", line 627, in svd
>     relative=relative)
>   File "../anaconda3/envs/tf2/lib/python3.7/site-packages/tensornetwork/backends/numpy/decompositions.py", line 36, in svd
>     u, s, vh = np.linalg.svd(tensor, full_matrices=False)
>   File "<__array_function__ internals>", line 6, in svd
>   File "../anaconda3/envs/tf2/lib/python3.7/site-packages/numpy/linalg/linalg.py", line 1636, in svd
>     u, s, vh = gufunc(a, signature=signature, extobj=extobj)
>   File "../anaconda3/envs/tf2/lib/python3.7/site-packages/numpy/linalg/linalg.py", line 106, in _raise_linalgerror_svd_nonconvergence
>     raise LinAlgError("SVD did not converge")
> numpy.linalg.LinAlgError: SVD did not converge
>
> code script shown below,
>
> import tensornetwork as tn import numpy as np import tensorflow as tf# tn.set_default_backend('numpy')
> def itebd_ising(N=1000):
>     J=1.0;
>     g=0.5;
>     chi=50
>     d=2;
>     delta=0.05;
>     # N=3000;
>
>     # two-site Hamiltonian
>     H = np.array([[J, -g/2, -g/2,0],
>                 [-g/2, -J,0,-g/2],
>                 [-g/2.,0,-J,-g/2.],
>                 [0,-g/2.,-g/2.,J]])
>     w,v=np.linalg.eig(H)
>     U=np.reshape(np.dot(np.dot(v,np.diag(np.exp(-delta*w))),np.transpose(v)),(2,2,2,2))
>
>     imps_state=tn.InfiniteMPS.random(d=[2,2], D=[chi,chi,chi], dtype=np.complex128)
>     print(imps_state.check_canonical())
>     imps_state.canonicalize()
>     print(imps_state.check_canonical())
>     truncation=[]
>     for step in range(N):
>         if step%2==0:
>             truncation_err = imps_state.apply_two_site_gate(U, site1=0, site2=1,max_singular_values=chi)
>         else:
>             truncation_err = imps_state.apply_two_site_gate(np.transpose(U,(1,0,3,2)), site1=0, site2=1,max_singular_values=chi)
>         truncation.append(np.linalg.norm(truncation_err))
>         imps_state.canonicalize()
>         print(np.linalg.norm(truncation_err))
>         print(imps_state.check_canonical())
>         # pdb.set_trace()
>     print("-"*20)
>     print(sum(truncation))if __name__ == "__main__":
>     itebd_ising(N=10)
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/google/TensorNetwork/issues/896>, or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAINHBQXJVYLKQHUVZZ5XTTSY64V5ANCNFSM4V3GZTMA>
> .
>


Resolving patch:
diff --git a/tensornetwork/matrixproductstates/infinite_mps.py b/tensornetwork/matrixproductstates/infinite_mps.py
--- a/tensornetwork/matrixproductstates/infinite_mps.py
+++ b/tensornetwork/matrixproductstates/infinite_mps.py
@@ -125,6 +125,7 @@ def transfer_matrix_eigs(self,
     """
     D = self.bond_dimensions[0]
 
+
     def mv(vector):
       result = self.unit_cell_transfer_operator(
           direction, self.backend.reshape(vector, (D, D)))
@@ -137,10 +138,20 @@ def mv(vector):
       initial_state = self.backend.reshape(initial_state,
                                            (self.bond_dimensions[0]**2,))
 
-    #note: for real dtype eta and dens are real.
-    #but scipy.linalg.eigs returns complex dtypes in any case
-    #since we know that for an MPS transfer matrix the largest
-    #eigenvalue and corresponding eigenvector are real
+    if D == 1:
+      # special case of non boundary entanglement
+      Z = self.backend.norm(initial_state)
+      initial_state = initial_state / Z
+      result = mv(initial_state)
+      eigval = self.backend.norm(result)
+      result = self.backend.reshape(
+          result, (self.bond_dimensions[0], self.bond_dimensions[0]))
+      return eigval, result
+
+    # note: for real dtype eta and dens are real.
+    # but scipy.linalg.eigs returns complex dtypes in any case
+    # since we know that for an MPS transfer matrix the largest
+    # eigenvalue and corresponding eigenvector are real
     # we cast them.
     eta, dens = self.backend.eigs(
         A=mv,
@@ -197,6 +208,9 @@ def canonicalize(self,
     Returns:
       None
     """
+    if pseudo_inverse_cutoff is None:
+      pseudo_inverse_cutoff = self.backend.eps(self.dtype)
+
     if self.center_position is None:
       self.center_position = 0
 
@@ -220,12 +234,11 @@ def canonicalize(self,
     # eigvals_left and u_left are both `Tensor` objects
     eigvals_left, u_left = self.backend.eigh(l)
     eigvals_left /= self.backend.norm(eigvals_left)
-    if pseudo_inverse_cutoff:
-      mask = eigvals_left <= pseudo_inverse_cutoff
+    mask = eigvals_left <= pseudo_inverse_cutoff
+    eigvals_left = self.backend.index_update(eigvals_left, mask, 0.0)
 
     inveigvals_left = 1.0 / eigvals_left
-    if pseudo_inverse_cutoff:
-      inveigvals_left = self.backend.index_update(inveigvals_left, mask, 0.0)
+    inveigvals_left = self.backend.index_update(inveigvals_left, mask, 0.0)
 
     sqrtl = ncon(
         [u_left, self.backend.diagflat(self.backend.sqrt(eigvals_left))],
@@ -249,18 +262,15 @@ def canonicalize(self,
     # eigvals_right and u_right are both `Tensor` objects
     eigvals_right, u_right = self.backend.eigh(r)
     eigvals_right /= self.backend.norm(eigvals_right)
-    if pseudo_inverse_cutoff:
-      mask = eigvals_right <= pseudo_inverse_cutoff
+    mask = eigvals_right <= pseudo_inverse_cutoff
 
+    eigvals_right = self.backend.index_update(eigvals_right, mask, 0.0)
     inveigvals_right = 1.0 / eigvals_right
-    if pseudo_inverse_cutoff:
-      inveigvals_right = self.backend.index_update(inveigvals_right, mask, 0.0)
-
+    inveigvals_right = self.backend.index_update(inveigvals_right, mask, 0.0)
     sqrtr = ncon(
         [u_right, self.backend.diagflat(self.backend.sqrt(eigvals_right))],
         [[-1, 1], [1, -2]],
         backend=self.backend.name)
-
     inv_sqrtr = ncon([
         self.backend.diagflat(self.backend.sqrt(inveigvals_right)),
         self.backend.conj(u_right)


Test patch: