Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Objektno programiranje, simbolno računanje

Fakulteta za strojništvo, Univerza v Ljubljani

Objektno programiranje

Pri programiranju poznamo različne pristope, dokumentacija Python-a (docs.python.org) omenja npr:

  1. proceduralni: seznam navodil, kaj je treba izvesti (npr.: C, Pascal)

  2. deklarativni: opišemo kaj želimo, programski jezik pa izvede (npr., SQL)

  3. funkcijski: programiranje temelji na funkcijah (npr.: Haskell )

  4. objektni: program temelji na objektih, ki imajo lastnosti, funkcije ... (npr.: Java, Smalltalk)

Python je objektno orientiran programski jezik, vendar pa nas ne sili v uporabo objektov v vseh primerih. Kot bomo videli pozneje, ima objektno programiranje veliko prednosti, vendar pa je lahko mnogokrat okorno in bi po nepotrebnem naredilo program kompleksen. Iz tega razloga se eksplicitnemu objektnemu programiranju izognemo, če se le da.

Objektno programiranje v Pythonu temelji na razredih (class), objekti so pa instance (instance) razreda. Pogledali si bomo zgolj nekatere osnove objektnega programiranja (da boste lažje razumeli kodo drugih avtorjev in jo prirejali svojim potrebam).

Razred definiramo z ukazom class (dokumentacija):

class ImeRazreda:
    '''docstring'''
    [izraz 1]
    [izraz 2]
    .
    .

kjer ime razreda (torej ImeRazreda) po PEP8 pišemo z veliko začetnico. Če je ime sestavljeno iz več besed, vsako pišemo z veliko (t. i. principi CamelCase).

Poglejmo si primer:

Preden gremo v podrobnosti razumevanja kode, naredimo instanco razreda (torej objekt):

Funkcije definirane znotraj razreda poimenujemo metode, ko jih kličemo na objektih.

V zgornjem primeru metodo površina uporabimo tako:

1

Ime self je referenca na instanco razreda (objekt, ki bo ustvarjen). Imena znotraj razreda postanejo atributi objekta.

Primer atributa višina:

1

Od kje pride rezultat 1? Ko ustvarimo objekt, se najprej izvede inicializacijska funkcija __init__(), pri tem se kot argumenti funkcije __init__ uporabijo argumenti, ki jih posredujemo v razred.

Primer:

15

Pripravili smo tudi metodo, ki spremeni atribut širina:

100

Atribute lahko spreminjamo tudi neposredno, vendar se temu (zaradi možnosti napake in napačne uporabe) ponavadi izogibamo.

Primer:

300

Dedovanje

Pomembna lastnost razredov je dedovanje; samo ime pove bistvo: tako kot ljudje dedujemo od svojih staršev, podobno velja tudi za razrede. Vsak razred (class) tako lahko deduje lastnosti kakega drugega razreda (dokumentacija). Lahko ima celo več staršev (v te podrobnosti tukaj ne bomo šli).

Sintaksa razreda, ki deduje, je:

class Otrok(Starš):
    [izraz]
    .
    .

Opomba: tudi, če razredu ne definiramo starša, deduje razred object.

Primer, ko novi razred Kvadrat podeduje obstoječega (Pravokotnik):

Poglejmo sedaj uporabo:

Razred Kvadrat nima definicije metode za izračun površine, vendar pa jo je podedoval od razreda Pravokotnik in zato ima metodo za izračun površine:

16

V kolikor spremenimo širino, se ustrezno spremeni površina:

25
Primer dedovanja razreda list (seznam)

Najprej pripravimo seznam:

[1, 2, 3]

Če želimo seznamu dodati vrednost, uporabimo metodo append (to je metoda, ki jo imajo objekti tipa list):

Nato seznam prikažemo (najprej uvozimo matplotlib):

<Figure size 640x480 with 1 Axes>

Če nekaj takega izvajamo pogosto, potem je bolje, da si pripravimo svoj razred Seznam, ki deduje od list in dodamo metodo za prikaz nariši:

