Aansluitingsmodule Wiskunde voor BMT

Vakcode: 8G116
Datum: September 2003
Docent: Dr L.M.J. Florack
Begeleiders: Ir. R. Duits, Ir. B. Platel, Ir. F.M.W. Kanters

Met dit Mathematica notebook kun je zelf je oplossingen controleren. Bestudeer daartoe onderstaande voorbeelden en pas ze naar wens aan. Geloof niet blindelings in de resultaten die Mathematica genereert en let goed op de toelichtingen erbij.

Hoofdstuk 1: Elementaire algebraïsche vaardigheden

Haakjes wegwerken doe je met de functie Expand[]:

Expand[(((3  a - b))^2)]

Soms is dat niet expliciet nodig:

((((2/(Sqrt[20])) + (3/(Sqrt[5]))))^2)

Vereenvoudigen doet Mathematica  deels uit zichzelf, maar niet altijd zoals je het wellicht zou willen. Er is ook een expliciete functie Simplify[] beschikbaar. Gewoon een kwestie van proberen.

((((-2 c (d^4)))^3)/(2 (((3 (c^2) d))^2)))

Simplify[((((-2 c (d^4)))^3)/(2 (((3 (c^2) d))^2)))]

Als je gebroken machten of worteltekens gebruikt moet je Mathematica soms expliciet uitleggen wat je aannames zijn:

2 (Sqrt[ 2 a (b^2)]) (Sqrt[a])

Simplify[2 (Sqrt[ 2 a (b^2)]) (Sqrt[a])]

Het probleem hier is dat Mathematica niet weet dat a niet-negatief is. Dat kun je als volgt aangeven:

Simplify[2 (Sqrt[ 2 a (b^2)]) (Sqrt[a]), {a ≥ 0}]

Een tweede probleem is dat Mathematica niet weet dat b een reëel getal is en zo ja, wat het teken ervan is. Ook dat kun je aangeven. Stel bijvoorbeeld dat b niet-negatief is:

Simplify[
      2 (Sqrt[ 2 a (b^2)]) (Sqrt[a]), {a ≥ 0, 
        b ≥ 0}]

Of dat b niet-positief is:

Simplify[
      2 (Sqrt[ 2 a (b^2)]) (Sqrt[a]), {a ≥ 0, 
        b ≤ 0}]

In het algemeen kun je als volgt te werk gaan (Abs[] staat voor "absolute waarde"):

Simplify[
      2 (Sqrt[ 2 a (b^2)]) (Sqrt[a]), {a ≥ 0, 
        (b^2) ≥ 0}]

Simplify[
      2 (Sqrt[ 2 a (b^2)]) (Sqrt[a]), {a ≥ 0, 
        b ∈ Reals}]

Tip: Als je Simplify[] gebruikt, gebruik dan voor de zekerheid deze optie om al je aannamen kenbaar te maken.

Mathematica factoriseert niet uit zichzelf. Dat moet je met de functie Factor[] aangeven:

(x^3) + 5  (x^2) - 14  x

Factor[(x^3) + 5  (x^2) - 14  x]

Soms bestaat de factorisatie uit slechts één factor:

Factor[(x^2) + 1]

Mathematica voert geen "staartdelingen" uit om breuken van veeltermen te vereenvoudigen. Ook hier kun je Factor[] gebruiken om vereenvoudiging af te dwingen, mits de noemer inderdaad een factor is die voorkomt in de factorisatie van de teller.

((3  (x^2) - 20  x + 12)/(x - 6))

Factor[((3  (x^2) - 20  x + 12)/(x - 6))]

Hier werkt ook Simplify[]:

Simplify[((3  (x^2) - 20  x + 12)/(x - 6))]

Tenslotte kun je ook nog gebruik maken van Together[], die van een uitdrukking een breuk tracht te maken (dat is ze al in dit voorbeeld) en deze tevens tracht te vereenvoudigen door gemeenschappelijke factoren in teller en noemer weg te delen (dat is wat we hier willen):

