Repository: scipy/scipy

Issue:
lobpcg maxiter=None Exception has occurred: TypeError
lobpcg with maxiter=None results in Exception has occurred: TypeError
as reported in https://github.com/scipy/scipy/pull/10830#issuecomment-535724447

#### Reproducing code example:
```python
import numpy as np
from scipy.sparse import diags
from scipy.sparse.linalg.eigen.lobpcg import lobpcg

n = 50
m = 4
vals = -np.arange(1, n + 1)
A = diags([vals], [0], (n, n))
A = A.astype(np.float32)
X = np.random.randn(n, m)
X=X.astype(np.float32)
eigvals, _ = lobpcg(A, X, tol=1e-8, maxiter=None, verbosityLevel=1)
```

#### Error message:
```python
Exception has occurred: TypeError
'<' not supported between instances of 'int' and 'NoneType'
  line 422, in lobpcg
    while iterationNumber < maxIterations:
```

#### Scipy/Numpy/Python version information:
latest master
lobpcg maxiter=None Exception has occurred: TypeError
lobpcg with maxiter=None results in Exception has occurred: TypeError
as reported in https://github.com/scipy/scipy/pull/10830#issuecomment-535724447

#### Reproducing code example:
```python
import numpy as np
from scipy.sparse import diags
from scipy.sparse.linalg.eigen.lobpcg import lobpcg

n = 50
m = 4
vals = -np.arange(1, n + 1)
A = diags([vals], [0], (n, n))
A = A.astype(np.float32)
X = np.random.randn(n, m)
X=X.astype(np.float32)
eigvals, _ = lobpcg(A, X, tol=1e-8, maxiter=None, verbosityLevel=1)
```

#### Error message:
```python
Exception has occurred: TypeError
'<' not supported between instances of 'int' and 'NoneType'
  line 422, in lobpcg
    while iterationNumber < maxIterations:
```

#### Scipy/Numpy/Python version information:
latest master


Discussion:

Resolving patch:
diff --git a/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py b/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py
--- a/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py
+++ b/scipy/sparse/linalg/eigen/lobpcg/lobpcg.py
@@ -127,7 +127,7 @@ def _get_indx(_lambda, num, largest):
 
 def lobpcg(A, X,
            B=None, M=None, Y=None,
-           tol=None, maxiter=20,
+           tol=None, maxiter=None,
            largest=True, verbosityLevel=0,
            retLambdaHistory=False, retResidualNormsHistory=False):
     """Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG)
@@ -157,7 +157,7 @@ def lobpcg(A, X,
         Solver tolerance (stopping criterion).
         The default is ``tol=n*sqrt(eps)``.
     maxiter : int, optional
-        Maximum number of iterations.  The default is ``maxiter=min(n, 20)``.
+        Maximum number of iterations.  The default is ``maxiter = 20``.
     largest : bool, optional
         When True, solve for the largest eigenvalues, otherwise the smallest.
     verbosityLevel : int, optional
@@ -287,7 +287,8 @@ def lobpcg(A, X,
     blockVectorX = X
     blockVectorY = Y
     residualTolerance = tol
-    maxIterations = maxiter
+    if maxiter is None:
+        maxiter = 20
 
     if blockVectorY is not None:
         sizeY = blockVectorY.shape[1]
@@ -414,7 +415,7 @@ def lobpcg(A, X,
     iterationNumber = -1
     restart = True
     explicitGramFlag = False
-    while iterationNumber < maxIterations:
+    while iterationNumber < maxiter:
         iterationNumber += 1
         if verbosityLevel > 0:
             print('iteration %d' % iterationNumber)


Test patch:
diff --git a/scipy/sparse/linalg/eigen/lobpcg/tests/test_lobpcg.py b/scipy/sparse/linalg/eigen/lobpcg/tests/test_lobpcg.py
--- a/scipy/sparse/linalg/eigen/lobpcg/tests/test_lobpcg.py
+++ b/scipy/sparse/linalg/eigen/lobpcg/tests/test_lobpcg.py
@@ -299,6 +299,23 @@ def test_random_initial_float32():
     assert_allclose(eigvals, -np.arange(1, 1 + m), atol=1e-2)
 
 
+def test_maxit_None():
+    """Check lobpcg if maxit=None runs 20 iterations (the default)
+    by checking the size of the iteration history output, which should
+    be the number of iterations plus 2 (initial and final values).
+    """
+    np.random.seed(1566950023)
+    n = 50
+    m = 4
+    vals = -np.arange(1, n + 1)
+    A = diags([vals], [0], (n, n))
+    A = A.astype(np.float32)
+    X = np.random.randn(n, m)
+    X = X.astype(np.float32)
+    _, _, l_h = lobpcg(A, X, tol=1e-8, maxiter=20, retLambdaHistory=True)
+    assert_allclose(np.shape(l_h)[0], 20+2)
+
+
 @pytest.mark.slow
 def test_diagonal_data_types():
     """Check lobpcg for diagonal matrices for all matrix types.