Instanca objekta je:

__main__.Seznam
[1, 2, 3]

Čeprav nismo definirali metode append, jo je nov razred podedoval po razredu list:

[1, 2, 3, 1]

Ima tudi metodo za izris:

<Figure size 640x480 with 1 Axes>

Simbolno računanje s SymPy

Termin simbolno računanje pomeni, da matematične izraze rešujemo strojno v obliki abstraktnih simbolov (in ne numerično). Strojno simbolno računanje nam pomaga kadar nas zanima rezultat v simbolni obliki in so izrazi preobsežni za klasično reševanje na list in papir. K strojnemu reševanju se zatečemo tudi zaradi zmanjšanja možnosti napake (pri obsežnih izračunih se ljudje lahko zmotimo).

Simbolno računanje nikakor ni nadomestek numeričnih metod!

Pogledali si bomo nekatere osnove, nekateri priporočeni dodatni viri pa so:

SymPy je eden od sistemov za strojno algebro (CAS - Computer Algebra Systems), ki pa ima poleg zmogljivosti tudi to prednost, da je v celoti napisan v Pythonu (alternativni paket v Pythonu Sage na primer ni v celoti napisan v Pythonu).

Nekatera namenska komercialna orodja:

Najprej uvozimo modul SymPy; tipično paket uvozimo kot sym:

Opazimo lahko, da se SymPy uvaža tudi from sympy import *. Temu se praviloma izogibamo, saj tako s SymPy imeni po nepotrebnem zapolnimo osnovni imenski prostor programa. V slednjem primeru do funkcij paketa (npr. sympy.Sum) dostopamo neposredno (npr. Sum), kar je lahko privlačno, vendar nas začne motiti, ko dodamo še druge pakete (npr. numpy), kar lahko poleg zmede privede do tega, da se funkcije z enakimi imeni “povozijo”.

Zato da dobimo lepo oblikovan LaTeX izpis, uporabimo:

Definiranje spremenljivk in numerični izračun

Spremenljivke definiramo takole:

Preverimo lahko tip:

sympy.core.symbol.Symbol

Opazimo, da je spremenljivka x sedaj Symbol iz paketa sympy.

Sedaj lahko naredimo preprost izračun:

Loading...

Funkcijo lahko tudi poimenujemo; tukaj je primer, kjer uporabimo funkcijo sinus in konstanto π\pi:

Loading...

Bralec se morebiti sprašuje, zakaj potrebujemo novo funkcijo sympy.sin(), saj imamo vendar že tisto iz paketa numpy! Razlog je v tem, da simbolni izračun potrebuje popolnoma drugačno obravnavo kakor numerični in zato je koda zadaj povsem drugačna.

Če želimo zapisati enačbo, torej da enačimo en izraz z drugim, to naredimo takole:

Loading...

Nedefinirane matematične funkcije zapišemo kot (dokumentacija):

Sedaj lahko, na primer, definiramo differencialno enačbo:

Loading...

Pri definiranju spremenljivk lahko dodajamo predpostavke:

True

Predpostavke se potem upoštevajo pri izračunu. V splošnem vemo, da (x2)≠x\sqrt{(x^2)}\ne x, če pa je xx pozitiven, pa velja (x2)=x\sqrt{(x^2)}= x in sympy glede na predpostavke izračuna pravilen rezultat:

Loading...

Z metodo assumptions0 pogledamo predpostavke objekta:

{'positive': True, 'extended_real': True, 'hermitian': True, 'extended_nonzero': True, 'infinite': False, 'nonzero': True, 'imaginary': False, 'commutative': True, 'nonpositive': False, 'zero': False, 'complex': True, 'negative': False, 'extended_nonnegative': True, 'finite': True, 'extended_positive': True, 'extended_negative': False, 'nonnegative': True, 'real': True, 'extended_nonpositive': False}

