Uge 6: Ekstrema og Optimering#

Demo af Christian Mikkelstrup, Hans Henrik Hermansen, Jakob Lemvig, Karl Johan Måstrup Kristensen og Magnus Troen

from sympy import *
from dtumathtools import *
init_printing()

Når man skal til at undersøge ekstrema af en funktion \(f:\Omega \to \mathbb{R}\) er der i princippet 3 områder, som skal undersøges. I Theorem 5.2.2 beskrives de ved

  1. \(\boldsymbol{x}_0 \in \partial \Omega \cap \Omega\) (altså min og/eller max kan være et punkt på randen af definitionsmængden \(\Omega\))

  2. \(\boldsymbol{x}_0\) er et punkt hvor \(f\) ikke differentiabel (kladet undtagelsespunkt i det følgende)

  3. \(\boldsymbol{x}_0\) er et punkt hvor \(f\) er differentiabel og \(\nabla f(\boldsymbol{x}_0) = 0\) (kaldet et stationært punkt)

Lokale ekstrema, eksempel 1#

Vi vil forsøge at finde alle ekstremumspunkter for funktionen \(f: \mathbb{R}^2 \to \mathbb{R}\) givet ved:

\[\begin{equation*} f(x,y) = x^3 - 3x^2 + y^3 - 3y^2. \end{equation*}\]

Vi bemærker at \(f\) er defineret og differentiabel på alle punkter i \(\mathbb{R}^2\). Der er alstå ingen rand- eller undtagelsespunkter, vi bør undersøge.

Derfor kan vi nøjes med at undersøge de stationære punkter, der er givet ved løsningen til ligningerne:

x,y = symbols("x y", real=True)
f =  x**3 - 3 * x**2 + y**3 - 3 * y**2
lign1 = Eq(f.diff(x),0)
lign2 = Eq(f.diff(y),0)
display(lign1,lign2)
../_images/a8ae2d19c1f0108fd7c4126d56363108d88c7b86f3930196df0392348db7e8ee.png ../_images/68c8e4e0660277c151f9e4f95b047986e0d26e716b31a9876b1e23b632c29a4c.png

Disse ligninger er ikke-lineære, men løses alligevel let, enten i hånden eller i SymPy:

sols = nonlinsolve([lign1, lign2], [x,y])
sols
../_images/474f1091b180ed3157928aeb6444f83a49d36e104a68d35c5226c9647ef283f6.png

Nu har vi vores stationære punkter. Nu kan vi finde de partielt afledede af 2. orden og opstille Hessematricen.

H = dtutools.hessian(f)
H
\[\begin{split}\displaystyle \left[\begin{matrix}6 x - 6 & 0\\0 & 6 y - 6\end{matrix}\right]\end{split}\]

Derefter indsættes de stationære punkter, og egenværdierne for \(\boldsymbol{H}_f\) undersøges, hvilket er nemt, da \(H\) allerede er diagonaliseret, og egenværdierne derfor direkte kan aflæses af matricen.

[{(x0, y0): H.subs([(x,x0),(y,y0)])} for (x0,y0) in sols]
\[\begin{split}\displaystyle \left[ \left\{ \left( 0, \ 0\right) : \left[\begin{matrix}-6 & 0\\0 & -6\end{matrix}\right]\right\}, \ \left\{ \left( 0, \ 2\right) : \left[\begin{matrix}-6 & 0\\0 & 6\end{matrix}\right]\right\}, \ \left\{ \left( 2, \ 0\right) : \left[\begin{matrix}6 & 0\\0 & -6\end{matrix}\right]\right\}, \ \left\{ \left( 2, \ 2\right) : \left[\begin{matrix}6 & 0\\0 & 6\end{matrix}\right]\right\}\right]\end{split}\]

Theorem 5.2.4 fortæller os nu at \(f\) i punktet:

  • \((0,0)\) antager (attains i eNoterne) et egentligt (lokalt) maksimum, da begge egenværdier aflæses til at være negative

  • \((2,2)\) antager et egentligt (lokalt) minimum, da begge egenværdier aflæses til begge at være positive

  • \((0,2)\) har saddelpunkt, da egenværdierne har modsat fortegn

  • \((2,0)\) har saddelpunkt efter samme argument som \((0,2)\)

