Skip to content

Commit 514a8d7

Browse files
Create spot_brute_ackley_100d.ipynb
1 parent 8236439 commit 514a8d7

1 file changed

Lines changed: 323 additions & 0 deletions

File tree

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Brute Force: 100 Dimensions (Ackley Function)\n",
8+
"\n",
9+
"This notebook demonstrates how to use the `Spot` class from `spotpython` with and without the Nyström approximation for Kriging surrogates on the 100-dimensional Ackley function.\n",
10+
"\n",
11+
"We use a maximum of 500 function evaluations."
12+
]
13+
},
14+
{
15+
"cell_type": "code",
16+
"execution_count": 1,
17+
"metadata": {},
18+
"outputs": [
19+
{
20+
"name": "stdout",
21+
"output_type": "stream",
22+
"text": [
23+
"--- Expertenbericht: Multi-Start-Optimierung (100D Ackley) ---\n",
24+
"Dimension (D): 100\n",
25+
"Gesamtbudget (FEs): 500\n",
26+
"Lokaler Suchalgorithmus: 'Powell' (ableitungsfrei)\n",
27+
"---\n",
28+
"Strategische Budget-Allokation:\n",
29+
" Anzahl Starts (n): 25\n",
30+
" Budget pro Start (b): 20 FEs (lokale Suche)\n",
31+
" Erwartete Gesamt-FEs: 500\n",
32+
"---\n",
33+
"Starte Optimierungsläufe...\n",
34+
" Lauf 1/25 abgeschlossen. End-Wert: 21.1100 (Lokale FEs: 20/20)\n",
35+
" Lauf 2/25 abgeschlossen. End-Wert: 21.3363 (Lokale FEs: 20/20)\n",
36+
" Lauf 3/25 abgeschlossen. End-Wert: 21.3037 (Lokale FEs: 20/20)\n",
37+
" Lauf 4/25 abgeschlossen. End-Wert: 21.1079 (Lokale FEs: 20/20)\n",
38+
" Lauf 5/25 abgeschlossen. End-Wert: 21.1091 (Lokale FEs: 20/20)\n",
39+
" Lauf 6/25 abgeschlossen. End-Wert: 21.2609 (Lokale FEs: 20/20)\n",
40+
" Lauf 7/25 abgeschlossen. End-Wert: 21.2182 (Lokale FEs: 20/20)\n",
41+
" Lauf 8/25 abgeschlossen. End-Wert: 21.3431 (Lokale FEs: 20/20)\n",
42+
" Lauf 9/25 abgeschlossen. End-Wert: 21.2842 (Lokale FEs: 20/20)\n",
43+
" Lauf 10/25 abgeschlossen. End-Wert: 21.3092 (Lokale FEs: 20/20)\n",
44+
" Lauf 11/25 abgeschlossen. End-Wert: 21.1805 (Lokale FEs: 20/20)\n",
45+
" Lauf 12/25 abgeschlossen. End-Wert: 21.2944 (Lokale FEs: 20/20)\n",
46+
" Lauf 13/25 abgeschlossen. End-Wert: 21.2102 (Lokale FEs: 20/20)\n",
47+
" Lauf 14/25 abgeschlossen. End-Wert: 21.2913 (Lokale FEs: 20/20)\n",
48+
" Lauf 15/25 abgeschlossen. End-Wert: 21.3353 (Lokale FEs: 20/20)\n",
49+
" Lauf 16/25 abgeschlossen. End-Wert: 21.1844 (Lokale FEs: 20/20)\n",
50+
" Lauf 17/25 abgeschlossen. End-Wert: 21.2403 (Lokale FEs: 20/20)\n",
51+
" Lauf 18/25 abgeschlossen. End-Wert: 21.1968 (Lokale FEs: 20/20)\n",
52+
" Lauf 19/25 abgeschlossen. End-Wert: 21.0778 (Lokale FEs: 20/20)\n",
53+
" Lauf 20/25 abgeschlossen. End-Wert: 21.2517 (Lokale FEs: 20/20)\n",
54+
" Lauf 21/25 abgeschlossen. End-Wert: 21.2232 (Lokale FEs: 20/20)\n",
55+
" Lauf 22/25 abgeschlossen. End-Wert: 21.2731 (Lokale FEs: 20/20)\n",
56+
" Lauf 23/25 abgeschlossen. End-Wert: 21.4001 (Lokale FEs: 20/20)\n",
57+
" Lauf 24/25 abgeschlossen. End-Wert: 21.2894 (Lokale FEs: 20/20)\n",
58+
" Lauf 25/25 abgeschlossen. End-Wert: 21.2248 (Lokale FEs: 20/20)\n",
59+
"---\n",
60+
"Alle Optimierungsläufe abgeschlossen.\n",
61+
"Gesamtlaufzeit: 0.01 Sekunden\n",
62+
"Verbrauchtes Gesamtbudget: 500 / 500 FEs\n",
63+
"---\n",
64+
"\n",
65+
"--- Zusammenfassung der Ergebnisse ---\n",
66+
"Tabelle 1: Ergebnisse der Multi-Start-Optimierungsläufe\n",
67+
"======================================================================\n",
68+
"Lauf-ID | f(x_end) | Lokale FEs | Status\n",
69+
"----------------------------------------------------------------------\n",
70+
"0 | 21.1100 | 20 | Max FEs erreicht\n",
71+
"1 | 21.3363 | 20 | Max FEs erreicht\n",
72+
"2 | 21.3037 | 20 | Max FEs erreicht\n",
73+
"3 | 21.1079 | 20 | Max FEs erreicht\n",
74+
"4 | 21.1091 | 20 | Max FEs erreicht\n",
75+
"5 | 21.2609 | 20 | Max FEs erreicht\n",
76+
"6 | 21.2182 | 20 | Max FEs erreicht\n",
77+
"7 | 21.3431 | 20 | Max FEs erreicht\n",
78+
"8 | 21.2842 | 20 | Max FEs erreicht\n",
79+
"9 | 21.3092 | 20 | Max FEs erreicht\n",
80+
"10 | 21.1805 | 20 | Max FEs erreicht\n",
81+
"11 | 21.2944 | 20 | Max FEs erreicht\n",
82+
"12 | 21.2102 | 20 | Max FEs erreicht\n",
83+
"13 | 21.2913 | 20 | Max FEs erreicht\n",
84+
"14 | 21.3353 | 20 | Max FEs erreicht\n",
85+
"15 | 21.1844 | 20 | Max FEs erreicht\n",
86+
"16 | 21.2403 | 20 | Max FEs erreicht\n",
87+
"17 | 21.1968 | 20 | Max FEs erreicht\n",
88+
"18 | 21.0778 | 20 | Max FEs erreicht\n",
89+
"19 | 21.2517 | 20 | Max FEs erreicht\n",
90+
"20 | 21.2232 | 20 | Max FEs erreicht\n",
91+
"21 | 21.2731 | 20 | Max FEs erreicht\n",
92+
"22 | 21.4001 | 20 | Max FEs erreicht\n",
93+
"23 | 21.2894 | 20 | Max FEs erreicht\n",
94+
"24 | 21.2248 | 20 | Max FEs erreicht\n",
95+
"======================================================================\n",
96+
"\n",
97+
"--- Bestes gefundenes Minimum ---\n",
98+
"Bester Lauf (ID): 18\n",
99+
"Bester Funktionswert: 21.07782929\n",
100+
" (Globales Optimum ist: 0.0)\n",
101+
" Bester Vektor (x*): [-0.00, -0.00, -23.92, 12.68, 11.45, ...]\n"
102+
]
103+
}
104+
],
105+
"source": [
106+
"import numpy as np\n",
107+
"from scipy.optimize import minimize\n",
108+
"import time\n",
109+
"import warnings\n",
110+
"\n",
111+
"# ---\n",
112+
"# 1. Definition der Zielfunktion: 100D Ackley\n",
113+
"# ---\n",
114+
"# Basierend auf der Standarddefinition [1, 2, 3]\n",
115+
"# Globales Optimum: f(x*) = 0 bei x* = [0,..., 0]\n",
116+
"# ---\n",
117+
"\n",
118+
"def ackley(x):\n",
119+
" \"\"\"\n",
120+
" Berechnet die n-dimensionale Ackley-Funktion.\n",
121+
" Parameter a=20, b=0.2, c=2*pi werden standardmäßig verwendet.\n",
122+
" \"\"\"\n",
123+
" a = 20.0\n",
124+
" b = 0.2\n",
125+
" c = 2.0 * np.pi\n",
126+
" \n",
127+
" # Dimension aus dem Input-Vektor ableiten\n",
128+
" d = len(x) \n",
129+
" \n",
130+
" # Berechne die beiden Terme der Funktion\n",
131+
" sum_sq_term = -b * np.sqrt(np.sum(x**2) / d)\n",
132+
" cos_term = np.sum(np.cos(c * x)) / d\n",
133+
" \n",
134+
" # Kombiniere die Terme\n",
135+
" result = -a * np.exp(sum_sq_term) - np.exp(cos_term) + a + np.e\n",
136+
" \n",
137+
" return result\n",
138+
"\n",
139+
"# ---\n",
140+
"# 2. Definition der globalen Parameter und der Budget-Allokation\n",
141+
"# ---\n",
142+
"\n",
143+
"# Problem-Dimension\n",
144+
"DIMENSIONS = 100\n",
145+
"\n",
146+
"# Suchraum-Grenzen \n",
147+
"BOUND_LOW = -32.768\n",
148+
"BOUND_HIGH = 32.768\n",
149+
"\n",
150+
"# Globales Budget für Funktionsauswertungen\n",
151+
"BUDGET_TOTAL = 500\n",
152+
"\n",
153+
"# ---\n",
154+
"# 3. Strategische Bestimmung von n (Anzahl Starts) und b (Budget pro Lauf)\n",
155+
"# ---\n",
156+
"# Wie in Abschnitt 2 des Berichts hergeleitet:\n",
157+
"# Wir wählen n=10, um eine minimale Exploration zu gewährleisten.\n",
158+
"# Dies lässt b=50 FEs pro lokaler Suche (inkl. Start-FE).\n",
159+
"# n * b = 10 * 50 = 500.\n",
160+
"# ---\n",
161+
"\n",
162+
"N_STARTS = 25\n",
163+
"BUDGET_PER_RUN = BUDGET_TOTAL // N_STARTS # Ergibt 50\n",
164+
"\n",
165+
"# ---\n",
166+
"# 4. Haupt-Optimierungsfunktion\n",
167+
"# ---\n",
168+
"\n",
169+
"def run_multi_start_optimization():\n",
170+
" \"\"\"\n",
171+
" Führt die Multi-Start-Optimierung mit dem Powell-Verfahren durch.\n",
172+
" \"\"\"\n",
173+
" print(\"--- Expertenbericht: Multi-Start-Optimierung (100D Ackley) ---\")\n",
174+
" print(f\"Dimension (D): {DIMENSIONS}\")\n",
175+
" print(f\"Gesamtbudget (FEs): {BUDGET_TOTAL}\")\n",
176+
" print(f\"Lokaler Suchalgorithmus: 'Powell' (ableitungsfrei)\")\n",
177+
" print(\"---\")\n",
178+
" print(f\"Strategische Budget-Allokation:\")\n",
179+
" print(f\" Anzahl Starts (n): {N_STARTS}\")\n",
180+
" print(f\" Budget pro Start (b): {BUDGET_PER_RUN} FEs (lokale Suche)\")\n",
181+
" print(f\" Erwartete Gesamt-FEs: {N_STARTS * BUDGET_PER_RUN}\")\n",
182+
" print(\"---\")\n",
183+
" \n",
184+
" start_time = time.time()\n",
185+
" \n",
186+
" # Für Reproduzierbarkeit\n",
187+
" rng = np.random.default_rng(seed=42)\n",
188+
" \n",
189+
" # Generiere n Startpunkte [13, 14]\n",
190+
" # Shape: (N_STARTS, DIMENSIONS)\n",
191+
" start_points = rng.uniform(BOUND_LOW, BOUND_HIGH, size=(N_STARTS, DIMENSIONS))\n",
192+
" \n",
193+
" # Definiere die Bounds für scipy.optimize.minimize [4, 10]\n",
194+
" # Powell unterstützt 'bounds'\n",
195+
" # bounds = * DIMENSIONS\n",
196+
" bounds = [(BOUND_LOW, BOUND_HIGH)] * DIMENSIONS\n",
197+
" \n",
198+
" # Optionen für den Powell-Minimierer \n",
199+
" # Wir setzen maxfev auf unser berechnetes lokales Budget b.\n",
200+
" powell_options = {\n",
201+
" 'maxfev': BUDGET_PER_RUN,\n",
202+
" 'disp': False # Ausgabe pro Lauf unterdrücken\n",
203+
" }\n",
204+
" \n",
205+
" # Speichern der Ergebnisse\n",
206+
" all_results = []\n",
207+
" total_fevals_used = 0\n",
208+
" \n",
209+
" print(\"Starte Optimierungsläufe...\")\n",
210+
" \n",
211+
" # Unterdrücke Warnungen von SciPy, falls maxfev erreicht wird\n",
212+
" warnings.filterwarnings(\"ignore\", message=\".*Maximum number of function evaluations.*\")\n",
213+
" \n",
214+
" # --- Die Hauptschleife ---\n",
215+
" for i in range(N_STARTS):\n",
216+
" x0 = start_points[i]\n",
217+
" \n",
218+
" # Starte die lokale Suche\n",
219+
" # Die erste Auswertung (f(x0)) wird von minimize durchgeführt\n",
220+
" # und zählt zum Budget 'maxfev'.\n",
221+
" result = minimize(\n",
222+
" fun=ackley,\n",
223+
" x0=x0,\n",
224+
" method='Powell',\n",
225+
" bounds=bounds,\n",
226+
" options=powell_options\n",
227+
" )\n",
228+
" \n",
229+
" # Speichere relevante Daten\n",
230+
" all_results.append({\n",
231+
" 'run_id': i,\n",
232+
" 'f_start': ackley(x0) if result.nfev == 0 else np.nan, # Fallback\n",
233+
" 'f_end': result.fun,\n",
234+
" 'nfev_local': result.nfev, # FEs, die minimize genutzt hat\n",
235+
" 'success': result.success,\n",
236+
" 'message': result.message,\n",
237+
" 'best_x': result.x\n",
238+
" })\n",
239+
" \n",
240+
" total_fevals_used += result.nfev\n",
241+
" \n",
242+
" # Der Startwert f(x0) ist die erste Auswertung.\n",
243+
" # Wir müssen ihn separat holen, falls minimize ihn nicht liefert (sollte es aber)\n",
244+
" # Für das Reporting holen wir den Startwert:\n",
245+
" f_start_val = all_results[i]['f_start']\n",
246+
" if np.isnan(f_start_val) and result.nfev > 0:\n",
247+
" # Normalerweise nicht nötig, aber zur Sicherheit\n",
248+
" f_start_val = ackley(x0)\n",
249+
" # Diese FE ist bereits in result.nfev enthalten\n",
250+
" \n",
251+
" print(f\" Lauf {i+1}/{N_STARTS} abgeschlossen. \"\n",
252+
" f\"End-Wert: {result.fun:.4f} \"\n",
253+
" f\"(Lokale FEs: {result.nfev}/{BUDGET_PER_RUN})\")\n",
254+
" \n",
255+
" end_time = time.time()\n",
256+
" \n",
257+
" # ---\n",
258+
" # 5. Ergebnisanalyse und Zusammenfassung\n",
259+
" # ---\n",
260+
" print(\"---\")\n",
261+
" print(\"Alle Optimierungsläufe abgeschlossen.\")\n",
262+
" print(f\"Gesamtlaufzeit: {end_time - start_time:.2f} Sekunden\")\n",
263+
" print(f\"Verbrauchtes Gesamtbudget: {total_fevals_used} / {BUDGET_TOTAL} FEs\")\n",
264+
" print(\"---\")\n",
265+
" \n",
266+
" # Finde das beste Ergebnis über alle Läufe\n",
267+
" best_run = min(all_results, key=lambda r: r['f_end'])\n",
268+
" \n",
269+
" print(\"\\n--- Zusammenfassung der Ergebnisse ---\")\n",
270+
" \n",
271+
" # Erzeuge die Ergebnistabelle\n",
272+
" print(\"Tabelle 1: Ergebnisse der Multi-Start-Optimierungsläufe\")\n",
273+
" print(\"=\" * 70)\n",
274+
" print(f\"{'Lauf-ID':<8} | {'f(x_end)':<12} | {'Lokale FEs':<10} | {'Status'}\")\n",
275+
" print(\"-\" * 70)\n",
276+
" for res in all_results:\n",
277+
" # Status-Nachricht kürzen\n",
278+
" status = \"Max FEs erreicht\" if \"function evaluations\" in res['message'] else \"Andere\"\n",
279+
" if res['success']: status = \"Konvergiert\"\n",
280+
" \n",
281+
" print(f\"{res['run_id']:<8} | {res['f_end']:<12.4f} | {res['nfev_local']:<10} | {status}\")\n",
282+
" print(\"=\" * 70)\n",
283+
" \n",
284+
" print(\"\\n--- Bestes gefundenes Minimum ---\")\n",
285+
" print(f\"Bester Lauf (ID): {best_run['run_id']}\")\n",
286+
" print(f\"Bester Funktionswert: {best_run['f_end']:.8f}\")\n",
287+
" print(f\" (Globales Optimum ist: 0.0)\")\n",
288+
" # Zeige die ersten 5 von 100 Dimensionen des besten Vektors\n",
289+
" x_best = best_run['best_x']\n",
290+
" print(f\" Bester Vektor (x*): [{x_best[0]:.2f}, {x_best[1]:.2f}, {x_best[2]:.2f}, {x_best[3]:.2f}, {x_best[4]:.2f}, ...]\")\n",
291+
" \n",
292+
" return best_run\n",
293+
"\n",
294+
"# ---\n",
295+
"# 6. Skriptausführung\n",
296+
"# ---\n",
297+
"if __name__ == \"__main__\":\n",
298+
" best_result = run_multi_start_optimization()"
299+
]
300+
}
301+
],
302+
"metadata": {
303+
"kernelspec": {
304+
"display_name": "spot313",
305+
"language": "python",
306+
"name": "python3"
307+
},
308+
"language_info": {
309+
"codemirror_mode": {
310+
"name": "ipython",
311+
"version": 3
312+
},
313+
"file_extension": ".py",
314+
"mimetype": "text/x-python",
315+
"name": "python",
316+
"nbconvert_exporter": "python",
317+
"pygments_lexer": "ipython3",
318+
"version": "3.13.7"
319+
}
320+
},
321+
"nbformat": 4,
322+
"nbformat_minor": 2
323+
}

0 commit comments

Comments
 (0)