Rozwiązywanie równań z jedną niewiadomą

Najprostsze przykłady i wyjaśnienie użytej notacji oraz symboli.

Przykład 0: Rozwiąż w dziedzinie liczb rzeczywistych równanie, w notacji ,,tablicowej’’ podane jako:

 2 x + 3 = 4

Rozwiązanie tradycyjne:

Obustronnie odejmujemy 3 (równoważna czynność, przenosimy 3 z lewej na prawą stronę zmieniając znak)

2 x = 4 - 3
2 x = 1

Obustronnie dzielimy przez 2

x = 1/2

Dysponując komputerem zawsze należy rozpocząć rozwiązywanie zadania od metod graficznych, czyli rysowania wykresów wyrażeń pojawiających się jako składowe równania.Dotyczy to przede wszystkim równań, które poza niewiadomą (w tym wypadku x) nie zawierają żadnych innych symboli, za wyjątkiem liczb (np : 2, 3, 1/2).Dotyczy to także powszechnie znanych symboli np.liczby π).Typowo, równanie, składa się z dwóch stron przedzielonych znakiem równości (logicznej).Określamy je zwykle jako lewa i prawa, odpowiednio do tego, z której strony znaku równości się znajdują.Z języka angielskiego pochodzą skróty : 

	LHS (Left Hand Side, , , po stronie lewej dłoni’’) - lewa strona równania
            RHS (Right Hand Side, , , po prawej stronie dłoni’’) - prawa strona równania

Stwierdzenie : rozwiązaniem graficznym równania, jest punkt (lub zbiór takich punktów) w których wykresy lewej i prawej strony równania przecinają się.

	UWAGA: bardzo często prawa strona równania to ZERO.W takim wypadku rozwiązaniem równania jest przecięcie z osią Ox.Programy komputerowe nie zawsze rysują tę oś! Dlatego warto dla pewności narysować wykres funkcji równej zero; jest to taka sama funkcja jak wszystkie inne. Jej wykresem jest linia pozioma.W naszym, , zerowym’’ przykładzie lewa strona to 2 x + 3, natomiast prawa strona to 4.
       
       UWAGA : symbole 2 x + 3 oznaczają ,,2 razy x dodać trzy’’.W notacji ,,tablicowej’’ symbol mnożenia na ogół pomija się.Należy przy tym przestrzegać niepisanej reguły, która mówi, że w wyrażeniu matematycznym liczby całkowite powinny być na początku wyrażenia.

       Poprawnie :	 2 x + 3,  3+ 2 x

	Źle : 	x 2 + 3, 3 + x 2

Wpisane wyrażenia obliczamy klawiszami Shift + Enter !

1+1 (* Warto ten rachunek wykonać zaraz po uruchomieniu programu, aby sprawdzić czy jądro (Kernel) działa *)

2x+3  (* DOBRZE: Poprawna kolejność, ale nie wstawiono spacji oznaczającej mnożenie *)

x2+3 (* ŹLE! Błędna kolejność, wskutek czego Mathematica zinterpretowała wyrażenie x2 jako symbol o takiej właśnie nazwie. *)

x 2 +3 (* DOBRZE, ale proszę unikać takiej notacji. Spacja została zamieniona na znak mnożenia. Bardzo duże ryzyko pomyłki przy wpisywaniu. *)

2*x+3 (* DOBRZE. Sposób zalecany dla początkujących użytkowników. Znak mnożenia wpisany z klawiatury (Shift+8, ,,gwiazdka''), dzięki czemu nie popełnimy pomyłki. *)

3+x*2 (* DOBRZE. Jeżeli z jakiegoś powodu musimy użyć takiej kolejności, to powinniśmy jawnie wpisać znak mnożenia *)

Komentarz:

Każda wpisana linijka jest numerowana

Polecenia są numerowane przez jądro (Kernel)

Kolejność nie zależy od pozycji w notatniku! Przejście kilka linni do góry nie powoduje cofnięcia licznika, co łatwo zauważyć naciskając Shitf+Enter dwukrotnie w tej samej linijce.

można odwołać się do poprzedniego wyniku symbolem (poleceniem) 	%

dwa polecenia wstecz: %%; 
trzy wstecz %%%, 
itd.

do wyniku o numerze n można odwołać się za pomocą %n ; np: %12