Et saddelpunkt er et stationært punkt der ikke er et lokalt ekstremumspunkt. Bemærk at der er tale om lokale ekstremumsværdier. Funktionen har ingen maksimums- eller minimumsværdi, da man kan vise at \(\mathrm{im}(f)=]-\infty,\infty[\).

# Show points
list_of_stationary_points = [Matrix([x0,y0,f.subs([(x,x0),(y,y0)])]) for (x0,y0) in sols]
points = dtuplot.scatter(list_of_stationary_points, show=False, rendering_kw={"s" : 100,"color":"red"})

# Show the surface f with the stationary points
pf = dtuplot.plot3d(f,(x,-0.8,2.8),(y,-0.8,2.8),use_cm=True, colorbar=False,show=False,wireframe=True,rendering_kw={"alpha":0.6})
pf.camera = {"azim" : -50, "elev" : 30}
pf.extend(points)
pf.show()
../_images/33f0fc361033b9ec0838a063c66af2110ad95e602aa48b2db8740650f01457fe.png

Lokale ekstrema, eksempel 2#

Vi betragter nu funktionen \(f:\mathbb{R}^2 \to \mathbb{R}\) givet ved

\[\begin{equation*} f(x,y) = x^4 + 4x^2y^2 + y^4 -4x^3 - 4y^3 + 2 \end{equation*}\]

Definitionsmængden er hele \(\mathbb{R}^2\), altså er der ingen rand- eller undtagelsespunkter vi bør undersøge. Derfor nøjes vi med at undersøge de stationære punkter.

x,y = symbols('x y', real=True)

f = x ** 4 + 4 * x**2 * y ** 2 + y ** 4 - 4 * x ** 3 - 4 * y ** 3 + 2
lign1 = Eq(f.diff(x),0)
lign2 = Eq(f.diff(y),0)
lign1,lign2,f
../_images/5646da87eac0e1d7923a33edadb4d00a411c1a51c683949185a526e4db51c2c6.png
sols = nonlinsolve([lign1,lign2], [x, y])
sols
../_images/b693e6e2f32657d0ab8f48003342cdca261eed03ad84d2f610ea32001141db49.png
[(N(xsol),N(ysol)) for (xsol,ysol) in sols]
../_images/b0e24c266b89c081932b959d55a74a793dd21ebec6d4941770a286fbb5f88cc7.png

\(\verb|nonlinsolve()|\) tager ikke højde for hvordan vi har defineret vores variable, så selvom vi har prøvet at definere \(x,y\) med \(\verb|real=True|\), skal man her selv bruge hovedet. Vi kan her se, at der findes fire (reelle) stationære punkter. Nemlig:

stat_punkter = list(sols)[:-2] # Remove the last two elements (complex solutions) with list-slicing
stat_punkter
../_images/5a1ef4c1b3fe180ee02355c74413d40a1735fc33f6c647fec330a7ab1dfccb9a.png

Lad os finde Hessematricen for at kunne undersøge punkterne.

H = dtutools.hessian(f)
H
\[\begin{split}\displaystyle \left[\begin{matrix}12 x^{2} - 24 x + 8 y^{2} & 16 x y\\16 x y & 8 x^{2} + 12 y^{2} - 24 y\end{matrix}\right]\end{split}\]

Vi indsætter de stationære punkter og da \(\boldsymbol{H}_f\) ikke er diagonaliseret på forhånd som i sidste eksempel, må vi bede SymPy om egenværdierne

Hesse_matricer = [H.subs([(x,x0),(y,y0)]) for x0,y0 in stat_punkter]
Eig_Hesse_matricer = [h.eigenvals() for h in Hesse_matricer]

display(*zip(stat_punkter,Eig_Hesse_matricer))
../_images/66e60b5a34a93f55cff0c5482a3b6c1380d3a65eedda89ada56691c428f01764.png ../_images/e1cf21e365127787cfa77eaa4fcfdfff05d29b1e2854b2f7e5696c3d38cf7836.png ../_images/e5b4521d07b631d8521496ed12c79f44bdbcca82328d4193a59c87f654cff1ad.png ../_images/dafce6536af73c3549a69b208edda373bb7b7a44dfd8a95e9b4b1e1ff67fd2fa.png

Heraf kan vi aflæse at \(f\) har egenligt minimum i både \((0,3)\) og \((3,0)\). Vi kan se at \((1,1)\) er saddelpunkt og ikke et ekstremum, da der både er positiv og negativ egenværdi.

