Algebra Symboliczna
Wykład II

Andrzej Odrzywolek
Instytut Fizyki, Zakład Teorii Względnosci i Astrofizyki
29.10.2008, środa, 13:15

Dane kontaktowe

dr Andrzej Odrzywołek
pokój 447, IV pietro
E-mail: odrzywolek@th.if.uj.edu.pl
Wykład: środy 13.15-15.00, sala 128
Cwiczenia: piątki 10.30-12.00
Konsultacje: środy 11-13, czwartki 12-13
WWW: http://ribes.if.uj.edu.pl/alsymb/

CAS: podstawowe trudnosci dla studenta

Terminologia angielska - wiedza po polsku np:
całka - integral, rotacja  - curl, pochodna - derivative, równanie - equation, liczna naturalna  - non-negative integer, ułamek łańcuchowy - continued fraction; MATHEMATICA prawdopodobnie nie zostanie przetłumaczona na język polski w najbliższym czasie (być może nigdy)

Używanie CAS wymaga wiedzy matematycznej, szczególnie formułowania problemów w języku matematyki

Obliczenia z użyciem CAS są w jawnym konflikcie z obecnym stylem nauczania, opartym o ręczne rachunki

Wiedza matematyczna potrzebna do skutecznego używania CAS jest nieco inna niż ta potrzebna aby zdobywać oceny 5.0 z przedmiotów matematycznych np już w szkole średniej powinny zostać wprowadzone:
1. Liczby zespolone  - w dziedzinie zespolonej więksość rachunków jest łatwiejsza do zalgorytmizowania. Równanie kwadratowe w domenie rzeczywistej ma zawsze 2 rozwiązania; w domenie rzeczywistej 0, 1 lub 2 rozwiązania.
2. Jednoznaczna notacja - np. (sin^2)x ; zapis ten powinien oznaczać Sin[Sin[x]] a rozumiemy go jako (Sin[x])2 
3. Równania różniczkowe zwyczajne, zagadnienie początkowe i brzegowe
4. Graficzne(w tym 3D, animacje, użycie kolorów itd. ) metody rozwiązywania równań i nierówności w miejsce manipulacji wyrażeniami i zapamiętywanych wzorów
5. Podstawy obliczeń numerycznych i arytmetyki komputerowej: liczby zmiennoprzecinkowe, całkowite i wymierne, podstawowe algorytmy rozwiazywania typowych problemów (bisekcja, Monte Carlo itd.)

U niektórych osób CAS wyzwala ukryte uzdolnienia matematyczne których rozwój był wcześniej hamowany tradycyjnym nauczaniem, np: fatalny charakter pisma odręcznego nieomalże uniemożliwia rozwiązanie nawet prostego zadania na kartce bez popełnienia trywialnych błędów; rachunki są nudne i czasem trudno się do nich zmusić nawet jeśli wiadomo że ostatecznie doprowadzą do wyniku; niektóre osoby mają problem z zapamiętaniem ogromnej ilości algorytmów niezbędnych do skutecznego liczenia na kartce czy tablicy

UWAGA: Notacja jest ściśle sformalizowana!

1. (sin^2)x

sin^2x

UWAGA: nie ma żadnego komunikatu o błędzie! MATHEMATICA zinterpretowała wyrażenie jako zmienną o nazwie ,,sin'' podniesioną do kwadratu i pomnożoną przez ,,x''. Prawidłowy zapis:

Sin[x]^2

Prosty sposób na sprawdzenie: wstawiamy np. Pi:

sin^2 x /. x->Pi

Sin[x]^2 /. x->Pi

2. (sin^(-1))x (f. odwrotna do Sin[x])

sin^-1x (* zły zapis *)

InverseFunction[Sin][x] (* poprawny zapis *)

3. Mnożenie, np. sin ωt

sinωt (*ŹLE!*)

sin ωt (*ŹLE!*)

Sin[ωt](*ŹLE!*)

Sin[ωt] /. {ω->1, t->Pi} (*ŹLE! MATHEMATICA uznała że ωt to jedno wyrażenie o nazwie ,,ωt''*)

