Matematikai Algoritmusok és Felfedezések II.

1. SymPy.

2021 szeptember 9.

Technikai információk

Oktatók

Előadás: Damásdi Gábor damasdigabor@caesar.elte.com

  • (Iroda: Déli 3.508)
  • Fogadó óra: Előzetes egyeztetés szerint.

Gyakorlat:

  • Dobrovoczki Péter pdobrovoczki@caesar.elte.hu

Anyagok elérhetősége:

Tantárgy célja

  • Matematikusok számára hasznos programozási tudás átadása
  • Programozás általános folyamatának gyakorlása
  • Egy programozási nyelv (Python) alapjainak elsajátítása
  • Matematikusoknak hasznos programozási könyvtárak megismerése
  • Matematikai algoritmusok implementálása
  • Alapozás későbbi órákhoz(Algoritmusok tervezése és elemzése, Adatbányászat, Deep learning)

Tematika

  • Haladó Python
  • Hasznos könyvtárak
  • Matematikai témák/algoritmusok

Lesznek meghívott előadók

  • Differenciálegyenletek
  • Algoritmusok
  • Gépi tanulás
  • Optimalizáció, solverek

Követelmények

  • Beadandó feladat elkészítése
  • Beadandó feladat bemutatása

Az általunk használt programozási környezet

  • Python
  • Jupyter
  • Kooplex
  • Anaconda
  • Github

Kérdések?

Szimbolikus programozás

Tudományos csomagok (Python Scientific stack)

csomag
NumPy Hatékony N-dimenziós tömb
SciPy Numerikus számítások
Matplotlib Grafikonok és rajzok
IPython (Jupyter) Interaktív notebook
SymPy Szimbolikus számítások
Pandas Adatbányászat
In [ ]:
import sympy as sym
import math
import numpy as np
import matplotlib.pyplot as plt

A python alapból kerekítve tárolja a float-okat

In [ ]:
math.log(16), math.log(16, 2), math.exp(2), math.exp(math.log(10)),math.sqrt(8)
$$\pi^4+\pi^5$$

$$=?$$ $$e^6$$

In [ ]:
np.pi**4+np.pi**5-np.e**6

Szimbolikus számítások

A szimbolikus számítások célja, hogy a matematikai objektumokat precízen kezelje, kerekítések nélkül, és hogy formális objektumokkal is tudjunk számolni, mint például polinomok vagy függvények.

Előnyök:

  • Pontos eredmény
  • Közelebb van a matematikai gondolkodásmódhoz

Hátrányok:

  • Körülményes használni
  • Lassabb
  • Sok minden megoldhatatlan pontosan

SymPy

A SymPy három új típust vezet be a számoknak: Real, Rational és Integer.

In [ ]:
a = sym.Rational(1, 2)
In [ ]:
a
In [ ]:
sym.Rational(7)**(sym.Rational(1,2))
In [ ]:
(sym.Rational(7)**(sym.Rational(1,2)))**2
In [ ]:
sym.pi**2

Tetszőleges pontossággal kiértékelhetőek a valós számok:

In [ ]:
sym.pi.evalf()
In [ ]:
sym.pi.evalf(2000)

Itt is van végtelen!

In [ ]:
sym.oo > 99999
In [ ]:
sym.oo+1
In [ ]:
1/-sym.oo

A szokásos műveletek működnek:

In [ ]:
print(sym.Rational(1, 2)+sym.Rational(3, 4))
print(sym.Rational(1, 2)*sym.Rational(3, 4))
print(sym.Rational(1, 2)/sym.Rational(3, 4))
Azért mindent nem tud:
In [ ]:
a=sym.real_root((sym.Rational(8)+sym.real_root(sym.Rational(21),2)*sym.Rational(3)),3)+sym.real_root((sym.Rational(8)-sym.real_root(sym.Rational(21),2)*sym.Rational(3)),3)-1
a
In [ ]:
a.evalf(20)

Szimbolikus változók

A Python változóival szemben itt deklarálni kell a változókat!

In [ ]:
x = sym.Symbol('x')      
y = sym.Symbol('y')
alma=sym.Symbol('z')    #nem kell hogy passzoljanak
In [ ]:
type(x)
In [ ]:
2*x+x**2
In [ ]:
(x+y)**2

Expand

Kifejti az kifejezést