SymPy pozna tipe števil (dokumentacija):

  • Float realna števila (s plavajočo vejico, poljubne natančnosti),

  • Rational racionalna števila,

  • Integer cela števila,

  • kompleksna števila zapišemo z imaginarno enoto I (npr. 2 + 3*sym.I).

Ti tipi so pomembni, saj lahko vplivajo na način reševanja in na rešitev.

Racionalna števila

Zgoraj smo že definirali realna števila. Poglejmo na primeru sedaj racionalna števila:

Loading...

Nekateri izračuni:

Loading...
Loading...
Kompleksna števila

Imaginarno število se zapiše z I (to je drugače kot pri numpy, kjer je imaginarni del definiran z j):

Loading...
Loading...
Numerični izračun

Pri simbolnem izračunu najprej analitične izraze rešimo, poenostavimo itd., nato pa pogosto želimo tudi izračunati konkreten rezultat.

Poglejmo primer:

Loading...

Če želimo sedaj namesto xx uporabiti vrednost, npr 0.5, to naredimo z metodo subs() (dokumentacija):

Loading...

Zgoraj smo uporabili konstanto π\pi (dokumentacija); nekatere tipično uporabljene konstante so:

  • sympy.pi za število π\pi,

  • sympy.E za naravno število ee,

  • sympy.oo za neskončnost.

Kot smo videli zgoraj, subs() naredi zamenjavo in potem poenostavitve, ki so očitne; števila π\pi ni izračunal v obliki realnega števila. To moramo eksplicitno zahtevati z metodo:

kateri imata obe argument n (število števk).

Poglejmo primer:

Loading...

Podobno je z N:

Loading...

Mimogrede smo pokazali, da pod pogojem, da v izrazu nimamo števil s plavajočo vejico, lahko rezultat prikažemo poljubno natančno (dokumentacija).

V subs funkciji lahko uporabimo tudi slovar. Primer:

Loading...

ali seznam terk:

Loading...

Podobno ima metoda sympy.evalf() argument subs, ki sprejme slovar zamenjav, primer:

Loading...

Metoda sympy.subs pa lahko zamenja simbol (ali izraz) tudi z drugim izrazom:

Loading...

SymPy in NumPy

Pogosto sympy povežemo z numpy. Za primer si poglejmo, kako bi izraz:

Loading...

numerično učinkovito izračunali pri tisoč vrednostih xx.

Najprej uvozimo paket numpy:

Pripravimo numerično polje vrednosti:

array([0. , 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09])

Glede na zapisano zgoraj in predhodno znanje uporabimo izpeljevanje seznamov:

Opazimo, da je to dolgotrajno, zato izmerimo potreben čas:

377 ms ± 31.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Uporaba funkcije lambdify

Bistveno hitrejši način je uporaba pristopa lambdify, kjer se pripravi prevedena funkcija, optimirana za numerično izvajanje. Sintaksa funkcije sympy.lambdify() je (dokumentacija):

sympy.lambdify(simboli, funkcija, modules=None)

kjer so argumenti:

  • simboli simboli uporabljeni v funkcija, ki se zamenjajo z numeričnimi vrednostmi,

  • funkcija predstavlja sympy funkcijo,

  • modules predstavlja, za kateri paket je prevedena oblika pripravljena. Če je numpy nameščen, je privzeto za ta modul.

Primer uporabe:

Preverimo hitrost:

The slowest run took 5.98 times longer than the fastest. This could mean that an intermediate result is being cached.
53.6 µs ± 52 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Opazimo približno 10.000-kratno pohitritev!

Poglejmo še primer uporabe funkcije več spremenljivk:

array([ 9.8696044 , 28.77051002, 57.54795885, 96.20195089, 144.73248614, 203.1395646 , 271.42318627, 349.58335115, 437.62005924, 535.53331054])

Grafični prikaz

SymPy ima na matplotlib temelječ prikaz podatkov. Prikaz je sicer glede na matplotlib bolj omejen in ga uporabljamo za preproste prikaze. (dokumentacija).