Together[((3  (x^2) - 20  x + 12)/(x - 6))]

Een vierde mogelijkheid om dit resultaat te bewerkstelligen wordt hieronder besproken.

Als de breuk geen veelterm oplevert, dus als de noemer geen factor is die voorkomt in de ontbinding van de teller, dan werkt noch Factor[] noch Simplify[] noch Together[]:

(((x^3) + 2  (x^2) + 5  x + 1)/((x^2) + x + 1))

Factor[(((x^3) + 2  (x^2) + 5  x + 1)/((x^2) + x + 1))]

Simplify[(((x^3) + 2  (x^2) + 5  x + 1)/((x^2) + x + 1))]

Together[(((x^3) + 2  (x^2) + 5  x + 1)/((x^2) + x + 1))]

Zoals bekend kun je de breuk toch enigszins vereenvoudigen middels een "staartdeling" tot een veelterm plus restbreuk. De functie Apart[] doet dit wel voor je:

Apart[(((x^3) + 2  (x^2) + 5  x + 1)/((x^2) + x + 1))]

Overigens biedt Apart[] nog een vierde mogelijkheid om van gemeenschappelijke factoren in teller en noemer af te komen (zie voorbeeld hierboven):

Apart[((3  (x^2) - 20  x + 12)/(x - 6))]

Voor het oplossen van veeltermvergelijkingen kent Mathematica de functie Solve[]. Hiermee moet je enigszins voorzichtig te werk gaan. Ten eerste: Als een vergelijking naast variabelen ook parameters (ongespecificeerde constanten) heeft, dan moet je aangeven wat de variabele is met betrekking tot welke je de vergelijking wil oplossen. Als voorbeeld de ABC-formule:

Solve[A (x^2) + B x + C == 0, 
      x]

Ten tweede: Je ziet dat Mathematica niet maalt om de voorwaarde dat de discriminant niet-negatief mag zijn! Hier zie je dat Mathematica zelfs "onoplosbare" vergelijkingen weet op te lossen:

Solve[(x^2) + 1 == 0, x]

Wat is hier aan de hand? Mathematica hanteert een ruimere oplossingsverzameling dan de reële getallen, waardoor alle veeltermvergelijkingen oplossingen hebben. Dit zijn, zoals in bovenstaand voorbeeld, echter niet altijd reële oplossingen. Als je het symbool i tegenkomt in de oplossing, dan is deze niet reëel maar complex (i is een zogenaamd imaginair getal). Niet-reëelwaardige oplossingen zullen we (voorlopig) negeren.

Solve[
      (x^2) + x ( (2^(1/12)) - (3^(1/17))) - (2^(1/12)) (3^(1/17)) == 0, 
      x]

Met NSolve[] krijg je benaderende oplossingen:

NSolve[
      (x^2) + x ( (2^(1/12)) - (3^(1/17))) - (2^(1/12)) (3^(1/17)) == 0, 
      x]

Hoofdstuk 2: Goniometrie

Ook vele goniometrische vergelijkingen kun je oplossen met Solve[]. Echter, je vindt hiermee i.h.a. niet alle oplossingen. Als Mathematica een waarschuwing geeft moet je die dan ook niet klakkeloos naast je neer leggen. In dit geval zul je zelf je kennis van goniometrie moeten gebruiken om a.h.v. de door Mathematica gevonden oplossing(en) alle overige oplossingen te vinden:

Solve[Sin[x] == (1/2), x]

Als je vermoedt dat je een andere oplossing hebt kun je deze eenvoudig controleren. Dit kan met de zgn. replacement operator /. waaraan je een zogenaamde rule toevoegt om aan te geven wat door wat vervangen moet worden.

Sin[x] == (1/2) /. x ->  ((5  π)/6)

Sin[x] == (1/2) /. x ->  π

Solve[Tan[2  x + 1]^2 - (1 + (Sqrt[3])) Tan[2  x + 1] + (Sqrt[3]) == 0, 
      x]