Sin[ω t] (*DOBRZE! Spacja pomiędzy ,,ω'' i ,,t'' oznacza mnożenie*)

Sin[ω*t] (*DOBRZE! Znak mnożenia dla pewności warto wpisywać *)

4. Znak równości np. x^2=4, x=cos x

x^2=4(* ŹLE!*)

Solve[%,z]

x^2==4 (*DOBRZE! Podwójny znak równości używamy do tworzenia równań i wyrażeń logicznych. *)

Solve[%,x]

x = Cos[x]; (*FATALNIE!*)

Solve[%,x]

5. Stałe fundamentalne π, e, i, ∞

Sin[pi] (*ŹLE!*)

Sin[Pi]

e^iϕ //ComplexExpand(*ŹLE! podstawa logarytmów naturalnych to E, a jednostka urojona I*)

Exp[I ϕ] //ComplexExpand (*DOBRZE!*)

Limit[Exp[-x],x->infinity] (*ŹLE!*)

Limit[Exp[-x],x->Infinity] (*DOBRZE!*)

6. Zasady składniowe dot. funkcji: 
  a) argumenty funkcji podajemy w nawiasach kwadratowych np: Sin[x]
  b) funkcje wbudowane posiadają pełne nazwy zaczynające się z dużej litery np. Gamma[x]
  c) wyjatkami od reguły b) są funkcje elementarne m.in: Sin (sinus) , Cos (kosinus), Tan (tangens), Exp (f. wykładnicza), Log (logarytm naturalny)

log[a/b^3] //PowerExpand (*ŹLE! To nie jest logarytm naturalny, tylko niesprecyzowna funkcja o nazwie ,,log''*)

Log[a/b^3] //PowerExpand (*Dobrze!*)

Γ[6] (*ŹLE!*)

Gamma[6] (*DOBRZE!*)

7. Listy, macierze, tablice, zbiory tworzymy używając nawiasów ,,wąsatych'' { }; do pojedynczych elementów listy odwołujemy się PODWÓJNYMI nawiasami kwadratowymi [[ ]]. Indeksy elementów listy zaczynaja się OD ,,1'' !

lista={a,b,c,d,e,f}

lista[[2]]

lista[[0]]

lista[[-1]]

MATHEMATICA jako kalkulator

80*127

Nacisniecie Shift+Enter powoduje obliczenie wyrazenia.
Nacisniecie Enter powoduje przejscie do nastepnej linii.
Dokładnie na odwrót w MAPLE !

Kolejne polecenia i wyniki są numerowane przez Kernel MATHEMATICI. Pozycja w oknie interfejsu użytkownika nie ma znaczenia.

Możemy uruchomić Kernel osobno (MathKernel.exe - Windows, math - Linux)

Operatory %, %%, %%%, pozwalają na odwoływanie się do wyniku 1,2, 3 kroki wstecz itd. Operator %n odwołuje się do wyniku uzyskanego w n-tym kroku.

%

%%

%1

Operator ? wyświetla skróconą pomoc, ?? rozszerzoną pomoc.

??

?Sin

??Sin

?%

Podstawowe konstrukcje składniowe

, , Zakres zmienności'': {zmienna, start, koniec, krok}

Liczby całkowite od 0 do 10:

Table[n,{n,0,10}]

Całka od 0 do π

Integrate[Sin[x],{x,0,Pi}]

Wykres funkcji w przedziale (-5,5):

Plot[Sinh[x],{x,-5,5}]

Obliczenie wartosci sinusa od 0 do 2π co π/6:

Table[Sin[α],{α,0,2 Pi,Pi/6}]

Narysowanie wykresu f. sinus w przedziale od {-T,T} przy czym początkowa wartość T równa się 2 π

Manipulate[Plot[Sin[t],{t,-T,T}],{{T,2 Pi},0.1,50,0.1}]

Wykres polilogarytmu dla n = 1, 3, 5, 7

Manipulate[Plot[PolyLog[n,x],{x,-10,10}],{n,{1,3,5,7}}]

