lumpy-la 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lumpy/__init__.py +8 -0
- lumpy/constructors.py +60 -0
- lumpy/core.py +41 -0
- lumpy/decompositions.py +17 -0
- lumpy/equations.py +15 -0
- lumpy/geometry.py +36 -0
- lumpy/spaces.py +53 -0
- lumpy/utils.py +5 -0
- lumpy_la-0.1.0.dist-info/METADATA +6 -0
- lumpy_la-0.1.0.dist-info/RECORD +12 -0
- lumpy_la-0.1.0.dist-info/WHEEL +5 -0
- lumpy_la-0.1.0.dist-info/top_level.txt +1 -0
lumpy/__init__.py
ADDED
lumpy/constructors.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .utils import is_vector
|
|
3
|
+
|
|
4
|
+
def mat(*columns, dtype=float):
|
|
5
|
+
""""
|
|
6
|
+
Construct a matrix from columns.
|
|
7
|
+
|
|
8
|
+
Lists are interpreted as column entries. Existing column
|
|
9
|
+
vectors may also be passed directly.
|
|
10
|
+
"""
|
|
11
|
+
processed = []
|
|
12
|
+
|
|
13
|
+
for col in columns:
|
|
14
|
+
# Python list -> column vector
|
|
15
|
+
if isinstance(col, list):
|
|
16
|
+
col = np.array(col, dtype=dtype).reshape(-1,1)
|
|
17
|
+
|
|
18
|
+
if col.ndim != 2 or col.shape[1] != 1:
|
|
19
|
+
raise ValueError("mat() expects columns: lists or column vectors.")
|
|
20
|
+
|
|
21
|
+
processed.append(col)
|
|
22
|
+
|
|
23
|
+
if not processed:
|
|
24
|
+
raise ValueError("mat() requires at least one column.")
|
|
25
|
+
|
|
26
|
+
return np.hstack(processed).astype(dtype)
|
|
27
|
+
|
|
28
|
+
def matt(*rows, dtype=float):
|
|
29
|
+
"""
|
|
30
|
+
Construct a matrix from rows.
|
|
31
|
+
|
|
32
|
+
matt() preserves the usual visual layout of matrices,
|
|
33
|
+
while mat() preserves Lumpy's column-oriented semantics.
|
|
34
|
+
"""
|
|
35
|
+
if not rows:
|
|
36
|
+
raise ValueError("matt() requires at least one row.")
|
|
37
|
+
return mat(*rows, dtype=dtype).T
|
|
38
|
+
|
|
39
|
+
def vec(*entries, dtype=float):
|
|
40
|
+
"""Construct a column vector."""
|
|
41
|
+
return mat(list(entries), dtype=dtype)
|
|
42
|
+
|
|
43
|
+
def eye(n, dtype=float):
|
|
44
|
+
"""Construct the n x n identity matrix."""
|
|
45
|
+
return np.eye(n, dtype=dtype)
|
|
46
|
+
|
|
47
|
+
def e(n, i, dtype=float):
|
|
48
|
+
"""
|
|
49
|
+
e(n, i) returns the standard basis vector corresponding
|
|
50
|
+
to the mathematical vector e_(i+1) in R^n.
|
|
51
|
+
|
|
52
|
+
Indexing is 0-based to remain consistent with Python/NumPy.
|
|
53
|
+
"""
|
|
54
|
+
e = np.zeros((n,1), dtype=dtype)
|
|
55
|
+
e[i] = 1
|
|
56
|
+
return e
|
|
57
|
+
|
|
58
|
+
def diag(*entries, dtype=float):
|
|
59
|
+
"""Construct a diagonal matrix with given entries."""
|
|
60
|
+
return np.diag(entries).astype(dtype)
|
lumpy/core.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .utils import is_vector
|
|
3
|
+
|
|
4
|
+
def col(A, i):
|
|
5
|
+
"""Return column i as a column vector."""
|
|
6
|
+
return A[:, [i]]
|
|
7
|
+
|
|
8
|
+
def row(A, i):
|
|
9
|
+
"""Return row i as a row matrix."""
|
|
10
|
+
return A[[i], :]
|
|
11
|
+
|
|
12
|
+
def inner(A,B):
|
|
13
|
+
"""Inner product of matrices."""
|
|
14
|
+
return A.T @ B
|
|
15
|
+
|
|
16
|
+
def dot(u,v):
|
|
17
|
+
"""Dot product of vectors."""
|
|
18
|
+
if not(is_vector(u) and is_vector(v)):
|
|
19
|
+
raise ValueError("dot() requires column vectors.")
|
|
20
|
+
return (u.T @ v).item()
|
|
21
|
+
|
|
22
|
+
def norm(v):
|
|
23
|
+
"""Euclidean norm of a column vector."""
|
|
24
|
+
return np.linalg.norm(v)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def T(A):
|
|
28
|
+
"""Transpose of A."""
|
|
29
|
+
return A.T
|
|
30
|
+
|
|
31
|
+
def tr(A):
|
|
32
|
+
"""Trace of A."""
|
|
33
|
+
return np.trace(A)
|
|
34
|
+
|
|
35
|
+
def adj(A):
|
|
36
|
+
"""Adjoint (conjugate transpose) of A."""
|
|
37
|
+
return A.conj().T
|
|
38
|
+
|
|
39
|
+
def det(A):
|
|
40
|
+
"""Determinant of A."""
|
|
41
|
+
return np.linalg.det(A)
|
lumpy/decompositions.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
def svd(A, full_matrices=False, tol=1e-12):
|
|
4
|
+
"""
|
|
5
|
+
Return the singular value decomposition of A.
|
|
6
|
+
|
|
7
|
+
By default, returns only the rank-relevant singular directions:
|
|
8
|
+
|
|
9
|
+
A = U @ diag(s) @ Vt
|
|
10
|
+
|
|
11
|
+
If full_matrices=True, returns NumPy's full SVD.
|
|
12
|
+
"""
|
|
13
|
+
U, s, Vt = np.linalg.svd(A, full_matrices=full_matrices)
|
|
14
|
+
if not full_matrices:
|
|
15
|
+
rank = np.sum(s > tol)
|
|
16
|
+
return U[:,:rank], s[:rank], Vt[:rank,:]
|
|
17
|
+
return U, s, Vt
|
lumpy/equations.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
def solve(A, b):
|
|
4
|
+
"""
|
|
5
|
+
Solve Ax = b.
|
|
6
|
+
Prefer solve() over explicitly computing inv(A) @ b.
|
|
7
|
+
"""
|
|
8
|
+
return np.linalg.solve(A, b)
|
|
9
|
+
|
|
10
|
+
def lstsq(A, b, rcond=None):
|
|
11
|
+
"""
|
|
12
|
+
Return the least-squares solution to Ax ≈ b.
|
|
13
|
+
"""
|
|
14
|
+
x, residuals, rank, s = np.linalg.lstsq(A, b, rcond=rcond)
|
|
15
|
+
return x
|
lumpy/geometry.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .utils import is_vector
|
|
3
|
+
from .core import norm, dot
|
|
4
|
+
|
|
5
|
+
def dist(u, v):
|
|
6
|
+
"""
|
|
7
|
+
Return the Euclidean distance between two column vectors u and v.
|
|
8
|
+
"""
|
|
9
|
+
if not(is_vector(u) and is_vector(v)):
|
|
10
|
+
raise ValueError("dist() requires column vectors.")
|
|
11
|
+
return norm(u - v)
|
|
12
|
+
|
|
13
|
+
def angle(u, v):
|
|
14
|
+
"""
|
|
15
|
+
Return the angle in radians between two column vectors u and v.
|
|
16
|
+
"""
|
|
17
|
+
if not(is_vector(u) and is_vector(v)):
|
|
18
|
+
raise ValueError("angle() requires column vectors.")
|
|
19
|
+
return np.arccos(dot(u,v)/(norm(u)*norm(v)))
|
|
20
|
+
|
|
21
|
+
def normalize(A):
|
|
22
|
+
"""
|
|
23
|
+
Normalize each column of A.
|
|
24
|
+
"""
|
|
25
|
+
norms = np.linalg.norm(A, axis=0)
|
|
26
|
+
|
|
27
|
+
if np.any(norms == 0):
|
|
28
|
+
raise ValueError("Cannot normalize a matrix with zero columns.")
|
|
29
|
+
|
|
30
|
+
return A / norms
|
|
31
|
+
|
|
32
|
+
def unit(v):
|
|
33
|
+
"""Return unit vector in direction of v."""
|
|
34
|
+
if not is_vector(v):
|
|
35
|
+
raise ValueError("unit() requires a column vector.")
|
|
36
|
+
return normalize(v)
|
lumpy/spaces.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .decompositions import svd
|
|
3
|
+
|
|
4
|
+
def rank(A, tol=1e-12):
|
|
5
|
+
"""
|
|
6
|
+
Return the rank of A.
|
|
7
|
+
"""
|
|
8
|
+
_, s, _ = svd(A,tol=tol)
|
|
9
|
+
return len(s)
|
|
10
|
+
|
|
11
|
+
def orth(A,tol=1e-12):
|
|
12
|
+
"""
|
|
13
|
+
Return an orthonormal basis for the column space of A.
|
|
14
|
+
"""
|
|
15
|
+
U, _, _ = svd(A, tol=tol)
|
|
16
|
+
return U
|
|
17
|
+
|
|
18
|
+
def null(A, tol=1e-12):
|
|
19
|
+
"""
|
|
20
|
+
Return an orthonormal basis for the null space of A.
|
|
21
|
+
"""
|
|
22
|
+
U, s, Vt = svd(A, full_matrices=True, tol=tol)
|
|
23
|
+
rank = np.sum(s > tol)
|
|
24
|
+
return Vt[rank:].T
|
|
25
|
+
|
|
26
|
+
def proj(A,B,tol=1e-12):
|
|
27
|
+
"""
|
|
28
|
+
Orthogonal projection of B onto the column space of A.
|
|
29
|
+
Works for vectors and matrices.
|
|
30
|
+
"""
|
|
31
|
+
Q = orth(A,tol=tol)
|
|
32
|
+
return Q @ Q.T @ B
|
|
33
|
+
|
|
34
|
+
def independent(A):
|
|
35
|
+
"""
|
|
36
|
+
Return True if the columns of A are linearly independent.
|
|
37
|
+
"""
|
|
38
|
+
return rank(A) == A.shape[1]
|
|
39
|
+
|
|
40
|
+
def row_space(A, tol=1e-12):
|
|
41
|
+
"""
|
|
42
|
+
Return an orthonormal basis for the row space of A as columns.
|
|
43
|
+
"""
|
|
44
|
+
return orth(A.T, tol=tol)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def left_null(A, tol=1e-12):
|
|
48
|
+
"""
|
|
49
|
+
Return an orthonormal basis for the left nullspace of A as columns.
|
|
50
|
+
|
|
51
|
+
This is Null(A.T).
|
|
52
|
+
"""
|
|
53
|
+
return null(A.T, tol=tol)
|
lumpy/utils.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
lumpy/__init__.py,sha256=djC4qOHAGk36ucoxTLpkduYSkHdLXm1fKgYGuPIOxP0,180
|
|
2
|
+
lumpy/constructors.py,sha256=KYF-ocV9gLIXcBCuFUGAwqhjq6_8XQ18x-1bC3zuhb4,1659
|
|
3
|
+
lumpy/core.py,sha256=90zFaPs3AEG22mZJkFh8NZ4lg_SqyPlKLmQKYLp0msg,811
|
|
4
|
+
lumpy/decompositions.py,sha256=SJugXczclrxbz6z_aug-8pVa_Uu8D-BPZwL0OryjvJg,469
|
|
5
|
+
lumpy/equations.py,sha256=ZOjeVAD6IUF78WVYmVr_ZMjMoaj0Gb4zLnam3pJ8HRU,333
|
|
6
|
+
lumpy/geometry.py,sha256=dbaYtrCg2lG0APtiWYzvCdzB9RfO7pNfztvAhRvGyYY,959
|
|
7
|
+
lumpy/spaces.py,sha256=_WmB0XNqgFpmVhUStg-fPspO8Ya9wkC0WhCisqnzkSA,1138
|
|
8
|
+
lumpy/utils.py,sha256=cRhYKts5QqK36s9AR5j8TPMtBDA7R2iXOloYQqvI4-0,121
|
|
9
|
+
lumpy_la-0.1.0.dist-info/METADATA,sha256=4eM2trAVVRixNGnWCe07wJoxgmHEzJRZNoa1rwBFdks,132
|
|
10
|
+
lumpy_la-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
11
|
+
lumpy_la-0.1.0.dist-info/top_level.txt,sha256=a9ZtsYv09s-13PjorxfmuOle25Oyvgj5mpNFysCP19U,6
|
|
12
|
+
lumpy_la-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
lumpy
|