UWAGA: to nie jest odwołanie się n-kroków wstecz !

Pierwszym poleceniem z którym się zapoznamy to Plot, czyli instrukcja rysująca wykresy wyrażeń matematycznych. Jej struktura jest typowa dla większości przydatnych studentom  funkcji. Narysujemy na początek wykres wyrażenia 2x+3.

Plot[2*x+3, {x,-4,4}]

każde wbudowane polecenie programu Mathematica rozpoczyna się od wielkiej litery ( Plot a nie np: plot )

(* ŹLE! *)
plot[2x+3, {X,-4,4}]

Mathematica rozróżnia wielkie i małe litery ( x to nie to samo co X )

(* ŹLE ! *)
Plot[2x+3, {X,-4,4}]

nawiasy opisujące argumenty poleceń są obowiązkowe i KWADRATOWE ( Sin[x] a nie Sin(x) lub co gorsza ,,sin x’’ )

nawiasy wąsate {} służą do definiowania zbiorów np: {a, 1, 1/3} oraz zakresów (ang. Range), np: ,,x zmienia się od -4 do 4’’
zapiszemy jako {x, -4, 4}

(* ŹLE ! *)
plot{2*x+3, {x,-4,4}}

w wielu przypadkach Mathematica ostrzega nas o błędnej składni wyświetlając komunikaty o błędach

Plot(2x+3,{x,-4,4})

polecenie można automatycznie dokończyć kombinacją klawiszy Ctrl + Shift + K

Plot[f,{x,(Subscript[x, min]),(Subscript[x, max])}]

Spróbujemy teraz rozwiązać graficznie równanie ,,2 x + 3 = 4''. Rysujemy w tym celu dwa wyrażenia na jednym wykresie:

Plot[{2x+3, 4},{x,-4,4}]

Z wykresu odczytujemy łatwo, że rozwiązaniem jest x ≈ 0.5. Metody graficzne nie pozwalają na ustalenie czy jest to dokładnie 1/2.

Zyskujemy jednak kilka cennych informacji:

widzimy wykresy, co oznacza, że rozumiemy treść zadania i potrafimy poprawnie przepisać ją w Mathematice

rozwiązanie jest prawdopodobnie tylko jedno

wykresami są linie proste, lub niemal proste (nie są to skomplikowane krzywe)

wykres pojawił się natychmiast, co oznacza, że wyrażenia są łatwe do obliczenia

rozwiązanie jest w pobliżu x=0.5

Rozwiązanie łatwo uściślić, rysując wykres ,,zoomowany’’ na x=0.5, np: w przedziałe 0<x<1 :

Plot[{2x+3,4},{x,0,1}]

Powtarzając tę czynność, możemy dowolnie dokładnie wyznaczyć rozwiązanie :

Plot[{2x+3,4},{x,0.4,0.6}]

Plot[{2x+3,4},{x,0.49,0.51}]

Uwagi na temat struktury polecenia Plot.

Polecenie Plot posiada dwa argumenty oddzielone przecinkiem, w naszym przykładzie są to :

  2x+3		oraz		{x,-4,4}	.
  
  Warto zwrócić uwagę na fakt, iż rysując dwa wyrażenia równocześnie, Plot nadal ma dwa argumenty:
  
  {2x+3, 4}	oraz		{x,-4,4}	.
  
  Różnica jest taka, że w drugim przypadku argumentem jest lista wyrażeń. Jest to ogólna metoda mnemotechniczna, pozwalająca na przewidzenie struktury polecenia dla problemu złożonego, jeżeli znana jest składnia dla pojedynczego. 
  Przykłady:
  
  rysowanie jednej funkcji	 <-> 	rysowanie wielu funkcji
  
  rozwiązanie równania z jedną niewiadomą 	<-> 	rozwiązanie układu równań
  
  itp.

Hold[Plot[2x+3,{x,-4,4}]]//TreeForm

Oprócz metod graficznych mamy dostępne w Mathematice metody numeryczne oraz symboliczne. Ich zastosowanie wymaga umiejętności zapisania równania. W większości istniejących języków programowania, i Mathematica nie jest tu wyjątkiem, istnieją dwa osobne symbole na oznaczenie równości matematycznej  ( Equal, podwojony symbol == )  oraz instrukcji przypisania ( Set , =). 