In [ ]:
sym.expand((x + y) ** 3)
In [ ]:
sym.expand(x + y, complex=True)
In [ ]:
sym.expand(sym.cos(x + y),trig=True)

Simplify

Egyszerűsíti a kifejezést

In [ ]:
(x + x * y) / x
In [ ]:
sym.simplify((x + x * y) / x)
In [ ]:
sym.simplify(sym.sin(x)/sym.cos(x))
In [ ]:
sym.trigsimp(sym.sin(x)**2 + sym.cos(x)**2)

Behelyettesítés, kiértékelés

In [ ]:
f=sym.cos(x)+7
f.subs(x,y)
In [ ]:
f # A SymPy objektumai immutableök!! (kivéve a mátrixokat)
In [ ]:
f.subs(x,0)

Szorzattá alakítás

In [ ]:
f = x ** 4 - 3 * x ** 2 + 1
sym.factor(f)
In [ ]:
f = x ** 42 -1
sym.factor(f)

Egyebek

  • apart: parciális törtekre bontás
  • collect: adott változó szerint csoportosítás
In [ ]:
expr = (4*x**3 + 21*x**2 + 10*x + 12)/(x**4 + 5*x**3 + 5*x**2 + 4*x)
expr
In [ ]:
sym.apart(expr)
In [ ]:
expr = x*y + x - 3 + 2*x**2*y**2 - y*x**2 + y**2+x**3
collected_expr = sym.collect(expr, y)
collected_expr
In [ ]:
collected_expr = sym.collect(expr, x)
collected_expr

Számítások

Határérték limit

In [ ]:
print(sym.limit(x, x, sym.oo))
print(sym.limit((2*x+3) / x, x, sym.oo))
print(sym.limit(x ** x, x, 0))

Deriválás

A sym.diff(func, var, n) kiszámolja az n. deriváltat.

In [ ]:
sym.diff(sym.sin(2 * x), x, 2)
In [ ]:
sym.diff(sym.log(x), x, 1)

Taylor sorfejtés

In [ ]:
sym.series(sym.cos(x), x, 0)

Integrálás

In [ ]:
sym.integrate(6 * x ** 5, x)
In [ ]:
sym.integrate(sym.sin(x), x)
In [ ]:
sym.integrate(sym.exp(-x ** 2) * sym.erf(x), x)
In [ ]:
sym.integrate(sym.exp(-x**2 - y**2), (x, -sym.oo, sym.oo), (y, -sym.oo, sym.oo))

Határozott integrál

In [ ]:
sym.integrate(sym.sin(x), (x, 0, sym.pi / 2))

Improprius integrál

In [ ]:
sym.integrate(sym.exp(-x ** 2), (x, -sym.oo, sym.oo))

Egyenletek megoldása

Az első paraméter az egyenlet, aminek a gyökeit keresi, a második a változó.

In [ ]:
sym.solveset(x ** 4 - 1, x)
In [ ]:
a = sym.Symbol('a')      
b = sym.Symbol('b')
c = sym.Symbol('c')
d = sym.Symbol('d')
e = sym.Symbol('e')
f = sym.Symbol('f')
In [ ]:
sym.solveset(a*x ** 2 + b*x +c , x)
In [ ]:
sym.solveset(a*x ** 3 + b*x**2 +c*x+d , x) 
In [ ]:
sym.solveset(a*x ** 4 + b*x**3 +c*x**2+d*x+e , x) 
In [ ]:
sym.solveset(a*x ** 5 + b*x**4 +c*x**3+d*x**2+e*x+f , x)

Ezzel szemben a Numpy simán megold nekünk magasabb rendű polinomokat numerikusan:

In [ ]:
coeff = [1, 2, 1,2,7,9,10,11]
np.roots(coeff)

Lineáris egyenletrendszer

A solve parancsot használhatjuk, ami egy dict-el tér vissza.

In [ ]:
solution = sym.solve((x + 5 * y - 2, -3 * x + 6 * y - 15), (x, y))
solution[x], solution[y]
In [ ]:
z=sym.Symbol('z')
sym.linsolve([x + y + z - 1, x + y + 2*z - 3 ], (x, y, z))
In [ ]:
sym.Matrix([[1, 0], [0, 1]])

A nagy különbség a Numpy tömbjeivel szemben, hogy szimbólumokat is tehetünk bele!