Het is in dit geval natuurlijk inzichtelijker om eerst Tan[2x+1] op te lossen:

linkerlid = 
      Tan[2  x + 1]^2 - (1 + (Sqrt[3])) Tan[2  x + 1] + (Sqrt[3])  /. 
        Tan[2  x + 1] -> t

Solve[linkerlid == 0, t]

Zo zetten we de lijst van replacement rules om in een lijst van expliciete oplossingen. De operator Union[] zorgt ervoor dat elke oplossing precies éénmaal voorkomt. Het % teken staat voor "het resultaat van de voorafgaande berekening".

tussenoplossingen  =  Union[t /. %]

Solve[
      Tan[2  x + 1] == tussenoplossingen[[1]]  ||  
        Tan[2  x + 1] == tussenoplossingen[[2]], x]

Uit de waarschuwing blijkt dat we ook nu de oplossingen met een flinke korrel zout moeten nemen, maar in elk geval hebben we er méér dan voorheen.

Met Remove[] verwijder je definities, zodat er later geen verwarring over kan ontstaan en tevens het geheugen dat ervoor gealloceerd was vrijgemaakt wordt.

Remove[linkerlid, tussenoplossingen]

Nog een voorbeeld:

Solve[Tan[x] == Sin[x], x]

Wederom een waarschuwing, dus wederom een korrel zout erbij. Periodiciteit van de goniometrische functies zorgt ervoor dat er in werkelijkheid oneindig veel oplossingen zijn!

Let op!

In geval van niet-polynomiale vergelijkingen geeft Mathematica  in het algemeen niet alle oplossingen. Sla  geen waarschuwingen in de wind, maar gebruik je verstand! In veel gevallen kun je een ingewikkelde goniometrische vergelijking middels een substitutie "herformatteren" tot een veeltermvergelijking, waarop je de technieken uit het vorige hoofdstuk kunt toepassen.

Hoofdstuk 3: Exponentiële en logaritmische functies

Voor vergelijkingen met machtsfuncties en logaritmen geldt in principe dezelfde kanttekening als voor goniometrische en andere niet-polynomiale vergelijkingen. De oplossingen die Mathematica vindt moeten voorkomen onder jouw oplossingen, maar niet per se andersom.

Deze vergelijking gaat probleemloos:

Solve[Log[(x^3) - (x^2) - x + 1] == 0, x]

Maar hier moeten we alert zijn. Vindt Mathematica wel alle oplossingen?

Solve[(E^((x^2) + 1)) == (E^(2  x)), 
      x]

Gebruik makend van de je bekende regels weet je dat dit equivalent is met de volgende veeltermvergelijking, die maximaal twee oplossingen heeft:

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

Union[x /. %]

Twee samenvallende oplossingen dus, dus de waarschuwing bleek overbodig. Nog een voorbeeld:

Solve[(E^(2  x)) - 3  (E^x) + 2 == 0, 
      x]

Gezien de waarschuwingen proberen we een soortgelijk alternatief als voorheen. Let op onderstaande replacement rules. De tweede lijkt overbodig, maar is dat niet (probeer maar eens zonder deze). In principe vervang je met een replacement rule een bepaald patroon. Als dat patroon voor Mathematica "verborgen" zit in een andere expressie wordt dit daarin niet vervangen! In dit voorbeeld is het Mathematica kennelijk niet bekend dat (e^(2x)) gelijk is aan het kwadraat van (e^x).

linkerlid = (E^(2  x)) - 3  (E^x) + 
          2 /. {(E^x) -> 
            t, (E^(2  x)) -> (t^2)}

We krijgen nu geen waarschuwingen, dus mogen we de eindoplossingen wel vertrouwen:

Solve[linkerlid == 0, t]

tussenoplossingen  =  Union[t /. %]

In Mathematica werkt de functie Log[], evenals de meeste andere functies, elemtentsgewijs op een lijst. We hoeven dus niet de tussenoplossingen één voor één te nemen:

eindoplossingen = Log[%]

Remove[linkerlid, tussenoplossingen, eindoplossingen]

Let op!

In geval van niet-polynomiale vergelijkingen geeft Mathematica  in het algemeen niet alle oplossingen. Sla  geen waarschuwingen in de wind, maar gebruik je verstand! In veel gevallen kun je een ingewikkelde vergelijking met exponentiële of logaritmische functies middels een substitutie "herformatteren" tot een veeltermvergelijking, waarop je de technieken uit een voorgaand hoofdstuk kunt toepassen.

Hoofdstuk 4: Differentiëren

Zo definieer je een functie (let op de underscore):

f[x_] := (x^5)

Zo is de afgeleide gedefinieerd:

Limit[((f[x + h] - f[x])/h), h -> 0]

Maar Mathematica kent haar regels voor differentiëren:

f'[x]

Met Remove[] verwijder je, net als voorheen, een eerder geïntroduceerd symbool, zodat er later geen verwarring over zal bestaan.

Remove[f]

Zo check je dus limieten:

Limit[Sin[h], h -> 0]

Limit[Cos[h], h -> 0]

Limit[Tan[h], h -> 0]

De exponentiële functie heet in Mathematica Exp[]. The natuurlijke logaritme heet Log[]. Wil je de logaritme met een ander grondtal, dan roep je Log[] aan met twee argumenten als volgt:

Log[E]

Log[10, 10]

Met == test je de identiteiten die je al vermoedde:

Log[E, x] == Log[x]

Exp[x] == (E^x)

Mathematica heeft geen problemen met variabelen en parameters, zolang je maar duidelijk aangeeft met betrekking tot welk van de symbolen je een afgeleide neemt:

f[x_] := Sin[ω x + α]

f'[x]

Dit is in dit geval hetzelfde als de volgende, meer expliciete notatie (lees "de afgeleide van f(x) m.b.t. de variabele x"):

D[f[x], x]

Maar je had de parameters ook als extra variabelen mogen beschouwen, zodat je een functie van 3 variabelen krijgt. Dan is niet meer duidelijk wat je met de accent-notatie bedoelt. (Om verwarring te voorkomen gebruiken we wederom Remove[]; we gaan f immers opnieuw definiëren.)

Remove[f]

f[x_, ω_, α_] := Sin[ω x + α]

Als we nu de accent-notatie gebruiken weet Mathematica niet m.b.t. welke van de drie argumenten er gedifferentieerd moet worden:

f'[x, ω, α]

Daarentegen is dit wel ondubbelzinnig:

D[f[x, ω, α], x]

Dit mag je ook schrijven als (lees: "de 1-ste orde afgeleide van f(x,ω,α) m.b.t. de variabele x"):

D[f[x, ω, α], {x, 1}]

Hogere orde afgeleiden neem je als volgt:

D[f[x, ω, α], {x, 2}]

Remove[f]

Enkele voorbeeldjes uit het dictaat:

D[(x^4), x]

D[(Sqrt[x]), x]

D[Sin[3 (x + (π/4))], x]

D[(2^x), x]

D[Log[3  x], x]

D[2  (E^(-x)) Sin[2  x] Cos[3  x], x]

Een gecompliceerde uitdrukking valt wellicht te vereenvoudigen:

Simplify[%]

Zoals je opvalt heeft Mathematica hier kennelijk gebruik gemaakt van bepaalde goniometrische identiteiten!

D[(R/k) Log[(R/k)] - (R/k), R]

De definities van sinus en cosinus hyperbolicus staan in het dictaat.

D[Sinh[x], x]

D[Cosh[x], x]

Wel even checken of die wel overeenkomen met die welke Mathematica hanteert! Roep in herinnering dat het dubbele gelijkteken "==" staat voor een vergelijkende test die True of False (of "geen conclusie") oplevert:

Sinh[x] == (((E^x) - (E^(-x)))/2) // 
      Simplify

Cosh[x] == (((E^x) + (E^(-x)))/2) // 
      Simplify

Opmerking: Als je //Simplify weglaat weet Mathematica zich geen raad. Je kunt de twee "forward slashes" // lezen als "pas hierop toe". Dus x//f betekent "pas f toe op x", d.i. dus hetzelfde als f[x]. Hier is nog een voorbeeld om te onthouden (N[] staat voor "numerieke", d.w.z. "benaderende waarde"):

N[π]

π  // N

Mocht je het niet nauwkeurig genoeg vinden:

N[π, 35]

Zou Mathematica ook de rekenregels voor differentiëren kennen uit het dictaat? Enkele testjes (trek zelf je conclusies):

D[a f[x] + b g[x], x]

D[f[x] g[x], x]

D[f[g[x]], x]

D[f[x]/g[x], x]

Dit komt je wellicht niet bekend voor. Maar:

Together[%]

Dit is de welbekende "NAT" regel.

Hoofdstuk 5: Primitiveren

Primitiveren gaat als volgt:

f[x_] := 4  (x^3)

∫f[x] \[DifferentialD]x

Kennelijk voegt Mathematica géén integratieconstante toe uit eigen beweging! Uit de volgende test mag je dan ook niet concluderen dat (x^4) + 1geen primitieve is van 4(x^3). Dit is wederom een waarschuwing dat je alert moet blijven en je Mathematica resultaten niet klakkeloos moet accepteren!

∫f[x] \[DifferentialD]x == (x^4) + 1  // 
      Simplify

Remove[f]

Met absolute waarden heeft Mathematica ook een probleem:

∫Log[Abs[x]] \[DifferentialD]x

Zonder de absolute waarde bekommert Mathematica zich niet om de restricties op het argument van de logaritme en gaat ervan uit dat jij zelf zo verstandig bent te beseffen dat x positief (en reëel) moet zijn.

∫Log[x] \[DifferentialD]x

...Of negatief natuurlijk:

∫Log[-x] \[DifferentialD]x

Hier is weer een kleine greep sommetjes uit het dictaat:

∫(1/(Sqrt[x])) \[DifferentialD]x

∫Log[(1/2), x] \[DifferentialD]x

∫x (E^x) \[DifferentialD]x

Deze doe je niet zo een-twee-drie met de hand (maar het zou wel kunnen m.b.v. partieel integreren!):

∫(x^7) (E^x) \[DifferentialD]x

