first commit
This commit is contained in:
5
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__init__.py
vendored
Normal file
5
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__init__.py
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
"""
|
||||
External, bundled dependencies.
|
||||
|
||||
"""
|
||||
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/__init__.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/_arff.cpython-39.pyc
vendored
Normal file
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/_arff.cpython-39.pyc
vendored
Normal file
Binary file not shown.
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/_lobpcg.cpython-39.pyc
vendored
Normal file
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/_lobpcg.cpython-39.pyc
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/conftest.cpython-39.pyc
vendored
Normal file
BIN
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/__pycache__/conftest.cpython-39.pyc
vendored
Normal file
Binary file not shown.
1107
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_arff.py
vendored
Normal file
1107
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_arff.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
763
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_lobpcg.py
vendored
Normal file
763
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_lobpcg.py
vendored
Normal file
@@ -0,0 +1,763 @@
|
||||
"""
|
||||
scikit-learn copy of scipy/sparse/linalg/eigen/lobpcg/lobpcg.py v1.8.0
|
||||
to be deleted after scipy 1.3.0 becomes a dependency in scikit-lean
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG).
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] A. V. Knyazev (2001),
|
||||
Toward the Optimal Preconditioned Eigensolver: Locally Optimal
|
||||
Block Preconditioned Conjugate Gradient Method.
|
||||
SIAM Journal on Scientific Computing 23, no. 2,
|
||||
pp. 517-541. :doi:`10.1137/S1064827500366124`
|
||||
|
||||
.. [2] A. V. Knyazev, I. Lashuk, M. E. Argentati, and E. Ovchinnikov (2007),
|
||||
Block Locally Optimal Preconditioned Eigenvalue Xolvers (BLOPEX)
|
||||
in hypre and PETSc. :arxiv:`0705.2626`
|
||||
|
||||
.. [3] A. V. Knyazev's C and MATLAB implementations:
|
||||
https://github.com/lobpcg/blopex
|
||||
"""
|
||||
|
||||
import warnings
|
||||
import numpy as np
|
||||
from scipy.linalg import (inv, eigh, cho_factor, cho_solve,
|
||||
cholesky, LinAlgError)
|
||||
from scipy.sparse.linalg import aslinearoperator
|
||||
from numpy import block as bmat
|
||||
|
||||
__all__ = ["lobpcg"]
|
||||
|
||||
|
||||
def _report_nonhermitian(M, name):
|
||||
"""
|
||||
Report if `M` is not a Hermitian matrix given its type.
|
||||
"""
|
||||
from scipy.linalg import norm
|
||||
|
||||
md = M - M.T.conj()
|
||||
nmd = norm(md, 1)
|
||||
tol = 10 * np.finfo(M.dtype).eps
|
||||
tol = max(tol, tol * norm(M, 1))
|
||||
if nmd > tol:
|
||||
warnings.warn(
|
||||
f"Matrix {name} of the type {M.dtype} is not Hermitian: "
|
||||
f"condition: {nmd} < {tol} fails.",
|
||||
UserWarning, stacklevel=4
|
||||
)
|
||||
|
||||
def _as2d(ar):
|
||||
"""
|
||||
If the input array is 2D return it, if it is 1D, append a dimension,
|
||||
making it a column vector.
|
||||
"""
|
||||
if ar.ndim == 2:
|
||||
return ar
|
||||
else: # Assume 1!
|
||||
aux = np.array(ar, copy=False)
|
||||
aux.shape = (ar.shape[0], 1)
|
||||
return aux
|
||||
|
||||
|
||||
def _makeOperator(operatorInput, expectedShape):
|
||||
"""Takes a dense numpy array or a sparse matrix or
|
||||
a function and makes an operator performing matrix * blockvector
|
||||
products."""
|
||||
if operatorInput is None:
|
||||
return None
|
||||
else:
|
||||
operator = aslinearoperator(operatorInput)
|
||||
|
||||
if operator.shape != expectedShape:
|
||||
raise ValueError("operator has invalid shape")
|
||||
|
||||
return operator
|
||||
|
||||
|
||||
def _applyConstraints(blockVectorV, factYBY, blockVectorBY, blockVectorY):
|
||||
"""Changes blockVectorV in place."""
|
||||
YBV = np.dot(blockVectorBY.T.conj(), blockVectorV)
|
||||
tmp = cho_solve(factYBY, YBV)
|
||||
blockVectorV -= np.dot(blockVectorY, tmp)
|
||||
|
||||
|
||||
def _b_orthonormalize(B, blockVectorV, blockVectorBV=None, retInvR=False):
|
||||
"""B-orthonormalize the given block vector using Cholesky."""
|
||||
normalization = blockVectorV.max(axis=0) + np.finfo(blockVectorV.dtype).eps
|
||||
blockVectorV = blockVectorV / normalization
|
||||
if blockVectorBV is None:
|
||||
if B is not None:
|
||||
blockVectorBV = B(blockVectorV)
|
||||
else:
|
||||
blockVectorBV = blockVectorV # Shared data!!!
|
||||
else:
|
||||
blockVectorBV = blockVectorBV / normalization
|
||||
VBV = blockVectorV.T.conj() @ blockVectorBV
|
||||
try:
|
||||
# VBV is a Cholesky factor from now on...
|
||||
VBV = cholesky(VBV, overwrite_a=True)
|
||||
VBV = inv(VBV, overwrite_a=True)
|
||||
blockVectorV = blockVectorV @ VBV
|
||||
# blockVectorV = (cho_solve((VBV.T, True), blockVectorV.T)).T
|
||||
if B is not None:
|
||||
blockVectorBV = blockVectorBV @ VBV
|
||||
# blockVectorBV = (cho_solve((VBV.T, True), blockVectorBV.T)).T
|
||||
else:
|
||||
blockVectorBV = None
|
||||
except LinAlgError:
|
||||
# raise ValueError('Cholesky has failed')
|
||||
blockVectorV = None
|
||||
blockVectorBV = None
|
||||
VBV = None
|
||||
|
||||
if retInvR:
|
||||
return blockVectorV, blockVectorBV, VBV, normalization
|
||||
else:
|
||||
return blockVectorV, blockVectorBV
|
||||
|
||||
|
||||
def _get_indx(_lambda, num, largest):
|
||||
"""Get `num` indices into `_lambda` depending on `largest` option."""
|
||||
ii = np.argsort(_lambda)
|
||||
if largest:
|
||||
ii = ii[:-num - 1:-1]
|
||||
else:
|
||||
ii = ii[:num]
|
||||
|
||||
return ii
|
||||
|
||||
|
||||
def lobpcg(
|
||||
A,
|
||||
X,
|
||||
B=None,
|
||||
M=None,
|
||||
Y=None,
|
||||
tol=None,
|
||||
maxiter=None,
|
||||
largest=True,
|
||||
verbosityLevel=0,
|
||||
retLambdaHistory=False,
|
||||
retResidualNormsHistory=False,
|
||||
):
|
||||
"""Locally Optimal Block Preconditioned Conjugate Gradient Method (LOBPCG)
|
||||
|
||||
LOBPCG is a preconditioned eigensolver for large symmetric positive
|
||||
definite (SPD) generalized eigenproblems.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
A : {sparse matrix, dense matrix, LinearOperator}
|
||||
The symmetric linear operator of the problem, usually a
|
||||
sparse matrix. Often called the "stiffness matrix".
|
||||
X : ndarray, float32 or float64
|
||||
Initial approximation to the ``k`` eigenvectors (non-sparse). If `A`
|
||||
has ``shape=(n,n)`` then `X` should have shape ``shape=(n,k)``.
|
||||
B : {dense matrix, sparse matrix, LinearOperator}, optional
|
||||
The right hand side operator in a generalized eigenproblem.
|
||||
By default, ``B = Identity``. Often called the "mass matrix".
|
||||
M : {dense matrix, sparse matrix, LinearOperator}, optional
|
||||
Preconditioner to `A`; by default ``M = Identity``.
|
||||
`M` should approximate the inverse of `A`.
|
||||
Y : ndarray, float32 or float64, optional
|
||||
n-by-sizeY matrix of constraints (non-sparse), sizeY < n
|
||||
The iterations will be performed in the B-orthogonal complement
|
||||
of the column-space of Y. Y must be full rank.
|
||||
tol : scalar, optional
|
||||
Solver tolerance (stopping criterion).
|
||||
The default is ``tol=n*sqrt(eps)``.
|
||||
maxiter : int, optional
|
||||
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
|
||||
Controls solver output. The default is ``verbosityLevel=0``.
|
||||
retLambdaHistory : bool, optional
|
||||
Whether to return eigenvalue history. Default is False.
|
||||
retResidualNormsHistory : bool, optional
|
||||
Whether to return history of residual norms. Default is False.
|
||||
|
||||
Returns
|
||||
-------
|
||||
w : ndarray
|
||||
Array of ``k`` eigenvalues
|
||||
v : ndarray
|
||||
An array of ``k`` eigenvectors. `v` has the same shape as `X`.
|
||||
lambdas : list of ndarray, optional
|
||||
The eigenvalue history, if `retLambdaHistory` is True.
|
||||
rnorms : list of ndarray, optional
|
||||
The history of residual norms, if `retResidualNormsHistory` is True.
|
||||
|
||||
Notes
|
||||
-----
|
||||
If both ``retLambdaHistory`` and ``retResidualNormsHistory`` are True,
|
||||
the return tuple has the following format
|
||||
``(lambda, V, lambda history, residual norms history)``.
|
||||
|
||||
In the following ``n`` denotes the matrix size and ``m`` the number
|
||||
of required eigenvalues (smallest or largest).
|
||||
|
||||
The LOBPCG code internally solves eigenproblems of the size ``3m`` on every
|
||||
iteration by calling the "standard" dense eigensolver, so if ``m`` is not
|
||||
small enough compared to ``n``, it does not make sense to call the LOBPCG
|
||||
code, but rather one should use the "standard" eigensolver, e.g. numpy or
|
||||
scipy function in this case.
|
||||
If one calls the LOBPCG algorithm for ``5m > n``, it will most likely break
|
||||
internally, so the code tries to call the standard function instead.
|
||||
|
||||
It is not that ``n`` should be large for the LOBPCG to work, but rather the
|
||||
ratio ``n / m`` should be large. It you call LOBPCG with ``m=1``
|
||||
and ``n=10``, it works though ``n`` is small. The method is intended
|
||||
for extremely large ``n / m``.
|
||||
|
||||
The convergence speed depends basically on two factors:
|
||||
|
||||
1. How well relatively separated the seeking eigenvalues are from the rest
|
||||
of the eigenvalues. One can try to vary ``m`` to make this better.
|
||||
|
||||
2. How well conditioned the problem is. This can be changed by using proper
|
||||
preconditioning. For example, a rod vibration test problem (under tests
|
||||
directory) is ill-conditioned for large ``n``, so convergence will be
|
||||
slow, unless efficient preconditioning is used. For this specific
|
||||
problem, a good simple preconditioner function would be a linear solve
|
||||
for `A`, which is easy to code since A is tridiagonal.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] A. V. Knyazev (2001),
|
||||
Toward the Optimal Preconditioned Eigensolver: Locally Optimal
|
||||
Block Preconditioned Conjugate Gradient Method.
|
||||
SIAM Journal on Scientific Computing 23, no. 2,
|
||||
pp. 517-541. :doi:`10.1137/S1064827500366124`
|
||||
|
||||
.. [2] A. V. Knyazev, I. Lashuk, M. E. Argentati, and E. Ovchinnikov
|
||||
(2007), Block Locally Optimal Preconditioned Eigenvalue Xolvers
|
||||
(BLOPEX) in hypre and PETSc. :arxiv:`0705.2626`
|
||||
|
||||
.. [3] A. V. Knyazev's C and MATLAB implementations:
|
||||
https://github.com/lobpcg/blopex
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Solve ``A x = lambda x`` with constraints and preconditioning.
|
||||
|
||||
>>> import numpy as np
|
||||
>>> from scipy.sparse import spdiags, issparse
|
||||
>>> from scipy.sparse.linalg import lobpcg, LinearOperator
|
||||
>>> n = 100
|
||||
>>> vals = np.arange(1, n + 1)
|
||||
>>> A = spdiags(vals, 0, n, n)
|
||||
>>> A.toarray()
|
||||
array([[ 1., 0., 0., ..., 0., 0., 0.],
|
||||
[ 0., 2., 0., ..., 0., 0., 0.],
|
||||
[ 0., 0., 3., ..., 0., 0., 0.],
|
||||
...,
|
||||
[ 0., 0., 0., ..., 98., 0., 0.],
|
||||
[ 0., 0., 0., ..., 0., 99., 0.],
|
||||
[ 0., 0., 0., ..., 0., 0., 100.]])
|
||||
|
||||
Constraints:
|
||||
|
||||
>>> Y = np.eye(n, 3)
|
||||
|
||||
Initial guess for eigenvectors, should have linearly independent
|
||||
columns. Column dimension = number of requested eigenvalues.
|
||||
|
||||
>>> rng = np.random.default_rng()
|
||||
>>> X = rng.random((n, 3))
|
||||
|
||||
Preconditioner in the inverse of A in this example:
|
||||
|
||||
>>> invA = spdiags([1./vals], 0, n, n)
|
||||
|
||||
The preconditiner must be defined by a function:
|
||||
|
||||
>>> def precond( x ):
|
||||
... return invA @ x
|
||||
|
||||
The argument x of the preconditioner function is a matrix inside `lobpcg`,
|
||||
thus the use of matrix-matrix product ``@``.
|
||||
|
||||
The preconditioner function is passed to lobpcg as a `LinearOperator`:
|
||||
|
||||
>>> M = LinearOperator(matvec=precond, matmat=precond,
|
||||
... shape=(n, n), dtype=np.float64)
|
||||
|
||||
Let us now solve the eigenvalue problem for the matrix A:
|
||||
|
||||
>>> eigenvalues, _ = lobpcg(A, X, Y=Y, M=M, largest=False)
|
||||
>>> eigenvalues
|
||||
array([4., 5., 6.])
|
||||
|
||||
Note that the vectors passed in Y are the eigenvectors of the 3 smallest
|
||||
eigenvalues. The results returned are orthogonal to those.
|
||||
|
||||
"""
|
||||
blockVectorX = X
|
||||
blockVectorY = Y
|
||||
residualTolerance = tol
|
||||
if maxiter is None:
|
||||
maxiter = 20
|
||||
|
||||
if blockVectorY is not None:
|
||||
sizeY = blockVectorY.shape[1]
|
||||
else:
|
||||
sizeY = 0
|
||||
|
||||
# Block size.
|
||||
if len(blockVectorX.shape) != 2:
|
||||
raise ValueError("expected rank-2 array for argument X")
|
||||
|
||||
n, sizeX = blockVectorX.shape
|
||||
|
||||
if verbosityLevel:
|
||||
aux = "Solving "
|
||||
if B is None:
|
||||
aux += "standard"
|
||||
else:
|
||||
aux += "generalized"
|
||||
aux += " eigenvalue problem with"
|
||||
if M is None:
|
||||
aux += "out"
|
||||
aux += " preconditioning\n\n"
|
||||
aux += "matrix size %d\n" % n
|
||||
aux += "block size %d\n\n" % sizeX
|
||||
if blockVectorY is None:
|
||||
aux += "No constraints\n\n"
|
||||
else:
|
||||
if sizeY > 1:
|
||||
aux += "%d constraints\n\n" % sizeY
|
||||
else:
|
||||
aux += "%d constraint\n\n" % sizeY
|
||||
print(aux)
|
||||
|
||||
A = _makeOperator(A, (n, n))
|
||||
B = _makeOperator(B, (n, n))
|
||||
M = _makeOperator(M, (n, n))
|
||||
|
||||
if (n - sizeY) < (5 * sizeX):
|
||||
warnings.warn(
|
||||
f"The problem size {n} minus the constraints size {sizeY} "
|
||||
f"is too small relative to the block size {sizeX}. "
|
||||
f"Using a dense eigensolver instead of LOBPCG.",
|
||||
UserWarning, stacklevel=2
|
||||
)
|
||||
|
||||
sizeX = min(sizeX, n)
|
||||
|
||||
if blockVectorY is not None:
|
||||
raise NotImplementedError(
|
||||
"The dense eigensolver does not support constraints."
|
||||
)
|
||||
|
||||
# Define the closed range of indices of eigenvalues to return.
|
||||
if largest:
|
||||
eigvals = (n - sizeX, n - 1)
|
||||
else:
|
||||
eigvals = (0, sizeX - 1)
|
||||
|
||||
A_dense = A(np.eye(n, dtype=A.dtype))
|
||||
B_dense = None if B is None else B(np.eye(n, dtype=B.dtype))
|
||||
|
||||
vals, vecs = eigh(A_dense,
|
||||
B_dense,
|
||||
eigvals=eigvals,
|
||||
check_finite=False)
|
||||
if largest:
|
||||
# Reverse order to be compatible with eigs() in 'LM' mode.
|
||||
vals = vals[::-1]
|
||||
vecs = vecs[:, ::-1]
|
||||
|
||||
return vals, vecs
|
||||
|
||||
if (residualTolerance is None) or (residualTolerance <= 0.0):
|
||||
residualTolerance = np.sqrt(1e-15) * n
|
||||
|
||||
# Apply constraints to X.
|
||||
if blockVectorY is not None:
|
||||
|
||||
if B is not None:
|
||||
blockVectorBY = B(blockVectorY)
|
||||
else:
|
||||
blockVectorBY = blockVectorY
|
||||
|
||||
# gramYBY is a dense array.
|
||||
gramYBY = np.dot(blockVectorY.T.conj(), blockVectorBY)
|
||||
try:
|
||||
# gramYBY is a Cholesky factor from now on...
|
||||
gramYBY = cho_factor(gramYBY)
|
||||
except LinAlgError as e:
|
||||
raise ValueError("Linearly dependent constraints") from e
|
||||
|
||||
_applyConstraints(blockVectorX, gramYBY, blockVectorBY, blockVectorY)
|
||||
|
||||
##
|
||||
# B-orthonormalize X.
|
||||
blockVectorX, blockVectorBX = _b_orthonormalize(B, blockVectorX)
|
||||
if blockVectorX is None:
|
||||
raise ValueError("Linearly dependent initial approximations")
|
||||
|
||||
##
|
||||
# Compute the initial Ritz vectors: solve the eigenproblem.
|
||||
blockVectorAX = A(blockVectorX)
|
||||
gramXAX = np.dot(blockVectorX.T.conj(), blockVectorAX)
|
||||
|
||||
_lambda, eigBlockVector = eigh(gramXAX, check_finite=False)
|
||||
ii = _get_indx(_lambda, sizeX, largest)
|
||||
_lambda = _lambda[ii]
|
||||
|
||||
eigBlockVector = np.asarray(eigBlockVector[:, ii])
|
||||
blockVectorX = np.dot(blockVectorX, eigBlockVector)
|
||||
blockVectorAX = np.dot(blockVectorAX, eigBlockVector)
|
||||
if B is not None:
|
||||
blockVectorBX = np.dot(blockVectorBX, eigBlockVector)
|
||||
|
||||
##
|
||||
# Active index set.
|
||||
activeMask = np.ones((sizeX,), dtype=bool)
|
||||
|
||||
lambdaHistory = [_lambda]
|
||||
residualNormsHistory = []
|
||||
|
||||
previousBlockSize = sizeX
|
||||
ident = np.eye(sizeX, dtype=A.dtype)
|
||||
ident0 = np.eye(sizeX, dtype=A.dtype)
|
||||
|
||||
##
|
||||
# Main iteration loop.
|
||||
|
||||
blockVectorP = None # set during iteration
|
||||
blockVectorAP = None
|
||||
blockVectorBP = None
|
||||
|
||||
iterationNumber = -1
|
||||
restart = True
|
||||
explicitGramFlag = False
|
||||
while iterationNumber < maxiter:
|
||||
iterationNumber += 1
|
||||
if verbosityLevel > 0:
|
||||
print("-"*50)
|
||||
print(f"iteration {iterationNumber}")
|
||||
|
||||
if B is not None:
|
||||
aux = blockVectorBX * _lambda[np.newaxis, :]
|
||||
else:
|
||||
aux = blockVectorX * _lambda[np.newaxis, :]
|
||||
|
||||
blockVectorR = blockVectorAX - aux
|
||||
|
||||
aux = np.sum(blockVectorR.conj() * blockVectorR, 0)
|
||||
residualNorms = np.sqrt(aux)
|
||||
|
||||
residualNormsHistory.append(residualNorms)
|
||||
|
||||
ii = np.where(residualNorms > residualTolerance, True, False)
|
||||
activeMask = activeMask & ii
|
||||
if verbosityLevel > 2:
|
||||
print(activeMask)
|
||||
|
||||
currentBlockSize = activeMask.sum()
|
||||
if currentBlockSize != previousBlockSize:
|
||||
previousBlockSize = currentBlockSize
|
||||
ident = np.eye(currentBlockSize, dtype=A.dtype)
|
||||
|
||||
if currentBlockSize == 0:
|
||||
break
|
||||
|
||||
if verbosityLevel > 0:
|
||||
print(f"current block size: {currentBlockSize}")
|
||||
print(f"eigenvalue(s):\n{_lambda}")
|
||||
print(f"residual norm(s):\n{residualNorms}")
|
||||
if verbosityLevel > 10:
|
||||
print(eigBlockVector)
|
||||
|
||||
activeBlockVectorR = _as2d(blockVectorR[:, activeMask])
|
||||
|
||||
if iterationNumber > 0:
|
||||
activeBlockVectorP = _as2d(blockVectorP[:, activeMask])
|
||||
activeBlockVectorAP = _as2d(blockVectorAP[:, activeMask])
|
||||
if B is not None:
|
||||
activeBlockVectorBP = _as2d(blockVectorBP[:, activeMask])
|
||||
|
||||
if M is not None:
|
||||
# Apply preconditioner T to the active residuals.
|
||||
activeBlockVectorR = M(activeBlockVectorR)
|
||||
|
||||
##
|
||||
# Apply constraints to the preconditioned residuals.
|
||||
if blockVectorY is not None:
|
||||
_applyConstraints(activeBlockVectorR,
|
||||
gramYBY,
|
||||
blockVectorBY,
|
||||
blockVectorY)
|
||||
|
||||
##
|
||||
# B-orthogonalize the preconditioned residuals to X.
|
||||
if B is not None:
|
||||
activeBlockVectorR = activeBlockVectorR - (
|
||||
blockVectorX @
|
||||
(blockVectorBX.T.conj() @ activeBlockVectorR)
|
||||
)
|
||||
else:
|
||||
activeBlockVectorR = activeBlockVectorR - (
|
||||
blockVectorX @
|
||||
(blockVectorX.T.conj() @ activeBlockVectorR)
|
||||
)
|
||||
|
||||
##
|
||||
# B-orthonormalize the preconditioned residuals.
|
||||
aux = _b_orthonormalize(B, activeBlockVectorR)
|
||||
activeBlockVectorR, activeBlockVectorBR = aux
|
||||
|
||||
if activeBlockVectorR is None:
|
||||
warnings.warn(
|
||||
f"Failed at iteration {iterationNumber} with accuracies "
|
||||
f"{residualNorms}\n not reaching the requested "
|
||||
f"tolerance {residualTolerance}.",
|
||||
UserWarning, stacklevel=2
|
||||
)
|
||||
break
|
||||
activeBlockVectorAR = A(activeBlockVectorR)
|
||||
|
||||
if iterationNumber > 0:
|
||||
if B is not None:
|
||||
aux = _b_orthonormalize(
|
||||
B, activeBlockVectorP, activeBlockVectorBP, retInvR=True
|
||||
)
|
||||
activeBlockVectorP, activeBlockVectorBP, invR, normal = aux
|
||||
else:
|
||||
aux = _b_orthonormalize(B, activeBlockVectorP, retInvR=True)
|
||||
activeBlockVectorP, _, invR, normal = aux
|
||||
# Function _b_orthonormalize returns None if Cholesky fails
|
||||
if activeBlockVectorP is not None:
|
||||
activeBlockVectorAP = activeBlockVectorAP / normal
|
||||
activeBlockVectorAP = np.dot(activeBlockVectorAP, invR)
|
||||
restart = False
|
||||
else:
|
||||
restart = True
|
||||
|
||||
##
|
||||
# Perform the Rayleigh Ritz Procedure:
|
||||
# Compute symmetric Gram matrices:
|
||||
|
||||
if activeBlockVectorAR.dtype == "float32":
|
||||
myeps = 1
|
||||
elif activeBlockVectorR.dtype == "float32":
|
||||
myeps = 1e-4
|
||||
else:
|
||||
myeps = 1e-8
|
||||
|
||||
if residualNorms.max() > myeps and not explicitGramFlag:
|
||||
explicitGramFlag = False
|
||||
else:
|
||||
# Once explicitGramFlag, forever explicitGramFlag.
|
||||
explicitGramFlag = True
|
||||
|
||||
# Shared memory assingments to simplify the code
|
||||
if B is None:
|
||||
blockVectorBX = blockVectorX
|
||||
activeBlockVectorBR = activeBlockVectorR
|
||||
if not restart:
|
||||
activeBlockVectorBP = activeBlockVectorP
|
||||
|
||||
# Common submatrices:
|
||||
gramXAR = np.dot(blockVectorX.T.conj(), activeBlockVectorAR)
|
||||
gramRAR = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorAR)
|
||||
|
||||
if explicitGramFlag:
|
||||
gramRAR = (gramRAR + gramRAR.T.conj()) / 2
|
||||
gramXAX = np.dot(blockVectorX.T.conj(), blockVectorAX)
|
||||
gramXAX = (gramXAX + gramXAX.T.conj()) / 2
|
||||
gramXBX = np.dot(blockVectorX.T.conj(), blockVectorBX)
|
||||
gramRBR = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorBR)
|
||||
gramXBR = np.dot(blockVectorX.T.conj(), activeBlockVectorBR)
|
||||
else:
|
||||
gramXAX = np.diag(_lambda)
|
||||
gramXBX = ident0
|
||||
gramRBR = ident
|
||||
gramXBR = np.zeros((sizeX, currentBlockSize), dtype=A.dtype)
|
||||
|
||||
def _handle_gramA_gramB_verbosity(gramA, gramB):
|
||||
if verbosityLevel > 0:
|
||||
_report_nonhermitian(gramA, "gramA")
|
||||
_report_nonhermitian(gramB, "gramB")
|
||||
if verbosityLevel > 10:
|
||||
# Note: not documented, but leave it in here for now
|
||||
np.savetxt("gramA.txt", gramA)
|
||||
np.savetxt("gramB.txt", gramB)
|
||||
|
||||
if not restart:
|
||||
gramXAP = np.dot(blockVectorX.T.conj(), activeBlockVectorAP)
|
||||
gramRAP = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorAP)
|
||||
gramPAP = np.dot(activeBlockVectorP.T.conj(), activeBlockVectorAP)
|
||||
gramXBP = np.dot(blockVectorX.T.conj(), activeBlockVectorBP)
|
||||
gramRBP = np.dot(activeBlockVectorR.T.conj(), activeBlockVectorBP)
|
||||
if explicitGramFlag:
|
||||
gramPAP = (gramPAP + gramPAP.T.conj()) / 2
|
||||
gramPBP = np.dot(activeBlockVectorP.T.conj(),
|
||||
activeBlockVectorBP)
|
||||
else:
|
||||
gramPBP = ident
|
||||
|
||||
gramA = bmat(
|
||||
[
|
||||
[gramXAX, gramXAR, gramXAP],
|
||||
[gramXAR.T.conj(), gramRAR, gramRAP],
|
||||
[gramXAP.T.conj(), gramRAP.T.conj(), gramPAP],
|
||||
]
|
||||
)
|
||||
gramB = bmat(
|
||||
[
|
||||
[gramXBX, gramXBR, gramXBP],
|
||||
[gramXBR.T.conj(), gramRBR, gramRBP],
|
||||
[gramXBP.T.conj(), gramRBP.T.conj(), gramPBP],
|
||||
]
|
||||
)
|
||||
|
||||
_handle_gramA_gramB_verbosity(gramA, gramB)
|
||||
|
||||
try:
|
||||
_lambda, eigBlockVector = eigh(gramA,
|
||||
gramB,
|
||||
check_finite=False)
|
||||
except LinAlgError:
|
||||
# try again after dropping the direction vectors P from RR
|
||||
restart = True
|
||||
|
||||
if restart:
|
||||
gramA = bmat([[gramXAX, gramXAR], [gramXAR.T.conj(), gramRAR]])
|
||||
gramB = bmat([[gramXBX, gramXBR], [gramXBR.T.conj(), gramRBR]])
|
||||
|
||||
_handle_gramA_gramB_verbosity(gramA, gramB)
|
||||
|
||||
try:
|
||||
_lambda, eigBlockVector = eigh(gramA,
|
||||
gramB,
|
||||
check_finite=False)
|
||||
except LinAlgError as e:
|
||||
raise ValueError("eigh has failed in lobpcg iterations") from e
|
||||
|
||||
ii = _get_indx(_lambda, sizeX, largest)
|
||||
if verbosityLevel > 10:
|
||||
print(ii)
|
||||
print(f"lambda:\n{_lambda}")
|
||||
|
||||
_lambda = _lambda[ii]
|
||||
eigBlockVector = eigBlockVector[:, ii]
|
||||
|
||||
lambdaHistory.append(_lambda)
|
||||
|
||||
if verbosityLevel > 10:
|
||||
print(f"lambda:\n{_lambda}")
|
||||
# # Normalize eigenvectors!
|
||||
# aux = np.sum( eigBlockVector.conj() * eigBlockVector, 0 )
|
||||
# eigVecNorms = np.sqrt( aux )
|
||||
# eigBlockVector = eigBlockVector / eigVecNorms[np.newaxis, :]
|
||||
# eigBlockVector, aux = _b_orthonormalize( B, eigBlockVector )
|
||||
|
||||
if verbosityLevel > 10:
|
||||
print(eigBlockVector)
|
||||
|
||||
# Compute Ritz vectors.
|
||||
if B is not None:
|
||||
if not restart:
|
||||
eigBlockVectorX = eigBlockVector[:sizeX]
|
||||
eigBlockVectorR = eigBlockVector[sizeX:
|
||||
sizeX + currentBlockSize]
|
||||
eigBlockVectorP = eigBlockVector[sizeX + currentBlockSize:]
|
||||
|
||||
pp = np.dot(activeBlockVectorR, eigBlockVectorR)
|
||||
pp += np.dot(activeBlockVectorP, eigBlockVectorP)
|
||||
|
||||
app = np.dot(activeBlockVectorAR, eigBlockVectorR)
|
||||
app += np.dot(activeBlockVectorAP, eigBlockVectorP)
|
||||
|
||||
bpp = np.dot(activeBlockVectorBR, eigBlockVectorR)
|
||||
bpp += np.dot(activeBlockVectorBP, eigBlockVectorP)
|
||||
else:
|
||||
eigBlockVectorX = eigBlockVector[:sizeX]
|
||||
eigBlockVectorR = eigBlockVector[sizeX:]
|
||||
|
||||
pp = np.dot(activeBlockVectorR, eigBlockVectorR)
|
||||
app = np.dot(activeBlockVectorAR, eigBlockVectorR)
|
||||
bpp = np.dot(activeBlockVectorBR, eigBlockVectorR)
|
||||
|
||||
if verbosityLevel > 10:
|
||||
print(pp)
|
||||
print(app)
|
||||
print(bpp)
|
||||
|
||||
blockVectorX = np.dot(blockVectorX, eigBlockVectorX) + pp
|
||||
blockVectorAX = np.dot(blockVectorAX, eigBlockVectorX) + app
|
||||
blockVectorBX = np.dot(blockVectorBX, eigBlockVectorX) + bpp
|
||||
|
||||
blockVectorP, blockVectorAP, blockVectorBP = pp, app, bpp
|
||||
|
||||
else:
|
||||
if not restart:
|
||||
eigBlockVectorX = eigBlockVector[:sizeX]
|
||||
eigBlockVectorR = eigBlockVector[sizeX:
|
||||
sizeX + currentBlockSize]
|
||||
eigBlockVectorP = eigBlockVector[sizeX + currentBlockSize:]
|
||||
|
||||
pp = np.dot(activeBlockVectorR, eigBlockVectorR)
|
||||
pp += np.dot(activeBlockVectorP, eigBlockVectorP)
|
||||
|
||||
app = np.dot(activeBlockVectorAR, eigBlockVectorR)
|
||||
app += np.dot(activeBlockVectorAP, eigBlockVectorP)
|
||||
else:
|
||||
eigBlockVectorX = eigBlockVector[:sizeX]
|
||||
eigBlockVectorR = eigBlockVector[sizeX:]
|
||||
|
||||
pp = np.dot(activeBlockVectorR, eigBlockVectorR)
|
||||
app = np.dot(activeBlockVectorAR, eigBlockVectorR)
|
||||
|
||||
if verbosityLevel > 10:
|
||||
print(pp)
|
||||
print(app)
|
||||
|
||||
blockVectorX = np.dot(blockVectorX, eigBlockVectorX) + pp
|
||||
blockVectorAX = np.dot(blockVectorAX, eigBlockVectorX) + app
|
||||
|
||||
blockVectorP, blockVectorAP = pp, app
|
||||
|
||||
if B is not None:
|
||||
aux = blockVectorBX * _lambda[np.newaxis, :]
|
||||
|
||||
else:
|
||||
aux = blockVectorX * _lambda[np.newaxis, :]
|
||||
|
||||
blockVectorR = blockVectorAX - aux
|
||||
|
||||
aux = np.sum(blockVectorR.conj() * blockVectorR, 0)
|
||||
residualNorms = np.sqrt(aux)
|
||||
|
||||
if np.max(residualNorms) > residualTolerance:
|
||||
warnings.warn(
|
||||
f"Exited at iteration {iterationNumber} with accuracies \n"
|
||||
f"{residualNorms}\n"
|
||||
f"not reaching the requested tolerance {residualTolerance}.",
|
||||
UserWarning, stacklevel=2
|
||||
)
|
||||
|
||||
# Future work: Need to add Postprocessing here:
|
||||
# Making sure eigenvectors "exactly" satisfy the blockVectorY constrains?
|
||||
# Making sure eigenvecotrs are "exactly" othonormalized by final "exact" RR
|
||||
# Keeping the best iterates in case of divergence
|
||||
|
||||
if verbosityLevel > 0:
|
||||
print(f"Final eigenvalue(s):\n{_lambda}")
|
||||
print(f"Final residual norm(s):\n{residualNorms}")
|
||||
|
||||
if retLambdaHistory:
|
||||
if retResidualNormsHistory:
|
||||
return _lambda, blockVectorX, lambdaHistory, residualNormsHistory
|
||||
else:
|
||||
return _lambda, blockVectorX, lambdaHistory
|
||||
else:
|
||||
if retResidualNormsHistory:
|
||||
return _lambda, blockVectorX, residualNormsHistory
|
||||
else:
|
||||
return _lambda, blockVectorX
|
||||
139
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_numpy_compiler_patch.py
vendored
Normal file
139
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_numpy_compiler_patch.py
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
# Copyright (c) 2005-2022, NumPy Developers.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
|
||||
# * Neither the name of the NumPy Developers nor the names of any
|
||||
# contributors may be used to endorse or promote products derived
|
||||
# from this software without specific prior written permission.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import re
|
||||
from distutils.errors import DistutilsExecError
|
||||
|
||||
from numpy.distutils import log
|
||||
|
||||
|
||||
def is_sequence(seq):
|
||||
if isinstance(seq, str):
|
||||
return False
|
||||
try:
|
||||
len(seq)
|
||||
except Exception:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def forward_bytes_to_stdout(val):
|
||||
"""
|
||||
Forward bytes from a subprocess call to the console, without attempting to
|
||||
decode them.
|
||||
|
||||
The assumption is that the subprocess call already returned bytes in
|
||||
a suitable encoding.
|
||||
"""
|
||||
if hasattr(sys.stdout, "buffer"):
|
||||
# use the underlying binary output if there is one
|
||||
sys.stdout.buffer.write(val)
|
||||
elif hasattr(sys.stdout, "encoding"):
|
||||
# round-trip the encoding if necessary
|
||||
sys.stdout.write(val.decode(sys.stdout.encoding))
|
||||
else:
|
||||
# make a best-guess at the encoding
|
||||
sys.stdout.write(val.decode("utf8", errors="replace"))
|
||||
|
||||
|
||||
def CCompiler_spawn(self, cmd, display=None, env=None):
|
||||
"""
|
||||
Execute a command in a sub-process.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cmd : str
|
||||
The command to execute.
|
||||
display : str or sequence of str, optional
|
||||
The text to add to the log file kept by `numpy.distutils`.
|
||||
If not given, `display` is equal to `cmd`.
|
||||
env: a dictionary for environment variables, optional
|
||||
|
||||
Returns
|
||||
-------
|
||||
None
|
||||
|
||||
Raises
|
||||
------
|
||||
DistutilsExecError
|
||||
If the command failed, i.e. the exit status was not 0.
|
||||
|
||||
"""
|
||||
env = env if env is not None else dict(os.environ)
|
||||
if display is None:
|
||||
display = cmd
|
||||
if is_sequence(display):
|
||||
display = " ".join(list(display))
|
||||
log.info(display)
|
||||
try:
|
||||
if self.verbose:
|
||||
subprocess.check_output(cmd, env=env)
|
||||
else:
|
||||
subprocess.check_output(cmd, stderr=subprocess.STDOUT, env=env)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
o = exc.output
|
||||
s = exc.returncode
|
||||
except OSError as e:
|
||||
# OSError doesn't have the same hooks for the exception
|
||||
# output, but exec_command() historically would use an
|
||||
# empty string for EnvironmentError (base class for
|
||||
# OSError)
|
||||
# o = b''
|
||||
# still that would make the end-user lost in translation!
|
||||
o = f"\n\n{e}\n\n\n"
|
||||
try:
|
||||
o = o.encode(sys.stdout.encoding)
|
||||
except AttributeError:
|
||||
o = o.encode("utf8")
|
||||
# status previously used by exec_command() for parent
|
||||
# of OSError
|
||||
s = 127
|
||||
else:
|
||||
# use a convenience return here so that any kind of
|
||||
# caught exception will execute the default code after the
|
||||
# try / except block, which handles various exceptions
|
||||
return None
|
||||
|
||||
if is_sequence(cmd):
|
||||
cmd = " ".join(list(cmd))
|
||||
|
||||
if self.verbose:
|
||||
forward_bytes_to_stdout(o)
|
||||
|
||||
if re.search(b"Too many open files", o):
|
||||
msg = "\nTry rerunning setup command until build succeeds."
|
||||
else:
|
||||
msg = ""
|
||||
raise DistutilsExecError(
|
||||
'Command "%s" failed with exit status %d%s' % (cmd, s, msg)
|
||||
)
|
||||
0
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/__init__.py
vendored
Normal file
0
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/__init__.py
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
90
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/_structures.py
vendored
Normal file
90
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/_structures.py
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
"""Vendoered from
|
||||
https://github.com/pypa/packaging/blob/main/packaging/_structures.py
|
||||
"""
|
||||
# Copyright (c) Donald Stufft and individual contributors.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
class InfinityType:
|
||||
def __repr__(self) -> str:
|
||||
return "Infinity"
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(repr(self))
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
return False
|
||||
|
||||
def __le__(self, other: object) -> bool:
|
||||
return False
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return isinstance(other, self.__class__)
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not isinstance(other, self.__class__)
|
||||
|
||||
def __gt__(self, other: object) -> bool:
|
||||
return True
|
||||
|
||||
def __ge__(self, other: object) -> bool:
|
||||
return True
|
||||
|
||||
def __neg__(self: object) -> "NegativeInfinityType":
|
||||
return NegativeInfinity
|
||||
|
||||
|
||||
Infinity = InfinityType()
|
||||
|
||||
|
||||
class NegativeInfinityType:
|
||||
def __repr__(self) -> str:
|
||||
return "-Infinity"
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(repr(self))
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
return True
|
||||
|
||||
def __le__(self, other: object) -> bool:
|
||||
return True
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
return isinstance(other, self.__class__)
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
return not isinstance(other, self.__class__)
|
||||
|
||||
def __gt__(self, other: object) -> bool:
|
||||
return False
|
||||
|
||||
def __ge__(self, other: object) -> bool:
|
||||
return False
|
||||
|
||||
def __neg__(self: object) -> InfinityType:
|
||||
return Infinity
|
||||
|
||||
|
||||
NegativeInfinity = NegativeInfinityType()
|
||||
527
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/version.py
vendored
Normal file
527
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/_packaging/version.py
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
"""Vendoered from
|
||||
https://github.com/pypa/packaging/blob/main/packaging/version.py
|
||||
"""
|
||||
# Copyright (c) Donald Stufft and individual contributors.
|
||||
# All rights reserved.
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import collections
|
||||
import itertools
|
||||
import re
|
||||
import warnings
|
||||
from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union
|
||||
|
||||
from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType
|
||||
|
||||
__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"]
|
||||
|
||||
InfiniteTypes = Union[InfinityType, NegativeInfinityType]
|
||||
PrePostDevType = Union[InfiniteTypes, Tuple[str, int]]
|
||||
SubLocalType = Union[InfiniteTypes, int, str]
|
||||
LocalType = Union[
|
||||
NegativeInfinityType,
|
||||
Tuple[
|
||||
Union[
|
||||
SubLocalType,
|
||||
Tuple[SubLocalType, str],
|
||||
Tuple[NegativeInfinityType, SubLocalType],
|
||||
],
|
||||
...,
|
||||
],
|
||||
]
|
||||
CmpKey = Tuple[
|
||||
int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType
|
||||
]
|
||||
LegacyCmpKey = Tuple[int, Tuple[str, ...]]
|
||||
VersionComparisonMethod = Callable[
|
||||
[Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool
|
||||
]
|
||||
|
||||
_Version = collections.namedtuple(
|
||||
"_Version", ["epoch", "release", "dev", "pre", "post", "local"]
|
||||
)
|
||||
|
||||
|
||||
def parse(version: str) -> Union["LegacyVersion", "Version"]:
|
||||
"""
|
||||
Parse the given version string and return either a :class:`Version` object
|
||||
or a :class:`LegacyVersion` object depending on if the given version is
|
||||
a valid PEP 440 version or a legacy version.
|
||||
"""
|
||||
try:
|
||||
return Version(version)
|
||||
except InvalidVersion:
|
||||
return LegacyVersion(version)
|
||||
|
||||
|
||||
class InvalidVersion(ValueError):
|
||||
"""
|
||||
An invalid version was found, users should refer to PEP 440.
|
||||
"""
|
||||
|
||||
|
||||
class _BaseVersion:
|
||||
_key: Union[CmpKey, LegacyCmpKey]
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self._key)
|
||||
|
||||
# Please keep the duplicated `isinstance` check
|
||||
# in the six comparisons hereunder
|
||||
# unless you find a way to avoid adding overhead function calls.
|
||||
def __lt__(self, other: "_BaseVersion") -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key < other._key
|
||||
|
||||
def __le__(self, other: "_BaseVersion") -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key <= other._key
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key == other._key
|
||||
|
||||
def __ge__(self, other: "_BaseVersion") -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key >= other._key
|
||||
|
||||
def __gt__(self, other: "_BaseVersion") -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key > other._key
|
||||
|
||||
def __ne__(self, other: object) -> bool:
|
||||
if not isinstance(other, _BaseVersion):
|
||||
return NotImplemented
|
||||
|
||||
return self._key != other._key
|
||||
|
||||
|
||||
class LegacyVersion(_BaseVersion):
|
||||
def __init__(self, version: str) -> None:
|
||||
self._version = str(version)
|
||||
self._key = _legacy_cmpkey(self._version)
|
||||
|
||||
warnings.warn(
|
||||
"Creating a LegacyVersion has been deprecated and will be "
|
||||
"removed in the next major release",
|
||||
DeprecationWarning,
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self._version
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<LegacyVersion('{self}')>"
|
||||
|
||||
@property
|
||||
def public(self) -> str:
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def base_version(self) -> str:
|
||||
return self._version
|
||||
|
||||
@property
|
||||
def epoch(self) -> int:
|
||||
return -1
|
||||
|
||||
@property
|
||||
def release(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def pre(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def post(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def dev(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def local(self) -> None:
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_prerelease(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_postrelease(self) -> bool:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_devrelease(self) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE)
|
||||
|
||||
_legacy_version_replacement_map = {
|
||||
"pre": "c",
|
||||
"preview": "c",
|
||||
"-": "final-",
|
||||
"rc": "c",
|
||||
"dev": "@",
|
||||
}
|
||||
|
||||
|
||||
def _parse_version_parts(s: str) -> Iterator[str]:
|
||||
for part in _legacy_version_component_re.split(s):
|
||||
part = _legacy_version_replacement_map.get(part, part)
|
||||
|
||||
if not part or part == ".":
|
||||
continue
|
||||
|
||||
if part[:1] in "0123456789":
|
||||
# pad for numeric comparison
|
||||
yield part.zfill(8)
|
||||
else:
|
||||
yield "*" + part
|
||||
|
||||
# ensure that alpha/beta/candidate are before final
|
||||
yield "*final"
|
||||
|
||||
|
||||
def _legacy_cmpkey(version: str) -> LegacyCmpKey:
|
||||
|
||||
# We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch
|
||||
# greater than or equal to 0. This will effectively put the LegacyVersion,
|
||||
# which uses the defacto standard originally implemented by setuptools,
|
||||
# as before all PEP 440 versions.
|
||||
epoch = -1
|
||||
|
||||
# This scheme is taken from pkg_resources.parse_version setuptools prior to
|
||||
# it's adoption of the packaging library.
|
||||
parts: List[str] = []
|
||||
for part in _parse_version_parts(version.lower()):
|
||||
if part.startswith("*"):
|
||||
# remove "-" before a prerelease tag
|
||||
if part < "*final":
|
||||
while parts and parts[-1] == "*final-":
|
||||
parts.pop()
|
||||
|
||||
# remove trailing zeros from each series of numeric parts
|
||||
while parts and parts[-1] == "00000000":
|
||||
parts.pop()
|
||||
|
||||
parts.append(part)
|
||||
|
||||
return epoch, tuple(parts)
|
||||
|
||||
|
||||
# Deliberately not anchored to the start and end of the string, to make it
|
||||
# easier for 3rd party code to reuse
|
||||
VERSION_PATTERN = r"""
|
||||
v?
|
||||
(?:
|
||||
(?:(?P<epoch>[0-9]+)!)? # epoch
|
||||
(?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
|
||||
(?P<pre> # pre-release
|
||||
[-_\.]?
|
||||
(?P<pre_l>(a|b|c|rc|alpha|beta|pre|preview))
|
||||
[-_\.]?
|
||||
(?P<pre_n>[0-9]+)?
|
||||
)?
|
||||
(?P<post> # post release
|
||||
(?:-(?P<post_n1>[0-9]+))
|
||||
|
|
||||
(?:
|
||||
[-_\.]?
|
||||
(?P<post_l>post|rev|r)
|
||||
[-_\.]?
|
||||
(?P<post_n2>[0-9]+)?
|
||||
)
|
||||
)?
|
||||
(?P<dev> # dev release
|
||||
[-_\.]?
|
||||
(?P<dev_l>dev)
|
||||
[-_\.]?
|
||||
(?P<dev_n>[0-9]+)?
|
||||
)?
|
||||
)
|
||||
(?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
|
||||
"""
|
||||
|
||||
|
||||
class Version(_BaseVersion):
|
||||
|
||||
_regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
|
||||
|
||||
def __init__(self, version: str) -> None:
|
||||
|
||||
# Validate the version and parse it into pieces
|
||||
match = self._regex.search(version)
|
||||
if not match:
|
||||
raise InvalidVersion(f"Invalid version: '{version}'")
|
||||
|
||||
# Store the parsed out pieces of the version
|
||||
self._version = _Version(
|
||||
epoch=int(match.group("epoch")) if match.group("epoch") else 0,
|
||||
release=tuple(int(i) for i in match.group("release").split(".")),
|
||||
pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
|
||||
post=_parse_letter_version(
|
||||
match.group("post_l"), match.group("post_n1") or match.group("post_n2")
|
||||
),
|
||||
dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
|
||||
local=_parse_local_version(match.group("local")),
|
||||
)
|
||||
|
||||
# Generate a key which will be used for sorting
|
||||
self._key = _cmpkey(
|
||||
self._version.epoch,
|
||||
self._version.release,
|
||||
self._version.pre,
|
||||
self._version.post,
|
||||
self._version.dev,
|
||||
self._version.local,
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Version('{self}')>"
|
||||
|
||||
def __str__(self) -> str:
|
||||
parts = []
|
||||
|
||||
# Epoch
|
||||
if self.epoch != 0:
|
||||
parts.append(f"{self.epoch}!")
|
||||
|
||||
# Release segment
|
||||
parts.append(".".join(str(x) for x in self.release))
|
||||
|
||||
# Pre-release
|
||||
if self.pre is not None:
|
||||
parts.append("".join(str(x) for x in self.pre))
|
||||
|
||||
# Post-release
|
||||
if self.post is not None:
|
||||
parts.append(f".post{self.post}")
|
||||
|
||||
# Development release
|
||||
if self.dev is not None:
|
||||
parts.append(f".dev{self.dev}")
|
||||
|
||||
# Local version segment
|
||||
if self.local is not None:
|
||||
parts.append(f"+{self.local}")
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
@property
|
||||
def epoch(self) -> int:
|
||||
_epoch: int = self._version.epoch
|
||||
return _epoch
|
||||
|
||||
@property
|
||||
def release(self) -> Tuple[int, ...]:
|
||||
_release: Tuple[int, ...] = self._version.release
|
||||
return _release
|
||||
|
||||
@property
|
||||
def pre(self) -> Optional[Tuple[str, int]]:
|
||||
_pre: Optional[Tuple[str, int]] = self._version.pre
|
||||
return _pre
|
||||
|
||||
@property
|
||||
def post(self) -> Optional[int]:
|
||||
return self._version.post[1] if self._version.post else None
|
||||
|
||||
@property
|
||||
def dev(self) -> Optional[int]:
|
||||
return self._version.dev[1] if self._version.dev else None
|
||||
|
||||
@property
|
||||
def local(self) -> Optional[str]:
|
||||
if self._version.local:
|
||||
return ".".join(str(x) for x in self._version.local)
|
||||
else:
|
||||
return None
|
||||
|
||||
@property
|
||||
def public(self) -> str:
|
||||
return str(self).split("+", 1)[0]
|
||||
|
||||
@property
|
||||
def base_version(self) -> str:
|
||||
parts = []
|
||||
|
||||
# Epoch
|
||||
if self.epoch != 0:
|
||||
parts.append(f"{self.epoch}!")
|
||||
|
||||
# Release segment
|
||||
parts.append(".".join(str(x) for x in self.release))
|
||||
|
||||
return "".join(parts)
|
||||
|
||||
@property
|
||||
def is_prerelease(self) -> bool:
|
||||
return self.dev is not None or self.pre is not None
|
||||
|
||||
@property
|
||||
def is_postrelease(self) -> bool:
|
||||
return self.post is not None
|
||||
|
||||
@property
|
||||
def is_devrelease(self) -> bool:
|
||||
return self.dev is not None
|
||||
|
||||
@property
|
||||
def major(self) -> int:
|
||||
return self.release[0] if len(self.release) >= 1 else 0
|
||||
|
||||
@property
|
||||
def minor(self) -> int:
|
||||
return self.release[1] if len(self.release) >= 2 else 0
|
||||
|
||||
@property
|
||||
def micro(self) -> int:
|
||||
return self.release[2] if len(self.release) >= 3 else 0
|
||||
|
||||
|
||||
def _parse_letter_version(
|
||||
letter: str, number: Union[str, bytes, SupportsInt]
|
||||
) -> Optional[Tuple[str, int]]:
|
||||
|
||||
if letter:
|
||||
# We consider there to be an implicit 0 in a pre-release if there is
|
||||
# not a numeral associated with it.
|
||||
if number is None:
|
||||
number = 0
|
||||
|
||||
# We normalize any letters to their lower case form
|
||||
letter = letter.lower()
|
||||
|
||||
# We consider some words to be alternate spellings of other words and
|
||||
# in those cases we want to normalize the spellings to our preferred
|
||||
# spelling.
|
||||
if letter == "alpha":
|
||||
letter = "a"
|
||||
elif letter == "beta":
|
||||
letter = "b"
|
||||
elif letter in ["c", "pre", "preview"]:
|
||||
letter = "rc"
|
||||
elif letter in ["rev", "r"]:
|
||||
letter = "post"
|
||||
|
||||
return letter, int(number)
|
||||
if not letter and number:
|
||||
# We assume if we are given a number, but we are not given a letter
|
||||
# then this is using the implicit post release syntax (e.g. 1.0-1)
|
||||
letter = "post"
|
||||
|
||||
return letter, int(number)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
_local_version_separators = re.compile(r"[\._-]")
|
||||
|
||||
|
||||
def _parse_local_version(local: str) -> Optional[LocalType]:
|
||||
"""
|
||||
Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
|
||||
"""
|
||||
if local is not None:
|
||||
return tuple(
|
||||
part.lower() if not part.isdigit() else int(part)
|
||||
for part in _local_version_separators.split(local)
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def _cmpkey(
|
||||
epoch: int,
|
||||
release: Tuple[int, ...],
|
||||
pre: Optional[Tuple[str, int]],
|
||||
post: Optional[Tuple[str, int]],
|
||||
dev: Optional[Tuple[str, int]],
|
||||
local: Optional[Tuple[SubLocalType]],
|
||||
) -> CmpKey:
|
||||
|
||||
# When we compare a release version, we want to compare it with all of the
|
||||
# trailing zeros removed. So we'll use a reverse the list, drop all the now
|
||||
# leading zeros until we come to something non zero, then take the rest
|
||||
# re-reverse it back into the correct order and make it a tuple and use
|
||||
# that for our sorting key.
|
||||
_release = tuple(
|
||||
reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
|
||||
)
|
||||
|
||||
# We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
|
||||
# We'll do this by abusing the pre segment, but we _only_ want to do this
|
||||
# if there is not a pre or a post segment. If we have one of those then
|
||||
# the normal sorting rules will handle this case correctly.
|
||||
if pre is None and post is None and dev is not None:
|
||||
_pre: PrePostDevType = NegativeInfinity
|
||||
# Versions without a pre-release (except as noted above) should sort after
|
||||
# those with one.
|
||||
elif pre is None:
|
||||
_pre = Infinity
|
||||
else:
|
||||
_pre = pre
|
||||
|
||||
# Versions without a post segment should sort before those with one.
|
||||
if post is None:
|
||||
_post: PrePostDevType = NegativeInfinity
|
||||
|
||||
else:
|
||||
_post = post
|
||||
|
||||
# Versions without a development segment should sort after those with one.
|
||||
if dev is None:
|
||||
_dev: PrePostDevType = Infinity
|
||||
|
||||
else:
|
||||
_dev = dev
|
||||
|
||||
if local is None:
|
||||
# Versions without a local segment should sort before those with one.
|
||||
_local: LocalType = NegativeInfinity
|
||||
else:
|
||||
# Versions with a local segment need that segment parsed to implement
|
||||
# the sorting rules in PEP440.
|
||||
# - Alpha numeric segments sort before numeric segments
|
||||
# - Alpha numeric segments sort lexicographically
|
||||
# - Numeric segments sort numerically
|
||||
# - Shorter versions sort before longer versions when the prefixes
|
||||
# match exactly
|
||||
_local = tuple(
|
||||
(i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
|
||||
)
|
||||
|
||||
return epoch, _release, _pre, _post, _dev, _local
|
||||
7
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/conftest.py
vendored
Normal file
7
dashboard/flask-server/venv/Lib/site-packages/sklearn/externals/conftest.py
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Do not collect any tests in externals. This is more robust than using
|
||||
# --ignore because --ignore needs a path and it is not convenient to pass in
|
||||
# the externals path (very long install-dependent path in site-packages) when
|
||||
# using --pyargs
|
||||
def pytest_ignore_collect(path, config):
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user