#!/usr/bin/env catnip
# Calcul symbolique avec SymPy
# Variables, dérivation, intégration, résolution d'équations
#
# DEPS: sympy

sympy = import('sympy')

# Symboles (avec hypothèses: réels)
x = sympy.Symbol("x", real=True)
y = sympy.Symbol("y", real=True)
t = sympy.Symbol("t", real=True)

print("⇒ Expressions et simplification")
p = x ** 2 + 2 * x + 1
print("  p(x) =", p)
print("  factor(p) =", sympy.factor(p))
print("  p(3) =", p.subs(x, 3))
print("  p(3) numérique =", sympy.N(p.subs(x, 3), 8))

identite = sympy.sin(x) ** 2 + sympy.cos(x) ** 2
print("  sin(x)^2 + cos(x)^2 =", identite)
print("  simplifié =", sympy.simplify(identite))

print()
print("⇒ Développement / factorisation")
expanded = sympy.expand((x + y) ** 4)
print("  expand((x+y)^4) =", expanded)
print("  factor(expand(...)) =", sympy.factor(expanded))

print()
print("⇒ Dérivées")
f = sympy.exp(-x ** 2)
df = sympy.diff(f, x)
d2f = sympy.diff(f, x, 2)
print("  f(x) =", f)
print("  f'(x) =", df)
print("  f''(x) =", d2f)

# Dérivées partielles et gradient
g = x ** 2 * sympy.sin(y)
grad_g = list(sympy.diff(g, x), sympy.diff(g, y))
print("  g(x,y) =", g)
print("  ∂g/∂x =", grad_g[0])
print("  ∂g/∂y =", grad_g[1])
print("  grad(g) =", grad_g)

print()
print("⇒ Intégrales")
print("  ∫ x^2 dx =", sympy.integrate(x ** 2, x))
int_0_1 = sympy.integrate(x ** 2, tuple(x, 0, 1))
print("  ∫_0^1 x^2 dx =", int_0_1)
print("  valeur numérique =", sympy.N(int_0_1, 10))

# Intégrale impropre gaussienne
gauss = sympy.integrate(sympy.exp(-x ** 2), tuple(x, -sympy.oo, sympy.oo))
print("  ∫_{-∞}^{+∞} exp(-x^2) dx =", gauss)
print("  valeur numérique =", sympy.N(gauss, 10))

print()
print("⇒ Équations")
sols = sympy.solve(x ** 2 - 5 * x + 6, x)
print("  x^2 - 5x + 6 = 0 ->", sols)

# Système linéaire
sol_sys = sympy.solve(list(x + y - 5, x - y - 1), list(x, y))
print("  x+y=5, x-y=1 ->", sol_sys)

# Équation différentielle: f' + f = 0
f_sym = sympy.Function("f")
ode = sympy.Eq(f_sym(t).diff(t) + f_sym(t), 0)
sol_ode = sympy.dsolve(ode, f_sym(t))
print("  f'(t)+f(t)=0 ->", sol_ode)

print()
print("⇒ Limites et séries")
print("  lim(sin(x)/x, x->0) =", sympy.limit(sympy.sin(x) / x, x, 0))
print("  lim((1+1/x)^x, x->∞) =", sympy.limit((1 + 1 / x) ** x, x, sympy.oo))

taylor = sympy.series(sympy.cos(x), x, 0, n=6)
print("  série de Taylor de cos(x) à l'ordre 5 =", taylor)

print()
print("⇒ Matrices symboliques")
M = sympy.Matrix(list(list(1, x), list(x, 1)))
print("  M =", M)
print("  det(M) =", M.det())
print("  M^{-1} =", M.inv())
print("  valeurs propres =", M.eigenvals())