Plot[Table[PolyLog[n,x],{n,{1,3,5,7}}],{x,-10,10}]

Podstawowe konstrukcje składniowe

Reguły transformacyjne i operator ,,zamień wszystko'' (ReplaceAll)

Reguła transformacyjna ,,x zamieniamy na y'':

regula1 = x->y

x^2+4 /. x->y

x^2+4 /. regula1

x+y /. Plus->Power

FullForm[x+y]

Sin[α] /. Sin->Exp

Przykład : Wydobywanie wartości zwracanej przez FindRoot

FindRoot[x^x==Pi,{x,1}]

x /. %

x/. FindRoot[x^x==Pi,{x,1}]

Uwagi na temat automatyzacji obliczeń w MATHEMATICE

Do wykonania prostych zadań znajomość składni i języka programowania MATHEMATICI nie jest niezbędna!

Nie zapominajmy o możliwościach jakie daje GUI. Jeżeli mamy do rozwiązania jedno równanie,  jeden układ równań lub jedną całkę do wyliczenia szkoda tracić czas na przekształecenie wyniku z np. reguły transformacyjnej na listę czy eksport do pliku. Można w tym celu posłużyć się kursorem myszy i np. kombinacją Ctrl+C Ctrl+V. Nie ma w tym nic złego lub niepoprawnego! Co więcej, często jest to najefektywniejsze czasowo rozwiązanie, szczególnie dla osób używających CAS sporadycznie.

Przykład: Oblicz sumę kwadratów rozwiązań równania:

Solve[3 x^3+x+1==0,x]

(x/. Solve[3 x^3+x+1==0,x]) //#^2& //Tr //Simplify

Czas metodą Ctrl+C Ctrl+V około 30 sekund. Napisanie tego w jednej linijce, wliczając przeglądanie manuala i nieudane próby około kilka minut.

Jeżeli mamy do rozwiązania serię podobnych problemów, w pewnym momencie będziemy zmuszeni do użycia zaawansowanej składni i programowania

Trudno wyznaczyć granicę. Dla osoby która opanowała składnię perfekt nawet dla 1 rozwiązania szybsze jest wpisanie komend. Czasem przekopiowanie ręczne kilkunastu czy kilkudziesięciu wyników jest optymalne, zwłaszcza pod naciskiem upływającego czasu (np. kolokwium zaliczneiowe). Obliczenie 1000 całek na pewno wymaga programowania.

Możliwość rozwiązywania w krótkim czasie setek klasycznych problemów analizy i algebry w połączeniu z szybkimi metodami numerycznymi otwiera nowy rozdział nauki i inżynierii. Wszystko co można policzyć ,,na kartce'' zrobiono w XIX wieku i zastosowano w XX. Pominięto tylko problemy zbytnio złożone rachunkowo.

Arytmetyka dowolnej precyzji

UWAGA: istotna przewaga MATHEMATICI nad innymi rozwiązaniami pozwlającymi na obliczenia dowolnej precyzji tkwi w możliwości używania każdej funkcji i procedury np. funkcji specjalnych Gamma, FresnelS, obliczeniowych FindRoot, NIntegrate, NDSolve itp.

Przykład: obliczenie pierwiastka kwadratowego

Sqrt[2]

Każdy wynik symboliczny posiada nieskończenie dużą precyzję, dlatego jest bardzo cenny:

Precision[Sqrt[2]]

Precision[Pi]

Precision[Log[2]]

(1/2)^10000

N[%]

Precision[%]

(1/2.0)^10000

Precision[%]

(1/2.0)^10000.0

Precision[%]

Wprowadzenie liczby numerycznej 2 zawierającej 100 zer po przecinku:

Sqrt[2.0``100] //Precision

N[Sqrt[2]]

Pierwiastek z 2 obliczony z dokładnością 100 miejsc po przecinku:

N[Sqrt[2],100]//Precision

Utrata precyzji numerycznej:

Nest[Tan,2.0``100,100]

Precision[%]

