Einführungskurs/Extremwertsuche
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Java</language>
== Extremwertsuche nach dem Verfahren des Goldenen Schnitts ==
Die binäre Suche muss nicht zwingend zur Intervallhalbierung führen.<br />
Wir betrachten die Extremwertsuche nach dem Verfahren des Goldenen Schnitts zunächst für die Suche eines lokalen Minimums:
<table border="0">
<tr>
<td align="center">
[[Bild:Extremwert.gif]]<br />
Animation: Minimumsuche nach dem Verfahren des Goldenen Schnitts
</td>
<td>'''Algorithmus''' (Minimumsuche):
<ul>
<li>Lege ein Suchintervall durch zwei äußere Intervallgrenzen fest.</li>
<li>Zerlege dieses Suchintervall durch einen ''zweimaligen'' Goldenen Schnitt in 3 Teilintervalle.</li>
<li>Berechne die Funktionswerte an beiden Schnittstellen.</li>
<li>Das neue Suchintervall wird aus der Schnittstelle mit dem größeren der beiden Funktionswerte und einer der äußeren Intervallgrenzen derart gebildet, dass die Schnittstelle mit dem ''kleineren'' Funktionswert ''eingeschlossen'' wird.</li>
<li>Führe im neuen Suchintervall den Goldener Schnitt durch, der wieder zu 3 Teilintervallen führt.</li>
<li>Wiederhole das Verfahren solange, bis das Suchintervall einer hinreichend kleinen ε-Umgebung genügt.</li>
<li>Der Funktionswert eines Arguments aus dieser ε-Umgebung entspricht dem gesuchten Minimum.</li>
</ul>
</td>
</tr>
</table>
== Implementation ==
Mit einem kleinen Trick lässt sich ''ein und dieselbe'' Suchfunktion sowohl für lokale Minima als auch für lokale Maxima einsetzen. Der Vergleich der Funktionswerte wird mit einem Korrekturfaktor <math>k</math> geführt, der lediglich die Werte <math>1</math> oder <math>-1</math> annehmen kann, z.B.:
if (k*fkt(li) > k*fkt(re)) ...
Dieser Faktor kann als Parameter übergeben werden und hat die gleiche Wirkung wie die Umkehr des Relationszeichens bei einem herkömmlichen Vergleich.
<code id="4d2a2c431b9c6">
public double fkt(double x) {
double y = 3*Math.sin(2*x);
return y;
}
public Object ExtremwertSuche(double von, double bis, double dx) {
final double gs = (Math.sqrt(5)-1)/2;
int genau = 4;
private double Runden(double x, int n) {
return Math.round(x*Math.pow(10, n))/Math.pow(10, n);
}
private double Suche(int k, double xl, double li, double re, double xr) {
double eps = 1/Math.pow(10, genau+2);
if (xr-xl < eps)
return (xl+xr)/2;
else if (k*fkt(li) > k*fkt(re))
return Suche(k, xl, re-gs*(re-xl), li, re);
else
return Suche(k, li, re, li+gs*(xr-li), xr);
}
private int TeilAusgabe(int k) {
int anzahl = 0;
double schnitt = gs*dx;
double xl; xr; yl; yr; x; y;
xl = von; yl = fkt(xl);
while (xl < bis) {
xr = xl+dx; yr = fkt(xr);
if (yl*yr >= 0) {
x = Suche(k, xl, xr-schnitt, xl+schnitt, xr);
y = fkt(x);
if (k*y > k*yl && k*y > k*yr) {
anzahl++;
System.out.println("f("+Runden(x, genau)+") "+(char)9+"= "+Runden(y, genau));
}
}
xl = xr; yl = yr;
}
return anzahl;
}
public void Ausgabe() {
int anzahl;
System.out.println("Lokale Maxima:");
anzahl = TeilAusgabe(1);
if (anzahl == 0) System.out.println("--> Keine lokalen Maxima gefunden!");
System.out.println();
System.out.println("Lokale Minima:");
anzahl = TeilAusgabe(-1);
if (anzahl == 0) System.out.println("--> Keine lokalen Minima gefunden!");
}
return this;
}
</code>
<run id="4d29dc2fc26ac">
Object ExtremwertSuche1 = ExtremwertSuche(-10, 10, 0.33);
ExtremwertSuche1.Ausgabe();
</run>
Zurück zur [[Einführungskurs/Binäre Suche|Binären Suche]].