Pogledali si bomo preproste primere, ki se navezujejo na funkcijo sympy.plotting.plot; najprej uvozimo funkcijo:

Sintaksa uporabe funkcije sympy.plotting.plot() (dokumentacija) je:

plot(izraz, razpon, **kwargs)

kjer so argumenti:

  • izraz je matematični izraz ali več izrazov,

  • razpon je razpon prikaza (privzeti razpon je (-10, 10)),

  • **kwargs so keyword arguments, torej slovar različnih možnosti.

Funkcija vrne instanco objekta sympy.Plot().

Minimalni primer ene funkcije:

<Figure size 640x480 with 1 Axes>
<sympy.plotting.plot.Plot at 0x17308af6510>

Opomba: zadnja vrstica opozori na rezultat v obliki instance Plot; izpis objekta <sympy.plotting.plot.Plot at 0x...> skrijemo z uporabo podpičja:

plot(x**2);

slika pa se vseeno prikaže.

Nekateri pogosti argumenti so:

  • show prikaže sliko (privzeto True),

  • line_color barva izrisa,

  • xscale in yscale način prikaza (možnosti: linear ali log),

  • xlim in ylim omejitev prikaza za osi (terka dveh (min, max) vrednosti).

Pripravimo dve sliki, kjer bo yy os logaritemska in bo razpon izrisa od 1 do 5:

Sedaj prvo sliko razširimo z drugo in prikažemo rezultat:

<Figure size 640x480 with 1 Axes>
Parametrični izris

Podobno uporabljamo funkcijo sympy.plotting.plot_parametric za parametrični izris (dokumentacija):

plot_parametric(izraz_x, izraz_y, range, **kwargs)

kjer sta nova argumenta:

  • izraz_x in izraz_y definicije lege koordinate xx in yy,

  • **kwargs je slovar možnosti.

Uvozimo funkcijo:

Prikažimo uporabo na primeru:

<Figure size 640x480 with 1 Axes>
Izris v prostoru

Funkcija sympy.plotting.plot3d (dokumentacija) za izris v prostoru ima sintakso:

plot3d(izraz, razpon_x, razpon_y, **kwargs)

kjer so argumenti:

  • izraz definicija površine,

  • razpon_x in razpon_y razpon koordinate x in y,

  • **kwargs slovar možnosti.

Uvozimo funkcijo:

Prikažimo uporabo na primeru:

<Figure size 640x480 with 1 Axes>

Za ostale prikaze glejte dokumentacijo.

Algebra

V tem poglavju si bomo pogledali nekatere osnove uporabe SymPy za algebrajske operacije.

Uporaba expand in factor

Definirajmo matematični izraz:

Loading...

in ga sedaj razčlenimo (angl. expand, glejte dokumentacijo):

Loading...

Če želimo pogledati koeficiente pred x, to naredimo z metodo coeff():

Loading...

Argumenti funkcije definirajo, kakšno razširitev želimo (dokumentacija). Če želimo npr. trigonometrično razširitev, potem uporabimo trig=True:

Loading...
Loading...

Obratna operacija od razčlenitve je razcepitev ali razstavljanje ali faktorizacija (angl. factor, dokumentacija):

Loading...

Če nas zanimajo posamezni členi, potem to naredimo s funkcijo sympy.factor_list:

Loading...
Poenostavljanje izrazov s simplify

Funkcija sympy.simplify() (dokumentacija) poskuša poenostaviti izraze v bolj preproste (npr. s krajšanjem spremenljivk).

Za posebne namene lahko poenostavimo tudi z:

Za več glejte dokumentacijo.

Primeri poenostavljanja:

Loading...
Loading...
Loading...

Uporaba apart in together

Funkciji uporabljamo za delo z ulomki:

Loading...

Razcep na parcialne ulomke (angl. partial fraction decomposition) izvedemo s funkcijo sympy.apart() (dokumentacija):

Loading...

in potem ponovno v obratni smeri s funkcijo sympy.together():

Loading...