UWAGA: omyłkowe użycie znaku pojedynczej równości zamiast podwojonego, jest najczęstszym błędem popełnianym przez studentów!

Próba wpisania równości 2 x + 3 = 4 kończy się komuniaktem o błędzie :

2x+3=4

Poprawny sposób wymaga użycia znaku podwójnej równości:

2x+3==4

Znak pojedynczej równości, inaczej instrukcja przypisania, służy do zapisywania pod wygodnymi dla nas nazwami wyrażeń, wyników itp. Na przykład :

x=4-3

oznacza : oblicz 4 - 3 a nastepnie zapamiętaj wynik pod nazwą x. Od tego momentu, użycie symbolu x jest równoważne liczbie jeden:

x

x+x

x+x+x+x

x+1

Symbol x nie może odtąd być używany jako niewiadoma :

2x+3==4

Otrzymujemy fałsz, gdyż 2*1 + 3 = 5 nie jest równe 4!

Bardzo przydatna jest umiejętność usunięcia przypisanej wartości x = 1. Można to zrobić przynajmniej na dwa sposoby :

Clear[x] (* Sposób pierwszy *)

x=. (* Sposób drugi *)

Początkujący często popełniają omyłkowe przypisania wielokrotnie. W takiej sytuacji konieczne może był wyłączenie i ponowne włączenie Kernela. W tym celu za pomocą kursora myszki wybieramy z Menu polecenie Evaluation->Quit Kernel ->Local.

Różnicę pomiędzy instrukcją przypisania a równością logiczną ilustruje ponizsza linijka :

rownanie  = ( 2x+3==4 )

Nasz Przykład 0 to 2 x + 3 == 4, i został zapamiętany pod nazwą rownanie. Rolą nawiasów okrągłych ( ) jest grupowanie wyrazeń i ustalenie kolejności wykonywania działań. (Nawiasy okrągłe nie są w tym wypadku konieczne. Dałem je dla przykładu.)

rownanie

Aby podstawić do równania pewną wartość x, np: x=2,  należy użyć operatora , , zamień wszystko'' , zapisywanego jako  /.  (ukośnik + kropka),
oraz reguły podstawiania (ang. Rule ) x->2 (minus + znak większości )

rownanie /.x->1

rownanie /.x->1/2

rownanie/.x->0.5

Warto zwrócić uwagę na nastepującą ciekawostkę. Wstawiając różne wartości x możemy przypadkowo natrafić na poprawne rozwiązanie. Gdy napiszemy odpowiedni program, komputer może te podstawienia wykonywać automatycznie. Można w ten sposób ,,rozwiązać’’ niektóre problemy. Szczególnie dotyczy to zadań szkolnych,  w których niepisane reguły zmuszają autorów pytań do konstruowania treści w taki sposób, aby wynik nie był zbyt skomplikowany.

Umiejąc zapisać równanie, możemy teraz użyć metod numerycznych lub symbolicznych do rozwiązania naszego równania.

Metody numeryczne:

FindRoot (dowolne równania)

NSolve (problemy algebraiczne, np. pierwiastki wielomianów)

Metody symboliczne:

Solve (,,naiwne’’ algorytmy rozwiązywania równań, szczególnie przydatne w fizyce)

Reduce (ścisłe matematycznie rozwiązania)

FindInstance (zaawansowane algorytmy, możliwość wyszukiwania wielokrotnych rozwiązań, tylko dla równań bez parametrów)

UWAGA: metody symboliczne pozwalają także na rozwiązywanie nierówności.

KOLEJNOŚĆ w jakiej wymienione zostały powyższe polecenia nie jest przypadkowa. Odzwierciedla w przybliżeniu spodziewany czas w jakim należy spodziewać się uzyskania wyniku. Z drugiej strony ,,ścisłość’’ uzyskanego rezultatu jest tym większa im dalsza pozycja na powyższej liście. 
Będziemy te zagadnienia omawiać dokładniej na kolejnych wykładach. 

Spodziewane efekty uruchomienia polecenia:

- METODY NUMERYCZNE -

FindRoot - jedno, przybliżone rozwiązanie równania; wynik na ogół pewny w przedziale zadanej dokładności, uzyskany zwykle w czasie niezauważalnie małym
NSolve - wszystkie rozwiązania równań wielomianowych, ale każde z nich przybliżone; metoda pewna w podanej kategorii równań, może wymagać długiego czasu obliczeń

