3. Symbolické výrazy a práce s nimi#
SageMath umožňuje uživateli pracovat i se symbolickými výrazy, tedy s digitálními analogy výrazů s kterými pracujeme i na papíře. Této funkčnosti samozřejmě intenzivně využijeme při práci s výrazy a rovnicemi obsahujícími neznámou či proměnnou, při řešení rovnic, nebo počítání limit a derivací. Touto problematikou se podrobně zabývá kapitola Symbolic calculus v dokumentaci.
3.1 Symbolické proměnné a výrazy#
Nejprve je přirozeně potřeba vytvořit proměnnou, s kterou budeme pracovat.
K tomu slouží funkce var
.
var('x')
x
Bez této inkantace bychom dostali chybu (na rozdíl např. od prostředí Mathematica, kde vše je symbolický výraz).
Máme na mysly takovouto chybu (proměnná y
nyní neexistuje).
y
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In [2], line 1
----> 1 y
NameError: name 'y' is not defined
Od tohoto okamžiku můžeme s x
pracovat jako s proměnnou a vytvářet různorodé výrazy (expression).
expr = x^2 + sin(x) / (x^2 + 1)
show(expr)
Ale třeba i rovnice obsahující tuto proměnnou.
show(exp(x) == 3)
Nebo nerovnice obsahující tuto proměnnou.
show((x - 1)*(x + 2) > 0)
K vypisování výrazů je vhodné používat funkci show
, která nám výraz zobrazí pomocí LaTeXu. Bez ní bychom dostali pouze textovou reprezentaci, která v komplikovanějších případech nemusí být příliš čitelná.
Srovnejte
1 / x + exp(x^2)
1/x + e^(x^2)
s
show(1 / x + exp(x^2))
Se symbolickými objekty lze dále pracovat mnoha způsoby, podrobněji se na toto téma podíváme v další sekci.
Nyní ještě poznamenejme, že pod kapotou jde o instance třídy Expression
.
print(type(x + 1))
print(type(x + 1 == 1))
print(type(x + 1 > 2))
<class 'sage.symbolic.expression.Expression'>
<class 'sage.symbolic.expression.Expression'>
<class 'sage.symbolic.expression.Expression'>
Python je objektový jazyk, jakého typu je takovýto symbolický výraz? Pomocí automatického doplňování sytaxe zkuste prozkoumat jeho vlastnosti (stiskněte TAB za tečkou).
# expr.
Nejjednodušším úkonem se symbolickým výrazem je pravděpodobně dosazování za proměnnou. Symbolický výraz samozřejmě může záviset i na více proměnných. Dosazovat ("substituovat") lze několika různými způsoby.
# pomocí rovnosti
show(expr(x = pi / 2))
# pomocí slovníku
show(expr({x: pi / 2}))
Poznámka: Vedle symbolických proměnných můžeme vytvářet i symbolické funkce, použijeme k tomu funkci function
. Například nechť f
je jistá funkce.
function('f')
f
type(f)
<class 'sage.symbolic.function_factory.function_factory.<locals>.NewSymbolicFunction'>
Takovouto funkci pak můžeme také využít v symbolických výrazech:
show(f(x + 1))
3.2 Jednoduché operace s výrazy#
Se symbolickými výrazy můžeme provádět základní algebraické operace, u nichž může dojít k jistému elementárnímu zjednodušení:
# součet
show(x + x)
# násobek
show(x * x)
# dělení
show(x / (x + 1))
# mocnění (a odčítání)
show(x ^ (2 - x))
Bez problémů ale můžeme používat i známé matematické funkce:
show(sin(x + 2))
show(tan(x^2))
show(exp(x) * log(x))
Ale například i:
show(floor(x)) # dolní celá část
show(factorial(x)) # faktoriál
Úplný seznam by byl velmi dlouhý, případně experimentujte s TAB nebo prohledejte dokumentaci.
Dejte si pozor na klasický neduh počítačových algebraických systémů, následující odpověď není v pořádku. Víte proč?
x / x
1
V tomto případě je tato úprava vypadá nevinně, ale ve složitějších výpočtech nás může nepříjemně překvapit (navíc nikdy nevíte, kde jinde ještě dojde k nějaké nelegální úpravě).
3.3 Zjednodušování a složitější operace s výrazy#
SageMath, podobně jako Mathematica, umožňuje s výrazy provádět celou řadu algebraických úprav a využívat vlastnosti funkcí ve výrazu se vyskytujících. Můžeme ho proto používat na "zjednodušování výrazů". Pozor, úloha "zjednodušení" není dobře definována. Různé tvary jednoho výrazu mohou být "jednoduché" v závislosti na úhlu pohledu.
Vyvořme si jednoduchý výraz pro testování.
expr = (x + 4)^5
show(expr)
Proveďme roznásobení tohoto algebraického výrazu pomocí metody expand
.
expr = expr.expand()
show(expr)
Naopak můžeme tento polynom upravit zpět na součin kořenových činitelů pomocí metody factor
, která se snaží objekt rozložit na součin více objektů.
expr = expr.factor()
show(expr)
Analogicky se chová i pro celá čísla.
show(12.factor())
Stejným způsobem lze pracovat třeba i s trigonometrickými funkcemi.
expr = sin(4*x)
show(expr)
Pro rozepsání výrazu ovšem nyní musíme využít metodu trig_expand
.
Následující úprava je v podstatě vzorec pro sinus čtyřnásobného úhlu.
expr = expr.trig_expand()
show(expr)
V opačnem směru pak zabere metoda trig_reduce
.
expr = expr.trig_reduce()
show(expr)
Dále máme k dispozici výstižně pojmenované metody simplify
a simplify_full
, které se snaží na zadaný výraz aplikovat různé úpravy a výraz tak "zjednodušit".
Podívejte se i na další podobně znějící metody (TAB).
Například:
expr = (1 - x) * (1 + x + x^2)
show(expr)
show(expr.simplify())
show(expr.simplify_full())
Tip: Doporučuji tyto metody využít při kontrole správnosti vašich úprav: zjednodušte rozdíl původního a vašeho výrazu, chcete dostat nulu (velmi zjednodušený výraz).
expr1 = cos(x)^2 - sin(x)^2
expr2 = cos(2 * x)
(expr1 - expr2).simplify_full()
0
3.4 Řešení (nelineárních) rovnic#
Pro řešení lineárních rovnic, což je jednoduchá úloha, má SageMath k dispozici lineárně algebraické nástroje, do kterých zde nebudeme zabíhat. Při studiu BI-MA1 nás spíše trápí různé nelineární rovnice. V tom případě je hledání jejich řešení výrazně komplikovanější úloha. Analytické, exaktní, řešení existuje typicky jen v speciálních případech. V drtivé většině případů, které se ovšem typicky nevyskytují ve školních příkladech, je nutné využít numerických metod.
Ukažme si nejprve, jak v SageMath vyřešit jednoduchou kvadratickou rovnici.
Využijeme funkci solve
, které předáme rovnici (případně list rovnic) a neznámou (případně list neznámých):
solve(2*x^2 + 3*x - 2 == 0, x)
[x == -2, x == (1/2)]
V příapdě úspěchu odpověď dostáváme ve formě listu s vyjádřením proměnných. To často není úplně praktické, můžeme požádat i o slovník (s kterým se pak i lépe pracuje, nebo dosazuje).
solve(2*x^2 + 3*x - 2 == 0, x, solution_dict=True)
[{x: -2}, {x: 1/2}]
Vidíme, že rovnice má dvě reálná řešení.
SageMath by si měl poradit i s jednoduchými nerovnostmi:
solve(2*x^2 + 3*x - 2 <= 0, x)
[[x >= -2, x <= (1/2)]]
nebo
solve(x * exp(x) > 0, x)
[[0 < x]]
Pokud si SageMath s úlohou neporadí, tak nám dá tautologickou odpověď:
solve(x * exp(x) > 1, x)
[[x*e^x - 1 > 0]]
Tyto dva příklady ukazují na poměrně typickou situaci: drobounká změna zadání z jednoduchého příkladu dělá neřešitelný problém (našimi aktuálními metodami).