V slednjem primeru pridemo do podobnega rezultata s sympy.simplify():

Loading...

Odvajanje

Odvajanje je načeloma relativno preprosta matematična operacija, ki jo izvedemo s funkcijo sympy.diff() (dokumentacija):

Pripravimo primer:

Loading...

Odvajajmo ga po xx:

Loading...

ali tudi

Loading...

Odvode višjega reda definiramo tako:

Loading...

ali (isti rezultat malo drugače):

Loading...

Odvod po več spremenljivkah d3fdx dy2\frac{d^3f}{dx\,dy^2} izvedemo takole:

Loading...

Integriranje

Funkcijo integrate lahko uporabimo za nedoločeno integriranje (dokumentacija):

integrate(f, x)

ali za določeno integriranje:

integrate(f, (x, a, b))

kjer so argumenti:

  • f funkcija, ki jo integriramo,

  • x spremenljivka, po kateri integriramo,

  • a in b meje integriranja.

Primer nedoločenega integriranja:

Loading...

Opazimo, da sympy pravilno upošteva možnost, da je y=0y=0.

Še primer določenega integriranja:

Loading...

Primer, ko so meje v neskončnosti (uporabimo konstanto za neskončnost sympy.oo):

Loading...

Vsota in produkt vrste

Vsoto vrste definiramo s pomočju funkcije sympy.Sum() (dokumentacija):

sympy.Sum(izraz, (spr, start, end))

kjer so argumenti:

  • izraz izraz, katerega seštevamo,

  • spr, start in end spremenljivka, ki narašča od start do end (end je vključen).

Primer vsote vrste:

Loading...

Šele ko uporabimo metodo doit(), se izračun izvede:

Loading...

Poglejmo še številčni rezultat:

Loading...

Produkt vrste definiramo podobno s funkcijo sympy.Product (dokumentacija):

sympy.Product(izraz, (spr, start, end))

kjer so argumenti:

  • izraz izraz, katerega množimo,

  • spr, start in end spremenljivka, ki narašča od start do end (end je vključen).

Primer:

Loading...
Loading...

Limitni račun

Limite računamo s pomočjo funkcije sympy.limit() (dokumentacija):

sympy.limit(f, x, x0)

kjer so argumenti:

  • f izraz, katerega limito iščemo,

  • x spremenljivka, ki limitira proti x0,

  • x0 limita.

Primer:

Loading...
Loading...

Za primer si poglejmo uporabo limite na definiciji odvoda:

dfdx=lim⁡h→0f(x+h,y)−f(x,y)h.\frac{\mathrm{d}f}{\mathrm{d}x} = \lim_{h\rightarrow 0}\frac{f(x+h,y)-f(x,y)}{h}.

Pripravimo funkcijo f in njen odvod:

Odvod funkcije je:

Loading...

Enak rezultat izračunamo tudi z uporabo limite:

Loading...

Taylorjeve vrste

Taylorjeve vrste izračunamo s pomočjo funkcijo sympy.series() (dokumentacija):

sympy.series(izraz, x=None, x0=0, n=6, dir='+')

kjer so argumenti:

  • izraz izraz, katerega vrsto določamo,

  • x neodvisna spremenljivka,

  • x0 vrednost, okoli katere določamo vrsto (privzeto 0),

  • n red vrste (privzeto 6),

  • dir smer razvoja vrste (+ ali -).

Primer:

Loading...

Če želimo definirati drugo izhodišče (x0=2) in z več členi (n=8), to izvedemo takole:

Loading...

Rezultat vključuje tudi red veljavnosti; na ta način lahko kontroliramo veljavnosti izvajanja (O\mathcal{O}).

Primer:

Loading...
Loading...

Izračuna s1 in s2 imata različna reda veljavnosti, posledično je produkt:

Loading...

natančen samo do reda O(x2)\mathcal{O}(x^2), kar sympy ustrezno obravnava:

Loading...

Podatek o stopnji veljavnosti lahko odstranimo:

Loading...

Linearna algebra

Matrike in vektorji

Matrike in vektorje definiramo s funkcijo Matrix. Če se pri numpy.array ni treba dosledno držati matematičnega zapisa vektorjev in matrik, je pri sympy to nujno.

Poglejmo si primer; najprej pripravimo spremenljivke:

Nato matriko in stolpični vektor:

Loading...
Loading...

Sedaj si poglejmo nekatere tipične operacije; najprej množenje matrike in vektorja:

Loading...

Nato skalarni produkt dveh vektorjev (paziti moramo na transponiranje enega od vektorjev):

Loading...

Determinanta in inverzna matrika:

Loading...
Loading...

Množenje in potenca matrike:

Loading...
Loading...

Reševanje enačb

Enačbe in sistem enačb rešujemo s funkcijo sympy.solve() (dokumentacija). Podprto je reševanje sledečih enačb:

  • polinomske enačbe,

  • transcendentne enačbe,

  • odsekovno definirane enačbe kot kombinacija zgornjih dveh tipov,

  • sistem linearnih in polinomskih enačb,

  • sistem enačb z neenakostmi.

Sintaksa je:

sympy.solve(f, *symbols, **flags)

kjer so argumenti:

  • f izraz ali seznam izrazov,

  • *symbols simbol ali seznam simbolov, katere želimo določiti,

  • **flags slovar možnosti.

Poglejmo primer:

Loading...
Loading...

Prikažimo rešitev (opazimo, da smo našli samo dve od neskončno rešitev):

<Figure size 640x480 with 1 Axes>

Kvadratna enačba:

Loading...

Sistem enačb:

Loading...

Za nelinearne sisteme pa lahko uporabimo tudi numerično reševanje s funkcijo sympy.nsolve() (dokumentacija):

sympy.nsolve(f, [args,] x0, modules=['mpmath'], **kwargs)

kjer so argumenti:

  • f enačba ali sistem enačb, ki ga rešujemo,

  • args spremenljivke (opcijsko),

  • x0 začetni približek (skalar ali vektor),

  • modules paket, ki se uporabi za izračun numerične vrednosti (enaka logika kot pri funkciji lambdify, privzet je paket mpmath),

  • **kwargs slovar opcij.

Poglejmo primer od zgoraj:

Loading...

Reševanje diferencialnih enačb

Nedefinirane funkcije

Preden si ogledamo diferencialne enačbe, moramo spoznati nedefinirane funkcije. Take funkcije definiramo sympy.Function dokumentacija.

Kot primer si poglejmo kako definiramo enačbo x¨(t)=g\ddot x(t)=g. Najprej definirajmo nedoločeno funkcijo:

Nato simbole:

In še enačbo:

Loading...
Diferencialne enačbe

Diferencialne enačbe in sisteme diferencialnih enačb rešujemo s funkcijo sympy.dsolve() (dokumentacija):

sympy.dsolve(eq, func=None, hint='default', simplify=True, 
             ics=None, xi=None, eta=None, x0=0, n=6, **kwargs)

kjer so izbrani argumenti:

  • eq differencialna enačba ali sistem diferencialnih enačb,

  • func rešitev, ki jo iščemo,

  • ics začetni in robni pogoji diferencialne enačbe.

Poglejmo si primer mase mm, ki drsi po površini s koeficientom trenja μ\mu; začetna hitrost je v0v_0, pomik x0=0x_0=0.

Definirajmo simbole:

Definirajmo diferencialno enačbo:

Loading...

Poglejmo lastnosti diferencialne enačbe:

Loading...
('factorable', 'nth_algebraic', 'nth_linear_constant_coeff_undetermined_coefficients', 'nth_linear_euler_eq_nonhomogeneous_undetermined_coefficients', 'nth_linear_constant_coeff_variation_of_parameters', 'nth_linear_euler_eq_nonhomogeneous_variation_of_parameters', 'nth_algebraic_Integral', 'nth_linear_constant_coeff_variation_of_parameters_Integral', 'nth_linear_euler_eq_nonhomogeneous_variation_of_parameters_Integral', '2nd_nonlinear_autonomous_conserved', '2nd_nonlinear_autonomous_conserved_Integral')