- METODY SYMBOLICZNE -

Solve - rozwiązuje równania ,,naiwym’’ algorytmem, np. stosując f. odwrotne; odpowiedź jest często niekompletna (brakuje rozwiązań), zdarza się, że błędna; dosyć szybka

Reduce - rozwiązuje równania ściśle matematycznie, uwzględniając wszystkie przypadki; odpowiedź jest na ogół bardzo złożona, a jej uzyskanie wymaga sporo czasu; wynik na ogół jest zupełnie niezrozumiały dla początkujących użytkowników; rozwiązania, o ile zostaną znalezione są na ogół poprawne

FindInstance - najsilniejsze, ale także najwolniejsze z poleceń (bywa, że wymaga godzinnych obliczeń); potrafi znajdować wiele rozwiązań, a także udowodnić, że nie ma innych; stosuje bardzo zaawansowane metody matematyczne; działa tylko dla równań bez parametrów; definiuje nowe liczby przestępne

Zobaczmy jak to wygląda w praktyce :

rownanie

FindRoot znajduje rozwiązanie w pobliżu punktu startowego, np : odczytanego z wykresu

FindRoot[rownanie,{x,0.5}]

W tym przypadku możemy  użyć NSolve, gdyż równanie zawiera tylko wielomiany. Nie potrzeba punktów statowych.

NSolve[rownanie,x]

Solve znajduje ścisłe rozwiązanie:

Solve[rownanie,x]

Reduce podaje wynik w innej, równoważnej  postaci:

Reduce[rownanie, x]

FindInstance szuka zadanej liczby rozwiązań. Zażądaliśmy znalezienia co najmniej dwóch rozwiązań. Ponieważ w wyniku otrzymaliśmy pojedyncze rozwiązanie, możemy uznać, że Mathematica udowodniła, że istnieje tylko jedno rozwiązanie!

FindInstance[rownanie,x,2]

Proszę zwrócić uwagę na formę uzyskanej odpowiedzi, jak wiemy równoważnej x=1/2 w notacji  tradycyjnej.

Wynik jest podawany w postaci reguły transformacyjnej , za wyjątkiem Reduce. Wynikiem jest Lista rozwiązań, w tym wypadku jednoelementowa, gdyż rozwiązanie jest jedno. FindRoot zawsze zwraca jeden wynik, i postać listy to uwzględnia. Pozostałe funkcje mogą zwracać wiele wyników, i dlatego odpowiedź jest listą dwukrotnie ,,zagnieżdżoną’’.

Aby wydobyć z takiej postaci wartość rozwiązania (0.5), postępujemy następująco:

x/.{x->0.5}

czyli podstawiamy w miejsce x wartość zgodnie z regułą transformacyjną {x -> 0.5}.

Przykład 1: Rozwiąż w dziedzinie liczb rzeczywistych równanie, w notacji ,,tablicowej’’ podane jako:

x + 1 = (2^x)

Ten przykład, wyglądający w pierwszym momencie na równie prosty jak poprzedni, zilustruje konieczność stosowania zalecanej kolejności rozwiązywania równań.

Plot[{x+1,2^x},{x,-4,4}]

Wykres pokazuje , że prawdopodobnie są dwa rozwiązania. Aby to lepiej zobaczyć, zmieniam zakres x :

Plot[{x+1,2^x},{x,-2,2}]

Plot[{x+1,2^x},{x,-1/2,3/2}]

Z wykresu odczytujemy przybliżone rozwiązania x ≈ 0 oraz x ≈ 1. Zgodnie z zalecanym schematem, zastosujemy teraz FindRoot.

FindRoot[x+1==2^x,{x,0}]

FindRoot[x+1==2^x,{x,1}]

FindRoot potwierdza nasze przypuszczenie, że rozwiązaniem są liczby 0 i 1. Dopiero teraz możemy pokusić się o użycie Solve.

Solve[x+1==2^x,x]

Powyższy rezultat stanowi odpowiedź na pytanie po co rysować wykresy i szukać rozwiązania numerycznego zanim wywołamy Solve. Komunikat o błędzie, oraz niezrozumiała dla większości początkujących w tym temacie studentów odpowiedź w drugim rozwiązaniu, zamiast spodziewanego x=1 to zniechęcający wynik. Na szczęście my już wiemy, że drugim rozwiązaniem powinno być 1, lub przynajmniej coś bardzo bliskiego 1. Sprawdzamy więc numeryczną wartość wyrażenia za pomocą ważnej funkcji N:

N[((-Log[2]-ProductLog[-1,-((Log[2])/2)])/(Log[2]))]

W takiej postaci Mathematica używa procesora w celu wyliczenia odpowiedzi, co jest na ogół najszybsze, i wystarczającej dokładności (16 cyfr po przecinku). Mamy jednak możliwość wykonania obliczeń o dowolnie dużej dokładności (chyba, że braknie pamięci). Np: obliczmy to wyrażenie z dokładnością 128 cyfr po przecinku:

N[((-Log[2]-ProductLog[-1,-((Log[2])/2)])/(Log[2])),128]

Wyrażenie ewidentnie jest równe 1. Dlaczego Mathematica podaje tak dziwną odpowiedź? Otóż Solve, aby zaoszczędzić czas, nie dokonuje uproszczenia wyników. Możemy to zrobić sami za pomocą polecenia Simplify (uprość).

Simplify[((-Log[2]-ProductLog[-1,-((Log[2])/2)])/(Log[2]))]

Użycie Simplify nic nie dało. Dla doświadczonego użytkownika jest to oczywiste. Simplify potrafi upraszczać wyłącznie wyrażenia zawierające funkcje elementarne (znane ze szkoły), jak dodawanie, mnożenie, niektóre pierwiastki (Sqrt) , logarytmy (Log), funkcje trygonometryczne (Sin ,Cos, Tan) itd. Wyrażenie zawiera funkcję specjalną ProductLog. Aby uprościć takie wyrażenie musimy zastosować ,,mocniejszą’’ (ale też wymagającą większej mocy obliczeniowej) wersję Simplify, czyli FullSimplify:

FullSimplify[((-Log[2]-ProductLog[-1,-((Log[2])/2)])/(Log[2]))]

Jaki wynik da Reduce?

Reduce[x+1==2^x,x]

Odpowiedź wygląda jeszcze inaczej. Operator || to LUB logiczne, natomiast && to I logiczne. Integers oznacza zbiór liczba całkowitych (Reals - rzeczywistych, Rationals - wymiernych, brak pojęcia liczby naturalnej ). Symbol C[1] oznacza więc dowolną liczbę całkowitą. W notacji tablicowej zwykle używamy literki k lub n.

Zapis powyższy oznacza istnienie nieskończonej liczby rozwiązań numerowanej liczbą całkowitą C[1].  Jest to zaskakujące, bo dotąd spodziewaliśmy się dwóch rozwiązań: x=0 i x=1. Niestety (dla studentów pierwszego roku), Mathematica używa zwykle liczb zespolonych, o ile nie zażądamy inaczej. W dziedzinie liczb zespolonych funkcja (2^x) jest okresowa, podobnie jak np. Sin[x] dla liczb rzeczywistych. Aby znazleźć wyłącznie rozwiązania rzeczywiste, musimy to jawnie podać:

Reduce[x+1==2^x,x,Reals]

Powyższa uwaga dotyczy także FindInstance :

FindInstance[x+1==2^x,x,Reals,10]

Ponieważ zażądaliśmy znalezienia 10 rozwiązań, a otrzymaliśmy 2, mamy pewność, że nie ma ich więcej.

Podsumowanie : przypadek bez parametrów

Równania tworzymy przy pomocy znaku podwójnej równości, == ( polecenie Equal).

Zalecana kolejność czynności przy rozwiązywaniu równań bez parametrów:
Plot - FindRoot - [NSolve] - Solve - Reduce - FindInstance

Podana niewiadoma, np: x,  jest traktowana jako liczba zespolona ! Aby szukać tylko rozwiązań rzeczywistych metodami symbolicznymi (Reduce, FindInstance) należy dodać opcję Reals, oznaczającą zbór liczb rzeczywistych.

Wyniki symboliczne należy obliczyć za pomocą polecenia N, sprawdzając czy nie są liczbami zespolonymi. Skomplikowane wyrażenia spróbować uprościć poleceniami Simplify (jeżeli składają się z funkcji elementarnych) oraz FullSimplify (jeżeli zawierają funkcje specjalne lub Simplify nie zadziałało).