In [ ]:
A = sym.Matrix([[1, x], [y, 1]])
A
In [ ]:
A.det()
In [ ]:
A.eigenvals()
In [ ]:
A.eigenvects()       ## sajátérték, multiplicitás, sajátvetor hármasokat ad vissza
In [ ]:
P, D = A.diagonalize()
print(P)
print(D)
In [ ]:
 P*D*(P**-1)
In [ ]:
sym.simplify( P*D*P**-1)

Bonyolultabb kifejezéseknél olyan problémába is futhatunk, hogy a program nem tudja eldönteni a kifejezésről, hogy 0-e, és elrontja a Gauss-eliminációt. (Ez sajnos elkerülhetetlen: https://en.wikipedia.org/wiki/Constant_problem)

Szimbolikus függvények

In [ ]:
f, g = sym.symbols('f g', cls=sym.Function)
2*f(x)
In [ ]:
f(x).diff(x) + f(x)

Differenciálegyenletek

$f'(x)=f(x)$

In [ ]:
sym.dsolve(f(x).diff(x) - f(x), f(x))
In [ ]:
sym.dsolve(sym.sin(x) * sym.cos(f(x)) + sym.cos(x) * sym.sin(f(x)) * f(x).diff(x), f(x), hint='separable') 

Számelmélet

In [ ]:
sym.isprime(4332221111)
In [ ]:
sym.isprime(314159)
In [ ]:
sym.sieve._list
In [ ]:
120121 in sym.sieve
In [ ]:
sym.sieve._list
In [ ]:
sym.ntheory.generate.prime(100)
In [ ]:
sym.ntheory.factorint(120)

Minden szám előáll legfeljebb 4 négyzetszám összegeként.

In [ ]:
from sympy.solvers.diophantine import diop_general_sum_of_squares
from sympy.abc import a, b, c, d, e
diop_general_sum_of_squares(a**2 + b**2 + c**2 + d**2 - 2345)
In [ ]:
[(i,diop_general_sum_of_squares(a**2 + b**2 + c**2 + d**2 - i)) for i in range (20)]
        
In [ ]:
print(sym.binomial(20,3))
print(sym.factorial(5))
print(sym.gamma(4.5))
print(sym.fibonacci(10))

Példa

Létezik-e négy pont a síkon, hogy bármely kettő távolsága páratlan?

Tegyük fel, hogy létezik, legyen az egyik pont az origó a másik három pedig $(A_x,A_y),(B_x,B_y),(C_x,C_y)$. Legyen $N=\begin{pmatrix} A_y & B_x & C_x\\ A_y & B_y & C_y \end{pmatrix} $

és $M=2NN^T=\begin{pmatrix} 2|A|^2 & 2<A,B> & 2<A,C>\\ 2<A,B> & 2|B|^2 & 2<B,C> \\ 2<A,C> & 2<B,C> & 2|C|^2 \\ \end{pmatrix} =\begin{pmatrix} 2|A|^2 & |A|^2+|B|^2-|AB|^2 & |A|^2+|C|^2-|AC|^2\\ |A|^2+|B|^2-|AB|^2 & 2|B|^2 & |B|^2+|C|^2-|BC|^2 \\ |A|^2+|C|^2-|AC|^2 & |B|^2+|C|^2-|BC|^2 & 2|C|^2 \\ \end{pmatrix} $

Világos hogy $det(M)=0$ mivel $rank(M)\le rank(N)\le 2$

In [ ]:
a = sym.Symbol('a')      
b = sym.Symbol('b')
c = sym.Symbol('c')
d = sym.Symbol('d')
e = sym.Symbol('e')
f = sym.Symbol('f')
ma=2*a+1
mb=2*b+1
mc=2*c+1
md=2*d+1
me=2*e+1
mf=2*f+1

M=sym.Matrix([[2*ma**2, ma**2+mb**2-md**2,ma**2+mc**2-me**2],[ ma**2+mb**2-md**2,2*mb**2,mb**2+mc**2-mf**2],[ ma**2+mc**2-me**2,mb**2+mc**2-mf**2,2*mc**2] ])
M
In [ ]:
expr=sym.simplify(sym.expand(M.det()))
expr
In [ ]:
expr.as_coefficients_dict()
In [ ]:
[a%8 for a in expr.as_coefficients_dict().values()]

Mivel minden együttható osztható 8-al kivéve a konstans tag, a determináns nem lehet osztható 8-al. Tehát nem lehet 0, ellentmondásra jutottunk.