Rešimo jo:

Loading...

Desno stran enačbe prikličemo takole (rhs - right-hand side):

Loading...

Dodatno

sympy.mechanics

sympy ima vgrajeno podporo za klasično mehaniko (dokumentacija). Celovit tutorial je bil prikazan na znanstveni konferenci SciPy 2016.


Vprašanja za vaje


Osnove objektnega programiranja

Vprašanje 1: Pripravite razred KompleksnoStevilo, ki v konstruktorju dva podana argumenta shrani v atributa self.re in self.im. Ustvarite objekt pripravljenega razreda, izpišite re in im.

Vprašanje 2: Razred KompleksnoStevilo nadgradite z metodo konjugiran(), ki bo omogočalo kompleksno konjugacijo objektov.

Vprašanje 3: Razred iz prejšnje naloge nadgradite z metodo absolutno(), ki izračuna in vrne absolutno vrednost kompleksnega števila, ∣a+i b∣=a2+b2|a + \text{i}\,b| = \sqrt{a^2 + b^2}.

Vprašanje 4: Pripravite razred RealnoStevilo, ki deduje za razredom KompleksnoStevilo. V funkciji __init__ naj pokliče konstruktor glavnega razreda, realnemu delu priredi podano vrednost, imaginarnemu pa vedno vrednost 0.


SymPy

Vprašanje 5: Z uporabo paketa SymPy definirajte potrebne simbole in definirajte izraze za kinetično in potencialno energijo EkE_k, EpE_p ter Lagrangevo energijsko funkcijo LL sistema mase in vzmeti . Vse simbole definirajte kot pozitivna realna števila.

Ek=m x˙(t)22E_k = \frac{m~\dot{x}(t)^2}{2}
Ep=k x(t)22E_p = \frac{k~x(t)^2}{2}
L=Ek−EpL = E_k - E_p

Vprašanje 6: Z uporabo spodaj zapisane enačbe nastavite gibalno enačbo sistema mase in vzmeti.

ddt(∂L∂x˙(t))−∂L∂x(t)=0\frac{d}{dt}\Big(\frac{\partial L}{\partial \dot{x}(t)}\Big) - \frac{\partial L}{\partial x(t)} = 0

Vprašanje 7: Z uporabo SymPy funkcije rešite dobljeno diferencialno enačbo. Definirajte nov simbol w in v dobljeni rešitvi opravite zamenjavo: km=ω\sqrt{\frac{k}{m}} = \omega. Desno stran enačbe shranite v spremenljivko pomik (uporabite resitev.args).

Vprašanje 8: Določite vrednosti integracijskih konstant 'C1', 'C2' tako, da v dobljen izraz za pomik vstavite začetna pogoja za pomik in hitrost:

x (t=0)=1x~(t=0) = 1
v (t=0)=x˙ (t=0)=0v~(t=0) = \dot{x}~(t=0) = 0

Vprašanje 9: Dobljeni vrednosti konstant 'C1' in 'C2' vstavite v prej določen izraz pomik.

Dobljeno odvisnost x(t)x(t) izrišite na območju 0≤t≤20 \leq t \leq 2 s, pri tem pa parameter w nadomestite z vrednostjo 2π2\pi.

Vprašanje 10: Na 5 mest natančno določite čas t0, ko je obravnavan sistem prvič v ravnovesni legi (x(t0)=0)x(t_0) = 0).

Vprašanje 11: Na podlagi končnega izraza za pomike x(t)x(t) tvorite numpy funkcijo za izračun odmika mase od ravnovesne lege v odvisnosti od časa (ω=2π\omega = 2\pi).

Izrišite rezultat na območju 0≤t≤20 \leq t \leq 2 s z uporabo knjižnice matplotlib.