Metadata-Version: 2.1
Name: linalgkit-lab
Version: 0.1.1
Summary: Comprehensive linear algebra library for education and research
Home-page: https://github.com/yourusername/linalgkit
Author: linalgkit contributors
Author-email: linalgkit@example.com
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Intended Audience :: Education
Classifier: Intended Audience :: Science/Research
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Provides-Extra: dev

# linalgkit

**A comprehensive, general-purpose Linear Algebra library for Python** — built directly from a complete university syllabus covering six modules.

```bash
pip install linalgkit-lab
```

---

## Modules Covered

| Module | Topic | Functions |
|--------|-------|-----------|
| I | Linear Systems & Gaussian Elimination | `solve_linear_system`, `gaussian_elimination`, `gauss_jordan_elimination`, `row_echelon_form`, `reduced_row_echelon_form`, `elementary_matrix`, … |
| II | Vector Spaces | `are_linearly_independent`, `span_basis`, `subspace_sum`, `subspace_intersection`, `is_direct_sum`, `extend_to_basis`, … |
| III | Linear Transformations | `kernel`, `image`, `rank_nullity`, `matrix_of_transformation`, `change_of_basis_matrix`, `is_isomorphism`, … |
| IV | Orthogonality | `gram_schmidt`, `gram_schmidt_qr`, `orthogonal_complement`, `is_orthogonal_matrix`, `is_unitary_matrix`, `project_onto_subspace`, … |
| V | Eigenvalues & Eigenvectors | `eigenvalues`, `eigenspaces`, `diagonalize`, `spectral_decomposition`, `orthogonal_diagonalize_symmetric`, `unitary_diagonalize_hermitian`, … |
| VI | Canonical Forms | `classify_quadratic_form`, `classify_conic`, `classify_quadric`, `verify_cayley_hamilton`, `minimal_polynomial`, `bilinear_form`, … |

---

## Quick Examples

```python
import linalgkit as la
import numpy as np

# ── Module I: Solve a linear system ─────────────────────────────
A = [[2, 1, -1], [1, -1, 2], [3, 2, 1]]
b = [8, -2, 11]
result = la.solve_linear_system(A, b)
print(result['solution_str'])
# Unique solution: x = [2. 3. 1.]

# Show row-reduction steps for lab work
worked = la.solve_linear_system(A, b, step=True)
for item in worked["steps"]:
    print(item["operation"])

# Infinite solutions
A2 = [[1, 2, 3], [4, 5, 6]]
b2 = [1, 2]
res2 = la.solve_linear_system(A2, b2)
print("Null space basis:", res2['null_space_basis'])

# ── Module I: Elementary matrices ────────────────────────────────
E = la.elementary_matrix(3, 'swap', 0, 1)           # swap rows 0,1
E2 = la.elementary_matrix(3, 'scale', 0, scalar=2)  # scale row 0
E3 = la.elementary_matrix(3, 'add', 1, j=0, scalar=-3)  # R1 -= 3*R0

# ── Module II: Vector spaces ─────────────────────────────────────
vectors = [[1, 0, 0], [0, 1, 0], [1, 1, 0]]  # third is redundant
basis = la.span_basis(vectors)
print("Basis size:", len(basis))   # 2

U_basis = [[1, 0, 0], [0, 1, 0]]
V_basis = [[0, 0, 1]]
print(la.is_direct_sum(U_basis, V_basis))  # {'is_direct_sum': True, ...}

# ── Module III: Linear Transformations ───────────────────────────
A = [[1, 2, 3], [0, 1, 4], [0, 0, 1]]
k = la.kernel(A)
im = la.image(A)
rn = la.rank_nullity(A)
print(f"Rank={rn['rank']}, Nullity={rn['nullity']}, Domain dim={rn['domain_dim']}")

# Matrix of transformation w.r.t. custom bases
def T(v): return np.array([v[0]+v[1], v[0]-v[1]])
M = la.matrix_of_transformation(T, [[1,0],[0,1]], [[1,0],[0,1]])

# ── Module IV: Orthogonality ─────────────────────────────────────
vectors = [[1, 1, 0], [1, 0, 1], [0, 1, 1]]
orth_basis = la.gram_schmidt(vectors, normalize_output=True)
print("Orthonormal?", la.is_orthonormal_set(orth_basis))  # True

comp = la.orthogonal_complement([[1, 0, 0]], ambient_dim=3)
print("Complement dim:", len(comp))  # 2

# ── Module V: Eigenvalues & Eigenvectors ─────────────────────────
A = [[3, 1], [1, 3]]
spaces = la.eigenspaces(A)
for sp in spaces:
    print(f"λ={sp['eigenvalue']}, AM={sp['algebraic_multiplicity']}, GM={sp['geometric_multiplicity']}")

P, D, Pinv = la.diagonalize(A)
print("Verified:", np.allclose(P @ D @ Pinv, A))  # True

sd = la.spectral_decomposition(A)
print("Spectral recon correct:", np.allclose(sd['verification'], A))

# ── Module VI: Canonical Forms ───────────────────────────────────
A = [[1, 0], [0, -2]]
res = la.classify_quadratic_form(A)
print(res['classification'])   # Indefinite

conic_A = [[1, 0], [0, 2]]
print(la.classify_conic(conic_A)['type'])   # Ellipse

quadric_A = np.diag([1.0, 2.0, 3.0])
print(la.classify_quadric(quadric_A)['type'])   # Ellipsoid

ch = la.verify_cayley_hamilton([[1, 2], [3, 4]])
print("Cayley-Hamilton:", ch['verified'])   # True
```

## Lab Notebook Helpers

Most notebook-style routines are available directly from the package:

```python
la.compute_rank_with_rref(A, step=True)
la.solve_homogeneous_system(A, step=True)
la.check_linear_independence(vectors, step=True)
la.find_basis_and_dimension(vectors, step=True)
la.check_direct_sum(U_basis, W_basis, ambient_dim=3, step=True)
la.verify_rank_nullity_theorem(A, step=True)
la.gram_schmidt_orthogonalization(vectors, step=True)
la.orthogonal_complement_basis(basis, ambient_dim=3, step=True)
la.compute_eigen(A, step=True)
la.diagonalize_matrix(A, step=True)
```

When `step=False` (the default), existing return values are preserved. When
`step=True`, functions return a dictionary with the computed result and a
`steps` field containing the intermediate operations or explanation.

---

## Edge Cases Handled

- **Inconsistent systems** → detected and reported cleanly
- **Rank-deficient matrices** → null-space basis always returned
- **Dependent vectors** → Gram-Schmidt skips, `span_basis` reduces
- **Singular matrices** → `matrix_inverse_via_gauss_jordan` returns `None`
- **Non-diagonalizable matrices** → `diagonalize` returns `None`
- **Non-symmetric input to quadratic form** → auto-symmetrized
- **Complex matrices** → full complex inner product / unitary support

---

## Requirements

- Python ≥ 3.8
- NumPy ≥ 1.21

---

## License

MIT
