| name | mathematics-formal |
| description | Formal mathematics for scientific computing — symbolic computation (sympy), numerical linear algebra, optimization (convex/non-convex), information theory, and numerical precision issues. Use when working with mathematical derivations, proofs, or rigorous numerical analysis. |
| allowed_agents | ["experiment","native_coding","ideation"] |
Mathematics (Formal and Computational)
Overview
This skill bridges formal mathematics and scientific computing, covering symbolic computation, numerical methods, optimization theory, and common numerical pitfalls. Use it when mathematical rigor or numerical correctness is central to your research.
When to Use This Skill
- Deriving or verifying mathematical expressions symbolically
- Implementing numerically stable algorithms
- Choosing and applying optimization methods
- Working with probability distributions or information theory
- Checking gradient implementations or matrix computations
1. Symbolic Computation with SymPy
import sympy as sp
x, y, t, n = sp.symbols("x y t n", real=True)
alpha, beta = sp.symbols("alpha beta", positive=True)
expr = (x + y)**3
print(sp.expand(expr))
print(sp.factor(x**2 - 1))
f = sp.exp(-alpha * x**2)
df = sp.diff(f, x)
integral = sp.integrate(f, (x, -sp.oo, sp.oo))
print(f"∫ exp(-αx²) dx = {integral}")
series = sp.series(sp.sin(x), x, 0, n=7)
print(series)
solutions = sp.solve(x**2 + 2*x - 3, x)
y_func = sp.Function("y")
ode = sp.Eq(y_func(t).diff(t) + alpha * y_func(t), 0)
sol = sp.dsolve(ode, y_func(t))
print(sol)
A = sp.Matrix([[1, 2], [3, 4]])
print(A.det())
print(A.eigenvals())
print(A.inv())
2. Numerical Linear Algebra
import numpy as np
from scipy import linalg
A = np.array([[1, 2], [2, 4.001]])
cond = np.linalg.cond(A)
print(f"Condition number: {cond:.2e}")
b = np.array([1.0, 2.0])
x = np.linalg.solve(A, b)
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import spsolve
A_sparse = csr_matrix(A)
x_sparse = spsolve(A_sparse, b)
U, s, Vh = np.linalg.svd(A)
k = 1
A_approx = (U[:, :k] * s[:k]) @ Vh[:k, :]
rank = np.linalg.matrix_rank(A, tol=1e-10)
A_pinv = np.linalg.pinv(A)
eigenvalues, eigenvectors = np.linalg.eigh(A.T @ A)
eigenvalues_g, eigenvectors_g = np.linalg.eig(A)
3. Optimization
Convex Optimization with CVXPY
import cvxpy as cp
import numpy as np
n, d = 100, 20
X = np.random.randn(n, d)
y = np.random.randn(n)
beta = cp.Variable(d)
lambda_reg = 0.1
objective = cp.Minimize(cp.sum_squares(X @ beta - y) + lambda_reg * cp.norm1(beta))
problem = cp.Problem(objective)
problem.solve()
print(f"Optimal beta: {beta.value}")
Unconstrained Optimization with SciPy
from scipy.optimize import minimize
import numpy as np
def rosenbrock(x):
return sum(100*(x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
def rosenbrock_grad(x):
grad = np.zeros_like(x)
grad[:-1] += -400 * x[:-1] * (x[1:] - x[:-1]**2) - 2 * (1 - x[:-1])
grad[1:] += 200 * (x[1:] - x[:-1]**2)
return grad
result = minimize(
rosenbrock,
x0=np.zeros(5),
jac=rosenbrock_grad,
method="L-BFGS-B",
options={"maxiter": 1000, "ftol": 1e-12},
)
print(f"Minimum: {result.fun:.6f} at x = {result.x}")
Optimization Method Selection
| Scenario | Recommended method |
|---|
| Convex, structured problem | CVXPY (disciplined convex programming) |
| Smooth, unconstrained | L-BFGS-B (gradient-based) |
| Smooth, constrained | SLSQP (equality + inequality constraints) |
| Non-smooth or derivative-free | Nelder-Mead, differential evolution |
| Large-scale ML (neural nets) | Adam, AdamW (with torch.optim) |
| Bayesian hyperparameter opt | Optuna, BoTorch |
4. Probability Theory
from scipy import stats
import numpy as np
normal = stats.norm(loc=0, scale=1)
poisson = stats.poisson(mu=5)
beta_dist = stats.beta(a=2, b=5)
print(f"Normal: mean={normal.mean()}, var={normal.var()}")
print(f"Poisson: mean={poisson.mean()}, var={poisson.var()}")
x = np.linspace(-3, 3, 100)
pdf = normal.pdf(x)
cdf = normal.cdf(x)
samples = normal.rvs(size=1000, random_state=42)
n_samples = 1000
means = [stats.expon(scale=2).rvs(size=30).mean() for _ in range(n_samples)]
print(f"Mean of means: {np.mean(means):.3f}, std: {np.std(means):.3f}")
print(f"Expected (CLT): {2:.3f}, {2/np.sqrt(30):.3f}")
5. Information Theory
import numpy as np
from scipy.stats import entropy
p = np.array([0.5, 0.3, 0.2])
H = entropy(p, base=2)
print(f"Entropy: {H:.3f} bits (max for 3 outcomes = log₂(3) = {np.log2(3):.3f})")
p_dist = np.array([0.4, 0.4, 0.2])
q_dist = np.array([0.33, 0.33, 0.34])
kl_pq = entropy(p_dist, q_dist, base=2)
kl_qp = entropy(q_dist, p_dist, base=2)
print(f"KL(P||Q) = {kl_pq:.3f}, KL(Q||P) = {kl_qp:.3f}")
p_xy = np.array([[0.2, 0.1], [0.15, 0.25], [0.1, 0.2]])
p_x = p_xy.sum(axis=1)
p_y = p_xy.sum(axis=0)
H_xy = entropy(p_xy.flatten(), base=2)
I_xy = entropy(p_x, base=2) + entropy(p_y, base=2) - H_xy
print(f"Mutual information I(X;Y) = {I_xy:.3f} bits")
def logsumexp(log_probs):
max_lp = log_probs.max()
return max_lp + np.log(np.exp(log_probs - max_lp).sum())
log_probs = np.array([-1000., -1001., -1002.])
print(f"log∑exp = {logsumexp(log_probs):.3f}")
6. Numerical Precision
import numpy as np
eps = np.finfo(float).eps
print(f"Machine epsilon: {eps:.2e}")
a, b = 1.0000001, 1.0
bad_result = a - b
good_result = np.float128(a) - np.float128(b)
def safe_log1p(x):
"""Numerically stable log(1+x) for small x."""
return np.log1p(x)
def safe_expm1(x):
"""Numerically stable exp(x)-1 for small x."""
return np.expm1(x)
def kahan_sum(values):
total = 0.0
compensation = 0.0
for v in values:
y = v - compensation
t = total + y
compensation = (t - total) - y
total = t
return total
def stable_softmax(x):
x_shifted = x - x.max()
exp_x = np.exp(x_shifted)
return exp_x / exp_x.sum()
Key rules:
- Check condition number before solving linear systems — if > 1e6, add regularization
- Use
np.linalg.solve() not inv(A) @ b
- Use
log1p(x) and expm1(x) for small x
- Apply the log-sum-exp trick when computing log-sums of probabilities
- Never compare floats with
== — use np.isclose(a, b, rtol=1e-5)