Als je het niet gelooft (probeer ook eens zonder //Simplify):

D[%, x] == (x^7) (E^x)  //  Simplify

∫x Sin[x] \[DifferentialD]x

Hoofdstuk 6: Eenvoudige differentiaalvergelijkingen

f[x_, ω_, α_] := Sin[ω x + α]

Zo verifieer je dat deze functie aan de differentiaalvergelijking f'' + (ω^2) f = 0 voldoet:

D[f[x, ω, α], {x, 2}] +  (ω^2) f[
              x, ω, α] == 0  //  Simplify

Remove[f]

Zo los je een eenvoudige differentiaalvergelijking op:

DSolve[f''[x] + f[x] == 0, f, x]

En zo controleer je de oplossing:

f''[x] + f[x] == 0  /. %  //  Simplify

Remove[f]

Je kunt ook begin- of randvoorwaarden meegeven:

DSolve[{f'[x] == f[x], f[0] == 1}, f, x]

Alternatieve inputgedaante:

DSolve[{f'[x] == f[x], f[0] == 1}, f[x], x]

Het verschil met voorgaande uitdrukking is dat nu enkel het symbool f[x] (een enkele functiewaarde) inhoud heeft gekregen, maar niet de functie f als zodanig. (Het symbool %% staat voor "het resultaat van de voorlaatste berekening".) Kijk maar eens naar het volgende drietal functiewaarden (Flatten[] haalt een overbodig paar accoladen weg; je mag deze ook achterwege laten):

{f[x], f[y], f[0]}  /. Flatten[%]

DSolve[{f''[x] == f[x], 
        f[0] == 1, f'[0] == 0}, f, x]

Remove[f]

DSolve[f''[x] + (ω^2) f[x] == 0, f, x]

Remove[f]

DSolve[f''[x] - (λ^2) f[x] == 0, f, x]

Remove[f]

DSolve[{f''[x] + (ω^2) f[x] == 0, 
        f[0] ==  1, f'[0] == 1}, f, x]

Remove[f]

DSolve[{f''[x] - (λ^2) f[x] == 0, 
        f[0] ==  1, f'[0] == 0}, f, x]

Remove[f]

DSolve[{U[x] U'[x] == a, U[0] == 0}, U, x]

Remove[U]

Hoofdstuk 7: Toepassingen

Als voorbeeld van het gebruik van Mathematica kijken we tenslotte naar de opgave "Getijden".

Als eenheden gebruiken we uren voor tijdsbepalingen en meters voor hoogten. (Vergewis je ervan dat eventuele waarschuwingen van Mathematica onschuldig zijn.)

uur = 1; min = 1/60 uur; sec = 1/3600 uur; dag =  24 uur; 
    m = 1;

We slaan de getijdenmetingen op in een lijstje:

getijdenmetingen = {{2 uur  + 45 min, 0.21  m}, {9  uur  + 15 min, 
            1.71 m}, {15 uur  + 18 min, 0.30 m}, {21 uur  + 15 min, 
            1.56 m}, {1 dag + 3 uur  + 20 min, 
            0.21 m}, {1 dag + 9 uur  + 56 min, 
            1.74 m}, {1 dag + 16 uur + 0  min, 
            0.28 m}, {1 dag + 21 uur + 53 min, 
            1.52 m}, {2 dag + 3 uur  + 51 min, 0.21 m}} // N

Mathematica beschikt over een "add-on package" dat nuttig is bij deze opgave, maar expliciet geladen moet worden voor gebruik:

Needs["Statistics`NonlinearFit`"]

Als je niet zeker weet of bepaalde variabelen ongedefinieerd zijn, gebruik dan Clear[]. (Opmerking: In het algemeen is het verstandig om namen van symbolen niet met een hoofdletter te beginnen, omdat je dan in conflict kunt raken met door Mathematica reeds gedefinieerde symbolen. Die beginnen namelijk doorgaans met een hoofdletter. We trekken ons er hier even niks van aan.)

Clear[A, T, τ, b];

In onderstaand voorbeeld zie je wederom dat je niet klakkeloos moet afgaan op wat Mathematica je voorschotelt! De oplossing is namelijk fout! Dat zie je meteen aan het plotje, welk het door Mathematica geschatte getijdenprofiel laat zien over een periode van zo'n anderhalf etmaal.

NonlinearFit[getijdenmetingen, A Cos[2  π ((t - τ)/T)] + b, 
      t, {A, T, τ, b}]

Plot[%, {t, 9  uur + 15  min, 1  dag + 21  uur}, 
        PlotRange -> All, Frame -> True];

Clear[A, T, τ, b];

Met een geringe hoeveelheid denkwerk lukt het je om tenminste één parameter zelf te bepalen. Je weet namelijk dat de periode van een eb-en-vloed beweging precies een half etmaal is! Dat is in flagrante strijd met wat Mathematica je hierboven voorhoudt. (Kun je Mathematica's conclusie overigens verklaren?) Derhalve:

T = dag/2

De parameter T hoeven we dus niet aan Mathematica over te laten:

NonlinearFit[getijdenmetingen, A Cos[2  π ((t - τ)/T)] + b, 
      t, {A, τ, b}]

Plot[%, {t, 9  uur + 15  min, 1  dag + 21  uur}, 
        PlotRange -> All, Frame -> True];

Dit lijkt een veel plausibeler resultaat!

EINDE