Da \(\boldsymbol{H}_f((0,0))\) har mindst en egenværdi som er er nul, er vi nødt til at lave en særundersøgelse af punktet \((0,0)\). Lad os prøve at se hvordan \(f\) opfører sig på linjen \(y=x\).

dtuplot.plot(f.subs(y,x),2,(x,-0.5,1.2),axis_center="auto")
../_images/e05264ef367620e40a973ec0ea64f8eb3b82eab94db53a84d3d342c99933a727.png
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f1ff1cc5f40>

Allerede her er det meget tydeligt, at \((0,0)\) hverken er et minimums- eller maksimumspunkt. Vi kan undersøge dette lidt nærmere:

tmp = f.subs(y,x) - f.subs([(x,0),(y,0)])
display(tmp, tmp.factor())
../_images/399e4aac434172290fa58f042320442e1d89cccba2475039dae810560becff89.png ../_images/e6b90a88d64f681b863dda208f5182b1b25bd1e399c0d02a0efcf43bd9f07488.png

Heraf kan vi se

\(f(x,x) - f(0,0) > 0\) når \(x < 0\) og \(f(x,x) - f(0,0) < 0\), når \(0 < x < \frac{4}{3}\)

Da \(f(x,x)\) antager værdier der både er større og mindre end \(f(0,0)\) for \((x,x)\) virkårligt tæt på \((0,0)\), kan \(f\) ikke have ekstremum i \((0,0)\).

Lad os se grafen for \(f\) sammen med de stationære punkter.

list_of_stationary_points = [Matrix([x0,y0,f.subs([(x,x0),(y,y0)])]) for (x0,y0) in stat_punkter]
points = dtuplot.scatter(list_of_stationary_points, show=False, rendering_kw={"color":"red", "s" : 30})

pf = dtuplot.plot3d(f,(x,-2, 5),(y,-2, 4),xlim=(-2,5),ylim=(-2,5),zlim=(-30,15), show=False, rendering_kw={"alpha":0.5})
pf.camera = {"azim" : -161, "elev" : 5}
(pf + points).show()
../_images/ed54703d1d2a4e00f19466bff7c1434b2e2945c5b9593084a1fe57fd78818b50.png

Globale ekstrema på begrænset og afsluttet mængde, eksempel 1#

Vi betragter nu funktionen \(f:\Omega \to \mathbb{R}\) med forskriften.

\[\begin{equation*} f(x,y) = 3 + x - x ^ 2 - y ^ 2 \end{equation*}\]

Igen er \(f\) veldefineret på hele \(\mathbb{R}^2\), men denne gang er definitionsmængden begrænset ved

\[\begin{equation*} \Omega := \Bigl\{(x,y) \in [0,2]\times[-1,1]\quad |\quad y \leq 1-x\Bigr\}, \end{equation*}\]

altså den mængde der indesluttes af linjerne \(y = -1\), \(y = 1-x\) og \(x=0\).

M = dtuplot.plot_implicit(Eq(x,0),Eq(y,1-x),Eq(y,-1), (1-x >= y) & (y >= -1) & (x >= 0),(x,-0.1,2.1),(y,-1.1,1.1),show=False)
M.legend = False
M.show()
The provided expression contains Boolean functions. In order to plot the expression, the algorithm automatically switched to an adaptive sampling.
../_images/60c123c9297a7cefa6728e8fe4b29f258694893146fa64f885cab438106d86f1.png

Vi bemærker at \(f\) er differentiabel over hele \(\Omega\), så der er ingen undtagelsespunkter, vi skal tage hensyn til. Derfor er den også kontinuert på hele \(\Omega\). Da \(\Omega\) er afsluttet og begrænset, har \(f\) derfor et globalt minimum og maksimum på \(\Omega\). De to værdier må enten antages i stationære punter eller på randen.

Da \(\Omega\) er en sammenhængende mængde, er værdimængden for \(f(\Omega) = [m;M]\), hvor \(m\) er det globale minimum, og \(M\) er et globale maksimum.

Lad os først kigge på \(f\)’s niveaukurver

f = 3 + x - x ** 2 - y ** 2
niveau = dtuplot.plot_contour(f,(x,-0.1,2.1),(y,-1.1,1.1),show=False)
niveau.extend(dtuplot.plot_implicit(Eq(x,0),Eq(y,1-x),Eq(y,-1),(x,-0.1,2.1),(y,-1.1,1.1),show=False))
niveau.show()
../_images/f816b8a78e6f2cdc6c9e8c0c344d10ac06cab120792dfd4d897f7624d59c9e67.png