Precyzja procesora (rachunek numeryczny ,,hardware'owy'')

$MachinePrecision

Rozwiązanie o dowolnej precyzji na ogół nie jest możliwe, jeżeli dane wejściowe mają precyzję niższą niż  żądamy tego od wyniku:

wynik1= x/. FindRoot[x^2==4.15,{x,1},PrecisionGoal->100,WorkingPrecision->100]

Rozwiązanie to podanie liczby z wymaganą dokładnością:

wynik2 = x/. FindRoot[x^2==4.15``100,{x,1},PrecisionGoal->100,WorkingPrecision->100]

Lub przekształcenie na liczbę wymierną:

4.15 //Rationalize

wynik3 =  x/. FindRoot[x^2==83/20,{x,1},PrecisionGoal->100,WorkingPrecision->100]

Na koniec rozwiązanie analityczne:

wynik4 =N[x /.(Reduce[x^2==83/20&&x>0,x] //ToRules),100]

Porównanie 4 wyników:

TableForm[{wynik1,wynik2,wynik3,wynik4}]

Przykład z manuala:

N[(Sqrt[2])+(Sqrt[3])-(Sqrt[5+2 (Sqrt[6])])]

N[(Sqrt[2])+(Sqrt[3])-(Sqrt[5+2 (Sqrt[6])]),100]

Simplify[(Sqrt[2])+(Sqrt[3])-(Sqrt[5+2 (Sqrt[6])])]

FullSimplify[(Sqrt[2])+(Sqrt[3])-(Sqrt[5+2 (Sqrt[6])])]

Operator nakazujacy zastosowanie polecenia do wyrazenia obliczonego przed nim (Postfix)

Przykład: ile wynosi wartosc numeryczna wyrazenia (e^π)-(π^e) lub (i^i) ?

E^Pi-Pi^E // N

I^I //N //Chop

I^I //ComplexExpand

Kilka przykładów:

(x^2-x-1)^7 //Expand

% //Simplify

Poniższe komendy robią to samo:

-1 //Sqrt //N

N[Sqrt[-1]]

Operator // używamy zwykle w pracy interaktywnej, gdy np. w ostatniej chwili przypominamy sobie że potrzebujemy wyrażenia w postaci numerycznej a nie symbolicznej. Dodajemy wtedy na końcu linijki  //N

Zmienne i wyrazenia

Dowolne wyrazenie (wielomian, funkcje, równanie, wykres,
macierz) mozna przypisac do pewnej zmiennej operatorem =

f=Sin[Sin[x]]

w=(x+1)^5

rownanie=x^2==-1

napis="algebra symboliczna"

n=100

t=12.7

Znak równosci (w równaniach) to podwójne == ! Uzycie w tym
momencie operatora przypisania = to najczesciej popełniany bład.

Zmienne wbudowane i już przypisane kolorowane są na czarno, pozostałe na niebiesko

Funkcje

Najprostsza definicja funkcji f:x->(2^x)

f[x_]:=2^x

f[2]

f[2.0]

f[a]

Składniki definicji funckji: f - nazwa, x - argument, _ - typ argumentu (pusty w tym przypadku), :=  - operator ,,oblicz dopiero po wywołaniu funkcji f''

Czysta funkcja (pure function) bez argumentu

Sin' (* pochodna sinusa *)

g=2^#& (* definicja funcji  g:x->(2^x) w postaci czystej funkcji *)

g[2]

Jak w wyrażeniu poniżej zamienić sinus na inną funkcję?

s=Sum[Sin[x]^n,{n,1,10}]

Bardzo prosto można to zrobić jeżeli funkcja ma nazwę:

s /. Sin->Log

Ale jak podstawić funkcję y=1/x ?

Sposób 1: zdefiniowanie funkcji wykonujacej operację 1/x

odwrotnosc[x_]:=1/x

s/. Sin -> odwrotnosc

Sposób 2 : użycie , , czystej funkcji''

s /. Sin ->(1/#&)

Funkcja wielu zmiennych

u[x_,y_,z_]:=Log[x^y^z]

u[1,a,a]

u[1,2,3]

u[2.0,2.0,2.0]

Operator podkreślenia ?, /; (porównywanie ze wzorcem)

f[t_]:=N[t]

g[t_?NumericQ]:=N[t]

h[t_?NumberQ]:=N[t]

f[Pi]

g[Pi]

h[Pi]

f[a]

g[a]

h[a]

i[i_?IntegerQ]:=i!

i[6]

i[6.0]

i[1.5]

i[-1]

Podobne  notacje

f1[n_?IntegerQ]:=n! (* n całkowite *)

f2[n_/;IntegerQ[n]&&n>0]:=n! (* n całkowite i większe od zera *)

f3[n_?IntegerQ]:=n! /;n>0 (* n całkowite i większe od zera *)

Listy

Lista może składać się z dowolnych elementów (w tym innych list) i wygląda następująco:

lista={x,1,Pi,Sin[x],{0,1},"abc",x+y}

Podstawowe operacje na elementach listy:

lista[[1]] (* pierwszy element listy *)

First[lista]  (* pierwszy element listy, inna notacja *)

lista[[4]] (* czwarty element listy *)

lista[[-1]] (* ostatni, czyli pierwszy od końca element listy *)

lista[[0]] (* elementy numerujemy od 1, zero wskazuje na nagłówek, patrz niżej *)

lista //FullForm

Dimensions[lista] (* rozmiar listy *)

Select[lista, #>0&] (* wybierz z listy elementy wieksze od zera, notacja za pomocą czystej funkcji*)

Select[lista, IntegerQ] (* wybierz z listy liczby całkowite *)

Select[lista, StringQ] (* wybierz z listy elementy tekstowe *)

,,Spłaszczenie listy''

lista //Flatten

Podstawy rysowania funkcji

Wykres funkcji danej w postaci jawnej:

Plot[Exp[x],{x,-3,3}]

Krzywa płaska (2 D) w postaci parametrycznej :

ParametricPlot[{3 Sin[t], 2 Cos[t]},{t,0, 2 Pi}]

Krzywa płaska w postaci uwikłanej:

ContourPlot[x^2/4+y^2/9==1,{x,-5,5},{y,-5,5}]

Kilka funkcji równocześnie na osobnych rysunkach:

Table[Plot[Sin[ω t],{t,-10,10},PlotLabel->"ω="<>ToString[ω]],{ω,1,10}]

Prosta animacja (opcja PlotRange jest konieczna w przypadku animacji):

Animate[Plot[Sin[ω t]/ω,{t,-10,10},PlotLabel->"ω="<>ToString[ω],PlotRange->{{-10,10},{-1,1}}],{ω,1,4,0.01}]

Kilka wykresów równocześnie:

Plot[Table[(Sin[x])^n,{n,2,16,2}],{x,-2 π, 2π}]

Table[Plot[(Sin[x])^n,{x,-2 π, 2π}],{n,2,16,2}]

Show[%]

Wykresy z tooltipami (najedź kursorem myszy na wykres! ):

ContourPlot[Evaluate[Table[x^n+y^n==3,{n,2,16,1}]],{x,-2, 2},{y,-2,2}]

Wykres funkcji danej w postaci tabeli liczb:

punkty=Table[{x,x^2 Exp[-x]Sin[x]},{x,0,10,0.5}]

ListPlot[punkty]

ListPlot[punkty, Joined->True]

ListPlot[punkty, Joined->True, InterpolationOrder->0]

ListPlot[punkty, Joined->True, InterpolationOrder->1]

ListPlot[punkty, Joined->True, InterpolationOrder->3]

Table[Tooltip[{Re[Exp[I ϕ]],Im[Exp[I ϕ]]},Exp[I ϕ]],{ϕ,0, 2 Pi,Pi/6}]

ListPlot[%,AspectRatio->1]

Najczesciej wykonywane symbolicznie zadania

Całka oznaczona, np: (∫_0^π)Sin[x]dx

Integrate[Sin[x],{x,0,Pi}]

Rozwiązanie równania, np: (x^4)=4

Solve[x^4==4,x]

Reduce[x^4==4,x]

FindInstance[x^4==4,x] (* czy równanie ma jakiekolwiek rozwiązanie *)

Upraszczanie/przekształcanie wyrazeń

TrigExpand[Sin[4 x]]

ExpToTrig[Exp[x]]

TrigToExp[Cos[x]]

PowerExpand[Log[(x /y)^m]]

Simplify[a^2+ 2a b + b^2]

Factor[x^4+x^2 + 1]

Simplify[Gamma[n+1],Assumptions->n∈Integers&&n>0]

FullSimplify[Gamma[n+1],Assumptions->n∈Integers&&n>0]

Expand[(1+x)^6]

Pochodna funkcji

D[Tan[x],x] (* pochodna Tan[x] po x *)

D[Sin[a x],{x,25}] (* 25-ta pochodna po x funkcji Sin[a x] *)

D[Exp[x^2+y^2],x,y] (* druga pochodna cząstkowa wyrażenia *)

Integrate[f'[x],{x,x1,x2}] (* podstawowy wzór rachunku całkowego *)

Granice

Limit[Sin[x]/x,x->0]

Limit[Exp[-1/x],x->0]

Limit[FresnelS[x],x->Infinity]

Czy MATHEMATICA obliczyła poniższe granice czy nie?

Limit[(FresnelS[x]-1/2)/Exp[-x],x->Infinity]

Limit[(FresnelS[x]-1/2)/Log[1+1/x],x->Infinity]

Najczęściej wykonywane numerycznie zadania

Całka oznaczona np: (∫_0^π)Sin[x]dx

NIntegrate[Sin[x],{x,0,Pi}]

Manipulate[NIntegrate[If[x^n+y^n<1,1,0],{x,0,Infinity},{y,0,Infinity}],{n,2,10,1}]

Numeryczne rozwiązanie równania

FindRoot[Exp[x]==Sin[x],{x,1}] (* punkt startowy x=-1 *)

Rzeczywiste rozwiazania układu równań x^2 + y^2 == 4, Log[x] + Log[y] == -1:

ContourPlot[{x^2+y^2==4, Log[x]+Log[y]==-1},{x,0,3},{y,0,3}]

Z wykresu odczytujemy wartości startowe:

FindRoot[{x^2+y^2==4, Log[x]+Log[y]==-1},{{x,2},{y,0.2}}]

FindRoot[{x^2+y^2==4, Log[x]+Log[y]==-1},{{x,0.2},{y,2}}]

Interpolacja wyników w celu zdefiniowania własnej funkcji:

sin={{0,0},{Pi/6,1/2},{Pi/4,Sqrt[2]/2},{Pi/3,Sqrt[3]/2},{Pi/2,1}}//Interpolation

Plot[{sin[x],Sin[x]},{x,0,Pi/2}]

Powody implementacji i używania metod numerycznych w CAS

Obliczenia numeryczne czesto prowadza do wyniku szybciej, np. obliczenie całki oznaczonej z funkcji o „banalnym’' przebiegu

Wiekszosc problemów nie posiada rozwiazania analitycznego

Zwykle ostatecznym celem jest uzyskanie wyniku liczbowego

Stosuje się algorytmy o ustabilizowanej reputacji. Algorytmy „niepewne” nie sa używane.

Dysponujemy metodami graficznymi  pozwalajacymi na relatywnie łatwe testowanie wyników pod katem poprawnosci

Gigantyczna i ciagle rosnaca moc obliczeniowa komputerów pozwala na obliczenia numeryczne w czasie rzeczywistym, w sposób nieomal nieodróżnialny od obliczeń analitycznych

Obliczenia symboliczne vs numeryczne

Pi1=3.141592653589793

Pi2 = 3141592653589793/10^15

3.141592653589793`

BaseForm[0.1,2]

0.00011001100110011001101

Nest[10 #^2&,0.1,100]

Nest[10 #^2&,0.1``50,100]

Nest[10 #^2&,1/10,100]