Lad os nu bestemme de stationære punkter.

lign1 = Eq(f.diff(x),0)
lign2 = Eq(f.diff(y),0)
sols = nonlinsolve([lign1,lign2], [x,y])
sols
../_images/81c999e33af797d98331cf85d3331b224297f73ac290f19c3060182bae20981f.png

Vi kan se at punkter ligger i \(\Omega\), og er derfor et relevant stationært punkt. Lad os plotte restriktionen af \(f\) til hver af de tre randlinjer. Derefter findes de stationære punkter for disse tre randlinjer.

dtuplot.plot(f.subs(y, -1),(x,0,2), title="Randlinjen f(x, -1)")
../_images/ddb158d60f8ea885cb1fb64fcceaac25fbc394391bca8d7c122651e6f494a091.png
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f1ff1dd87c0>
dtuplot.plot(f.subs(y, 1-x),(x,0,2), title="Randlinjen f(x, 1-x)")
../_images/4c346dbe5027fae2ba64978ffdd2ce38728db7489e0ac271375a18767004ee8e.png
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f2011a3ea60>
dtuplot.plot(f.subs(x,0), (y,-1,1), ylim = (0,3),aspect="equal", title="Randlinjen f(0, y)")
../_images/1fbc447b1bf7a67403a4e5ccc6773e044e34f769b3c1ad5836a6eecf0e64afa9.png
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f1ff272dc70>
stat_punkter = set(sols)

lodret = solve(f.subs(x,0).diff(y))
vandret = solve(f.subs(y,-1).diff(x))
skrå = solve(f.subs(y,1-x).diff(x))

stat_punkter.update(set([(0,y0) for y0 in lodret]))
stat_punkter.update(set([(x0,-1) for x0 in vandret]))
stat_punkter.update(set([(x0,1-x0) for x0 in skrå]))
stat_punkter
../_images/d9b68079c1c48928151834ce08c00765a73f2c0dc2649ab88ce02ba20e4392d2.png

Nu skal vi blot finde maksimum og minimum mellem de fundne stationære punkter og randlinjernes endepunkter, så \((0,1)\), \((0,-1)\) og \((2,-1)\)

undersøgelses_punkter = list(stat_punkter) + [(0,1),(0,-1),(2,-1)]
f_værdier = [f.subs([(x,x0),(y,y0)]) for x0,y0 in undersøgelses_punkter]

minimum = min(f_værdier)
maximum = max(f_værdier)
f_værdier, minimum, undersøgelses_punkter[f_værdier.index(minimum)], maximum, undersøgelses_punkter[f_værdier.index(maximum)]
../_images/c44905c3e40168453b3651248b0587712f230597e014a4d48a02f7757fef32b5.png

Nu har vi endelig:

Globalt minimum: \(0\) i punktet \((2,-1)\)
Globalt maximum: \(\frac{13}{4}\) i punktet \((\frac{1}{2},0)\)
Værdimængde: \([0,\frac{13}{4}]\)

Lad os plotte det hele samlet

u = symbols("u")
pf = dtuplot.plot3d(f,(x,0,2),(y,-1,1),show=False,rendering_kw={"alpha":0.7})
punkter = dtuplot.scatter([Matrix([2,-1,0]),Matrix([1/2,0,13/4])],show=False,rendering_kw={"color":"red","s":20})
l1 = dtuplot.plot3d_parametric_line(u,-1,f.subs({x:u,y:-1}),(u,0,2),use_cm=False,show=False,rendering_kw={"color":"red","linewidth":2})
l2 = dtuplot.plot3d_parametric_line(0,u,f.subs({x:0,y:u}),(u,-1,1),use_cm=False,show=False,rendering_kw={"color":"red","linewidth":2})
l3 = dtuplot.plot3d_parametric_line(u,1-u,f.subs({x:u,y:1-u}),(u,0,2),use_cm=False,show=False,rendering_kw={"color":"red","linewidth":2})
combined = (pf + punkter + l1 + l2 + l3)
combined.camera = {"azim" : 148, "elev" : 40}
combined.legend = False

combined.show()
../_images/1dfc5aefeaafb077176d3019a09e6433f8a5162546d249f4fc627c86206b1394.png