
Archery-Algorithmus (AA)
Inhalt
Einführung
In einer Zeit, in der die Aufgaben immer komplexer und die Ressourcen immer knapper werden, wird die Optimierung nicht nur zu einer Notwendigkeit, sondern auch zu einer echten algorithmischen Kunst in der modernen Welt. Wie findet man die beste Lösung unter vielen möglichen? Wie lassen sich Kosten minimieren, die Effizienz steigern und maximale Gewinne erzielen? Diese Fragen betreffen Fachleute aus den verschiedensten Bereichen - von der Wirtschaft bis zum Ingenieurwesen, von sozialen Systemen bis zur Ökologie. Vor der Lösung eines Optimierungsproblems ist es wichtig, das Problem richtig zu modellieren, indem Schlüsselvariablen und mathematische Beziehungen ermittelt werden, die die Realität adäquat wiedergeben. Die Optimierung ist im Finanzwesen und im Handel weit verbreitet und hilft nicht nur bei der Entwicklung neuer Anlagestrategien, sondern auch bei der Verbesserung bestehender Strategien. Trotz der Universalität der Ansätze lassen sich die Optimierungsmethoden jedoch bedingt in zwei Kategorien einteilen: deterministisch und stochastisch.
Deterministische Methoden wie der Gradientenabstieg bieten strenge und vorhersehbare Lösungen, indem sie mathematische Ableitungen verwenden, um das Optimum zu finden, wodurch sie verschiedene Szenarien effektiv modellieren können. Sobald die Probleme jedoch nichtlinear oder multivariat werden, kann ihre Effektivität drastisch abnehmen. In solchen Fällen kommen stochastische Methoden zum Einsatz, die auf der Grundlage von Zufallsprozessen in der Lage sind, unter komplexen Bedingungen akzeptable Lösungen zu finden, was sie besonders auf volatilen Märkten nützlich macht.Kombinationen von deterministischen und stochastischen Methoden spielen in modernen Optimierungsansätzen eine zentrale Rolle. Durch die Kombination dieser beiden Ansätze können Analysten flexiblere und anpassungsfähigere Modelle erstellen, die sowohl stabile als auch sich ändernde Bedingungen berücksichtigen können. Dadurch lässt sich nicht nur die Qualität der Prognosen verbessern, sondern auch das Risiko minimieren, was für ein erfolgreiches Investitionsmanagement entscheidend ist.
In diesem Artikel werde ich einen neuen Ansatz zur Lösung von Optimierungsproblemen vorstellen - den Archery Algorithm (AA). Der Algorithmus wurde von Fatemeh Ahmadi Zeidabadi und Kollegen entwickelt und im Februar 2022 veröffentlicht. Diese vom Bogenschießen inspirierte Methode erzeugt quasi-optimale Lösungen, indem sie die Position der Populationsmitglieder im Suchraum auf der Grundlage eines zufällig ausgewählten Elements aktualisiert. Wir werden die Effizienz von AA bei Standard-Zielfunktionen testen und die erzielten Ergebnisse mit uns bereits bekannten Algorithmen vergleichen. Indem wir in die Details eintauchen, werden wir zeigen, wie dieser innovative Ansatz die Art und Weise, wie wir über Optimierung denken, verändern und neue Horizonte für die Lösung komplexer Probleme eröffnen kann.
Implementierung des Algorithmus
Der Archery Algorithm (AA) ist eine völlig neue stochastische Optimierungsmethode, die entwickelt wurde, um optimale Lösungen für Optimierungsprobleme zu finden, und die durch das Verhalten eines Bogenschützen inspiriert wurde, der auf ein Ziel zielt. AA simuliert das Schießen von Pfeilen auf ein Ziel. Jedes Mitglied der Population stellt eine potenzielle Lösung für das Optimierungsproblem dar, und ihre Positionen im Suchraum werden auf der Grundlage der Leistung eines zufällig ausgewählten „Ziel“-Mitglieds aktualisiert, ähnlich wie Bogenschützen ihr Ziel anpassen, je nachdem, wo sie treffen wollen.
Die Grundgesamtheit wird als Matrix dargestellt, wobei jede Zeile einem Mitglied (Lösung) und jede Spalte einer Dimension des Problems entspricht. Dies ermöglicht eine strukturierte Bewertung und Aktualisierung von Entscheidungen auf der Grundlage ihrer Zielfunktionswerte. Die Leistung der einzelnen Mitglieder wird anhand einer Zielfunktion bewertet, die angibt, wie gut eine gefundene Lösung ist. Die Ergebnisse werden in einem Vektor gespeichert, der es dem Algorithmus ermöglicht, die Effizienz der verschiedenen Lösungen zu vergleichen.
Das Ziel ist in Abschnitte unterteilt, deren Breite der Produktivität der Bevölkerungsmitglieder entspricht. Eine Wahrscheinlichkeitsfunktion wird berechnet, um die Wahrscheinlichkeit zu bestimmen, mit der jedes Mitglied auf der Grundlage seines Zielfunktionswertes ausgewählt wird, wobei effizientere Bogenschützen eine höhere Wahrscheinlichkeit haben, ausgewählt zu werden. Ein Mitglied der Population wird nach dem Zufallsprinzip auf der Grundlage der kumulativen Wahrscheinlichkeit ausgewählt, was die Zielauswahl eines Bogenschützen simuliert. Diese Entscheidung wirkt sich darauf aus, wie die Positionen der anderen Mitglieder aktualisiert werden. Der Algorithmus aktualisiert die Position der einzelnen Bogenschützen im Suchraum anhand bestimmter Gleichungen. Die Aktualisierung hängt davon ab, ob der ausgewählte Bogenschütze einen besseren oder schlechteren Zielfunktionswert hat als der aktuelle. Bei diesem Verfahren wird der Suchraum nach dem Zufallsprinzip erkundet. AA arbeitet iterativ und aktualisiert die Population, bis eine Stopp-Bedingung (maximale Anzahl von Iterationen) erreicht ist. Während dieses Prozesses verfolgt der Algorithmus die beste gefundene Lösung.
Die ursprüngliche Version des oben vorgestellten AA-Algorithmus beschreibt die Matrix als eine Population und die Vektoren als Mitglieder der Population. Im Text werden jedoch keine spezifischen Operationen angegeben, die für die Arbeit mit Matrizen typisch sind. Tatsächlich beinhaltet der Algorithmus Standardaktionen mit Suchagenten, wie bei den meisten der zuvor diskutierten Algorithmen.
Die Formulierung „die Zielscheibe ist in Abschnitte unterteilt, deren Breite der Produktivität der Populationsmitglieder entspricht“ impliziert die Anwendung einer Roulette-Methode für die Auswahl. In diesem Fall ist die Wahrscheinlichkeit, einen Sektor zu wählen, proportional zu seiner Breite.
Auf diese Weise können komplexe Formulierungen, die viele Konzepte beschreiben, auf viel einfachere Weise erklärt werden, was die Umsetzung der Idee vereinfacht.
Der Bogenschießalgorithmus „Archery“ ist also eine populationsbasierte Optimierungsmethode, die die Prinzipien des Zielschießens nutzt, um die Suche nach optimalen Lösungen zu leiten. Es kombiniert Elemente des Zufalls mit der Normalverteilung, um den Suchraum zu erkunden und auszunutzen. Schlüsselkomponenten des Algorithmus:
1. Eine Population von Agenten (Bogenschützen)
2. Ein Vektor der Wahrscheinlichkeiten und kumulativen Wahrscheinlichkeiten
3. Ein Vererbungsmechanismus (in der ursprünglichen Version nicht vorhanden)
4. Ein Mechanismus zur Aktualisierung der Position
5. Parameter Trainingsintensität (I)
Lassen Sie uns zunächst den Pseudocode des Algorithmus vorstellen:
Initialisierung:
Erstellen einer Population von popSize Agenten
Für jeden Agenten:
Initialisierung einer zufälligen Position innerhalb des Suchbereichs
Initialisierung der vorherigen Position und Fitness
Hauptschleife:
Bis zum Erreichen der Stopp-Bedingung:
Für jeden Agenten i in der Population:
Berechnen Sie den Vektor der Wahrscheinlichkeiten P und die kumulativen Wahrscheinlichkeiten C
Für jede Koordinate c:
Auswahl von k Bogenschützen mit kumulativer Wahrscheinlichkeit
Wenn (random_number < inheritance_probability):
new_position [c] = k_archer_position [c]
Andernfalls:
I = rounding (1 + random_number_from_0_to_1) // Parameter für die Trainingsintensität
random_gaussian = generate_gaussian_number (mean = 0, min =-1, max = 1)
Wenn (k_archer_fitness > i_agent_fitness):
new_position [c] = previous_position [c] + random_gaussian * (k_archer_position [c] - I * previous_position [c])
Andernfalls:
new_position [c] = previous_position [c] + random_gaussian * (previous_position [c] - I * k_archer_position [c])
Begrenzung von new_position [c] innerhalb des Suchbereichs
Aktualisierung der Position des Agenten i
Bewerten der Fitness aller Agenten
Aktualisierung der besten Gesamtlösung
Für jeden Agenten:
Wenn die neue Fitness besser ist als die vorherige:
Aktualisieren der vorherige Position und Fitness
Rückgabe der besten gefundenen Lösung
Implementierungsmerkmale im Code:
1. Der Algorithmus verwendet einen probabilistischen Ansatz, um die Bogenschützen auszuwählen, von denen er lernen soll.
2. Der Vererbungsmechanismus ermöglicht es den Agenten, die Positionen erfolgreicher Bogenschützen mit einer gewissen Wahrscheinlichkeit direkt zu kopieren.
3. Bei der Aktualisierung der Positionen wird eine Gauß-Verteilung verwendet, um Zufälligkeit in den Lernprozess der Bogenschützen zu bringen.
4. Der Algorithmus speichert die vorherigen besten Positionen der Agenten, sodass er ein gewisses „Gedächtnis“ für gute Entscheidungen hat.
5. Die Implementierung wird einen Mechanismus zur Begrenzung neuer Positionen innerhalb des zulässigen Suchbereichs umfassen.
6. Der von den Autoren beschriebene Parameter der Trainingsintensität (I) wird verwendet, um den Grad des Einflusses der aktuellen Position auf die neue Position zu regulieren.
Der Parameter I (Trainingsintensität) ist eine Zufallsvariable, die den Wert 1 oder 2 annehmen kann. Sie ist wie folgt definiert: I = Rundung auf die nächste ganze Zahl (1 + zufällig erzeugte Zahl von 0 bis 1). Das bedeutet, dass I mit einer Wahrscheinlichkeit von 0,5 gleich 1 und mit derselben Wahrscheinlichkeit gleich 2 sein wird. Die Rolle des Parameters I im Algorithmus:
1. Wenn I = 1 ist, nimmt der Algorithmus kleinere Positionsanpassungen vor.
2. Wenn I = 2 ist, kann der Algorithmus drastischere Änderungen an einer Position vornehmen.
Kommen wir nun zum Algorithmus selbst. Beschreibung der Struktur des Bogenschützen, S_AA_Agent. Sie repräsentiert einen Agenten in einem Optimierungsalgorithmus mit einem Satz von Koordinaten im Lösungsraum und enthält Informationen über seine Effizienz in Form der Fitnessfunktion.
- cPrev [] - das Array speichert die vorherigen Koordinaten des Agenten.
- fPrev - die Variable speichert den vorherigen Wert der Agentenfitness.
Die Methode Init ermöglicht es uns, den Agenten auf die Arbeit vorzubereiten, indem wir Anfangswerte für seine Koordinaten und seine Fitness festlegen. Anschließend wird der Wert fPrev auf den kleinstmöglichen Wert für den Typ „double“ gesetzt, da die Fitness noch nicht berechnet wurde.
//—————————————————————————————————————————————————————————————————————————————— struct S_AA_Agent { double cPrev []; // previous coordinates double fPrev; // previous fitness void Init (int coords) { ArrayResize (cPrev, coords); fPrev = -DBL_MAX; } }; //——————————————————————————————————————————————————————————————————————————————
Werfen wir einen Blick auf die Klasse C_AO_AAm, die den Algorithmus selbst implementiert und von der Klasse C_AO abgeleitet wird.
- popSize - Größe der Population.
- inhProbab - Wahrscheinlichkeit, ein Merkmal von einem anderen Bogenschützen zu erben.
Dann wird das Array params mit der Größe 2 initialisiert, in dem die Parameter des Algorithmus gespeichert werden: Populationsgröße und Vererbungswahrscheinlichkeit.
- SetParams - Methode setzt die Parameter basierend auf den im Array params gespeicherten Werten. Es extrahiert Werte für popSize und inhProbab und wandelt sie in die entsprechenden Typen um.
- Init - die Methode initialisiert den Algorithmus, indem sie die minimalen und maximalen Suchgrenzen, den Suchschritt und die Anzahl der Epochen übernimmt.
- Moving und Revision - die Methoden sind für die Logik der Verschiebung von Agenten im Lösungsraum und deren Revision (Aktualisierung) verantwortlich.
S_AA_Agent agent [] - Array von Agenten, die zur Durchführung der Optimierung verwendet werden sollen.
Die Klasse C_AO_AAm implementiert den Optimierungsalgorithmus, während SetParams, Init, Moving und Revision die Konfiguration und das Verhalten des Algorithmus während seines Betriebs verwalten.
//—————————————————————————————————————————————————————————————————————————————— class C_AO_AAm : public C_AO { public: //-------------------------------------------------------------------- ~C_AO_AAm () { } C_AO_AAm () { ao_name = "AAm"; ao_desc = "Archery Algorithm M"; ao_link = "https://www.mql5.com/en/articles/15782"; popSize = 50; // population size inhProbab = 0.3; ArrayResize (params, 2); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "inhProbab"; params [1].val = inhProbab; } void SetParams () { popSize = (int)params [0].val; inhProbab = params [1].val; } bool Init (const double &rangeMinP [], // minimum search range const double &rangeMaxP [], // maximum search range const double &rangeStepP [], // step search const int epochsP = 0); // number of epochs void Moving (); void Revision (); //---------------------------------------------------------------------------- double inhProbab; //probability of inheritance S_AA_Agent agent []; private: //------------------------------------------------------------------- }; //——————————————————————————————————————————————————————————————————————————————
Die Methode Init in der Klasse C_AO_AAm ist für die Initialisierung des Optimierungsalgorithmus zuständig. Sie benötigt vier Parameter: Arrays für die minimalen und maximalen Suchgrenzen, den Suchschritt und die Anzahl der Epochen, die standardmäßig gleich Null sind.
- Wenn die Standardinitialisierung erfolgreich ist, ändert die Methode die Größe des Agenten, sodass er der angegebenen Populationsgröße popSize entspricht. So können wir die erforderliche Anzahl von Agenten für den Algorithmus erstellen.
- In der for-Schleife wird jeder Agent aus dem Array mit der Init-Methode initialisiert, die die Anfangskoordinaten für jeden Agenten angibt.
Am Ende gibt die Methode „true“ zurück, was den erfolgreichen Abschluss der Algorithmusinitialisierung anzeigt. Die Init-Methode stellt also sicher, dass der Algorithmus für den Betrieb vorbereitet ist, indem er die notwendigen Parameter einstellt und Agenten erstellt, die an der Optimierung teilnehmen werden.
//—————————————————————————————————————————————————————————————————————————————— bool C_AO_AAm::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //---------------------------------------------------------------------------- ArrayResize (agent, popSize); for (int i = 0; i < popSize; i++) agent [i].Init (coords); return true; } //——————————————————————————————————————————————————————————————————————————————
Die Methode Moving in der Klasse C_AO_AAm ist für die Bewegung der Agenten im Lösungsraum auf der Grundlage ihrer aktuellen Positionen und der Werte der Funktion, die sie optimieren, verantwortlich. Zerlegen wir sie in Teile:
- Wird die Methode zum ersten Mal aufgerufen (Revision ist false), dann wird für jeden Agenten und jede Koordinate ein Zufallswert innerhalb der angegebenen Grenzen von rangeMin und rangeMax initialisiert.
- Anschließend wird dieser Wert mit der Methode SeInDiSp angepasst, die sicherstellt, dass der Wert mit der angegebenen Stufe übereinstimmt.
Danach wird dem Flag für Revision true zugwiesen und die Methode beendet ihre Arbeit.
- Als nächstes werden zwei Arrays erstellt: P für Wahrscheinlichkeiten und C für kumulative Wahrscheinlichkeiten.
- Der schlechteste Wert der Funktion F_worst wird ermittelt, um die Werte der Fitnessfunktion für die Agenten zu normalisieren.
- Die Wahrscheinlichkeiten für jeden Agenten werden dann berechnet und normalisiert, sodass sie in der Summe 1 ergeben.
- Die kumulativen Wahrscheinlichkeiten C werden auf der Grundlage der Wahrscheinlichkeiten P berechnet.
- Für jeden Agenten und jede Koordinate wird ein Partnerbogenschütze (ein Agent) auf der Grundlage der kumulativen Wahrscheinlichkeit ausgewählt.
- Ist der Zufallswert kleiner als die angegebene Vererbungswahrscheinlichkeit inhProbab, nimmt der Agent die Koordinate des ausgewählten Agenten an (wodurch die Vererbung der Merkmale mit einer bestimmten Wahrscheinlichkeit gewährleistet ist).
- Andernfalls aktualisiert der Agent seine Position auf der Grundlage einer Gleichung, die die aktuelle Position, den Zufallswert und die Position des Partnerschützen berücksichtigt.
- Schließlich wird der neue Koordinatenwert auch mit der Methode SeInDiSp angepasst.
Die Methode Moving implementiert die Bewegung von Agenten im Lösungsraum unter Berücksichtigung ihrer aktuellen Positionen und Funktionswerte und verwendet probabilistische Methoden, um Bewegungsrichtungen auszuwählen und Positionen zu aktualisieren.
//—————————————————————————————————————————————————————————————————————————————— void C_AO_AAm::Moving () { //---------------------------------------------------------------------------- if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } //------------------------------------------------------------------------- // Calculate probability vector P and cumulative probability C double P [], C []; ArrayResize (P, popSize); ArrayResize (C, popSize); double F_worst = DBL_MAX; double sum = 0; for (int i = 0; i < popSize; i++) { if (a [i].f < F_worst) F_worst = a [i].f; } for (int i = 0; i < popSize; i++) { P [i] = a [i].f - F_worst; sum += P [i]; } for (int i = 0; i < popSize; i++) { P [i] /= sum; C [i] = (i == 0) ? P [i] : C [i - 1] + P [i]; } double x; for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { // Select archer (k) using cumulative probability int k = 0; double r = u.RNDprobab (); while (k < popSize - 1 && C [k] < r) k++; if (u.RNDbool () < inhProbab) { x = a [k].c [c]; } else { // Update position using Eq. (5) and (6) double I = MathRound (1 + u.RNDprobab ()); double rnd = u.GaussDistribution (0, -1, 1, 8); if (a [k].f > a [i].f) { x = agent [i].cPrev [c] + rnd * (a [k].c [c] - I * agent [i].cPrev [c]); } else { x = agent [i].cPrev [c] + rnd * (agent [i].cPrev [c] - I * a [k].c [c]); } } a [i].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]); } } } //——————————————————————————————————————————————————————————————————————————————
Die Methode Revision in der Klasse C_AO_AAm ist für die Aktualisierung der Informationen über die besten Agenten in der Population zuständig. Die Methode geht folgendermaßen vor:
- Die Variable ind wird mit dem Wert -1 initialisiert. Sie wird verwendet, um den Index des Agenten mit dem besten Funktionswert zu speichern.
- Die for-Schleife durchläuft alle Agenten in der Population popSize und prüft, ob der Wert der aktuellen Agentenfunktion a [i].f den aktuell besten Wert der Funktion fB übersteigt:
- fB wird auf den neuen besseren Wert von a [i].f aktualisiert.
- wird der Index dieses Bearbeiters in der Variablen ind gespeichert.
- Wenn der Wert der aktuellen Agentenfunktion a [i].f den Wert der vorherigen des Agenten [i].fPrev übersteigt:
- wird der vorherige Wert von fPrev für den Agenten aktualisiert.
- werden die aktuellen Koordinaten des Agenten mittels ArrayCopy in das Array cPrev kopiert.
Die Methode Revision dient der Aktualisierung der Informationen über die beste globale Lösung sowie der Aktualisierung der besten Positionen der Agenten.
//—————————————————————————————————————————————————————————————————————————————— void C_AO_AAm::Revision () { //---------------------------------------------------------------------------- int ind = -1; for (int i = 0; i < popSize; i++) { if (a [i].f > fB) { fB = a [i].f; ind = i; } } if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY); //---------------------------------------------------------------------------- for (int i = 0; i < popSize; i++) { if (a [i].f > agent [i].fPrev) { agent [i].fPrev = a [i].f; ArrayCopy (agent [i].cPrev, a [i].c, 0, 0, WHOLE_ARRAY); } } } //——————————————————————————————————————————————————————————————————————————————
Testergebnisse
Ich habe den Algorithmus leicht verändert. Der ursprüngliche Algorithmus sieht keinen direkten Informationsaustausch zwischen Bogenschützen vor. Der Austausch erfolgt indirekt durch die Interaktion der Koordinaten über die Normalverteilung, sodass ich es für notwendig hielt, den Austausch solcher Informationen hinzuzufügen. Zu diesem Zweck habe ich den zusätzlichen Algorithmus inhProbab hinzugefügt, der dafür zuständig ist, einen solchen Austausch mit einer bestimmten Wahrscheinlichkeit durchzuführen.
if (u.RNDbool () < inhProbab)
{
x = a [k].c [c];
}
Die im Folgenden dargestellten Ergebnisse entsprechen der ursprünglichen Version des Algorithmus, wie sie von den Autoren beabsichtigt war.
AA|Archery Algorithm|50.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.6699547926310098
25 Hilly's; Func runs: 10000; result: 0.37356238340164605
500 Hilly's; Func runs: 10000; result: 0.257542163368952
=============================
5 Forest's; Func runs: 10000; result: 0.38166669771790607
25 Forest's; Func runs: 10000; result: 0.199300365268835
500 Forest's; Func runs: 10000; result: 0.15337954055780398
=============================
5 Megacity's; Func runs: 10000; result: 0.4076923076923077
25 Megacity's; Func runs: 10000; result: 0.17907692307692308
500 Megacity's; Func runs: 10000; result: 0.10004615384615476
=============================
All score: 2.72222 (30.25%)
Der Algorithmus erreicht im Test 30,25 %, aber mit meiner Änderung verbesserte er seine Leistung um mehr als 13 %. Nachstehend sind die Ergebnisse der geänderten Version aufgeführt:
AAm|Archery Algorithm M|50.0|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.9353194829441194
25 Hilly's; Func runs: 10000; result: 0.6798262991897616
500 Hilly's; Func runs: 10000; result: 0.2596620178276653
=============================
5 Forest's; Func runs: 10000; result: 0.5735062785421186
25 Forest's; Func runs: 10000; result: 0.22007188891556378
500 Forest's; Func runs: 10000; result: 0.1486980566819649
=============================
5 Megacity's; Func runs: 10000; result: 0.6307692307692309
25 Megacity's; Func runs: 10000; result: 0.344
500 Megacity's; Func runs: 10000; result: 0.10193846153846249
=============================
All score: 3.89379 (43.26%)
Ich habe also den geänderten Algorithmus ausgewählt und in die Bewertungstabelle aufgenommen. Unten sehen Sie die Visualisierung des Algorithmus. Ich denke, sie ist recht gut. Natürlich gibt es eine Streuung der Ergebnisse, die jedoch nicht kritisch ist und nur bei Funktionen mit einer kleinen Anzahl von Koordinaten auftritt.
AAm mit der Testfunktion Hilly
AAm mit der Testfunktion Forest
AAm mit der Testfunktion Megacity
Nach den Betriebsergebnissen belegt die modifizierte Version des Algorithmus den 26.
# | AO | Beschreibung | Hilly | Hilly final | Forest | Forest final | Megacity (discrete) | Megacity final | Final result | % of MAX | ||||||
10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | ||||||||
1 | ANS | Suche über die gesamte Nachbarschaft | 0.94948 | 0.84776 | 0.43857 | 2.23581 | 1.00000 | 0.92334 | 0.39988 | 2.32323 | 0.70923 | 0.63477 | 0.23091 | 1.57491 | 6.134 | 68.15 |
2 | CLA | Сode Lock Algorithmus | 0.95345 | 0.87107 | 0.37590 | 2.20042 | 0.98942 | 0.91709 | 0.31642 | 2.22294 | 0.79692 | 0.69385 | 0.19303 | 1.68380 | 6.107 | 67.86 |
3 | AMOm | Optimierung der Tiermigration M | 0,90358 | 0,84317 | 0,46284 | 2,20959 | 0,99001 | 0,92436 | 0,46598 | 2,38034 | 0,56769 | 0,59132 | 0,23773 | 1,39675 | 5.987 | 66,52 |
4 | (P+O)ES | (P+O) Entwicklungsstrategien | 0.92256 | 0.88101 | 0.40021 | 2.20379 | 0.97750 | 0.87490 | 0.31945 | 2.17185 | 0.67385 | 0.62985 | 0.18634 | 1.49003 | 5.866 | 65.17 |
5 | CTA | Kometenschweif-Algorithmus | 0.95346 | 0.86319 | 0.27770 | 2.09435 | 0.99794 | 0.85740 | 0.33949 | 2.19484 | 0.88769 | 0.56431 | 0.10512 | 1.55712 | 5.846 | 64.96 |
6 | SDSm | stochastische Diffusionssuche M | 0.93066 | 0.85445 | 0.39476 | 2.17988 | 0.99983 | 0.89244 | 0.19619 | 2.08846 | 0.72333 | 0.61100 | 0.10670 | 1.44103 | 5.709 | 63.44 |
7 | ESG | Entwicklung der sozialen Gruppen | 0.99906 | 0.79654 | 0.35056 | 2.14616 | 1.00000 | 0.82863 | 0.13102 | 1.95965 | 0.82333 | 0.55300 | 0.04725 | 1.42358 | 5.529 | 61.44 |
8 | SIA | Simuliertes isotropes Abkühlen | 0.95784 | 0.84264 | 0.41465 | 2.21513 | 0.98239 | 0.79586 | 0.20507 | 1.98332 | 0.68667 | 0.49300 | 0.09053 | 1.27020 | 5.469 | 60.76 |
9 | ACS | künstliche, kooperative Suche | 0.75547 | 0.74744 | 0.30407 | 1.80698 | 1.00000 | 0.88861 | 0.22413 | 2.11274 | 0.69077 | 0.48185 | 0.13322 | 1.30583 | 5.226 | 58.06 |
10 | ASO | Anarchische Gesellschaftsoptimierung | 0,84872 | 0,74646 | 0,31465 | 1,90983 | 0,96148 | 0,79150 | 0,23803 | 1,99101 | 0,57077 | 0,54062 | 0,16614 | 1,27752 | 5.178 | 57,54 |
11 | TSEA | Schildkrötenpanzer-Evolutionsalgorithmus | 0.96798 | 0.64480 | 0.29672 | 1.90949 | 0.99449 | 0.61981 | 0.22708 | 1.84139 | 0.69077 | 0.42646 | 0.13598 | 1.25322 | 5.004 | 55.60 |
12 | DE | differentielle Evolution | 0.95044 | 0.61674 | 0.30308 | 1.87026 | 0.95317 | 0.78896 | 0.16652 | 1.90865 | 0.78667 | 0.36033 | 0.02953 | 1.17653 | 4.955 | 55.06 |
13 | CRO | Optimierung chemischer Reaktionen | 0.94629 | 0.66112 | 0.29853 | 1.90593 | 0.87906 | 0.58422 | 0.21146 | 1.67473 | 0.75846 | 0.42646 | 0.12686 | 1.31178 | 4.892 | 54.36 |
14 | BSA | Vogelschwarm-Algorithmus | 0.89306 | 0.64900 | 0.26250 | 1.80455 | 0.92420 | 0.71121 | 0.24939 | 1.88479 | 0.69385 | 0.32615 | 0.10012 | 1.12012 | 4.809 | 53.44 |
15 | HS | Harmoniesuche | 0.86509 | 0.68782 | 0.32527 | 1.87818 | 0.99999 | 0.68002 | 0.09590 | 1.77592 | 0.62000 | 0.42267 | 0.05458 | 1.09725 | 4.751 | 52.79 |
16 | SSG | Setzen, Säen und Wachsen | 0.77839 | 0.64925 | 0.39543 | 1.82308 | 0.85973 | 0.62467 | 0.17429 | 1.65869 | 0.64667 | 0.44133 | 0.10598 | 1.19398 | 4.676 | 51.95 |
17 | BCOm | Optimierung der bakteriellen Chemotaxis M | 0.75953 | 0.62268 | 0.31483 | 1.69704 | 0.89378 | 0.61339 | 0.22542 | 1.73259 | 0.65385 | 0.42092 | 0.14435 | 1.21912 | 4.649 | 51.65 |
18 | (PO)ES | (PO) Entwicklungsstrategien | 0.79025 | 0.62647 | 0.42935 | 1.84606 | 0.87616 | 0.60943 | 0.19591 | 1.68151 | 0.59000 | 0.37933 | 0.11322 | 1.08255 | 4.610 | 51.22 |
19 | TSm | Tabu-Suche M | 0.87795 | 0.61431 | 0.29104 | 1.78330 | 0.92885 | 0.51844 | 0.19054 | 1.63783 | 0.61077 | 0.38215 | 0.12157 | 1.11449 | 4.536 | 50.40 |
20 | BSO | Brainstorming-Optimierung | 0.93736 | 0.57616 | 0.29688 | 1.81041 | 0.93131 | 0.55866 | 0.23537 | 1.72534 | 0.55231 | 0.29077 | 0.11914 | 0.96222 | 4.498 | 49.98 |
21 | WOAm | Wal-Optimierungsalgorithmus M | 0.84521 | 0.56298 | 0.26263 | 1.67081 | 0.93100 | 0.52278 | 0.16365 | 1.61743 | 0.66308 | 0.41138 | 0.11357 | 1.18803 | 4.476 | 49.74 |
22 | AEFA | Algorithmus für künstliche elektrische Felder | 0.87700 | 0.61753 | 0.25235 | 1.74688 | 0.92729 | 0.72698 | 0.18064 | 1.83490 | 0.66615 | 0.11631 | 0.09508 | 0.87754 | 4.459 | 49.55 |
23 | ACOm | Ameisen-Kolonie-Optimierung M | 0.88190 | 0.66127 | 0.30377 | 1.84693 | 0.85873 | 0.58680 | 0.15051 | 1.59604 | 0.59667 | 0.37333 | 0.02472 | 0.99472 | 4.438 | 49.31 |
24 | BFO-GA | Optimierung der bakteriellen Futtersuche - ga | 0.89150 | 0.55111 | 0.31529 | 1.75790 | 0.96982 | 0.39612 | 0.06305 | 1.42899 | 0.72667 | 0.27500 | 0.03525 | 1.03692 | 4.224 | 46.93 |
25 | ABHA | Algorithmus für künstliche Bienenstöcke | 0.84131 | 0.54227 | 0.26304 | 1.64663 | 0.87858 | 0.47779 | 0.17181 | 1.52818 | 0.50923 | 0.33877 | 0.10397 | 0.95197 | 4.127 | 45.85 |
26 | AAm | Algorithmus für das Bogenschießen M | 0.93532 | 0.67983 | 0.25966 | 1.87481 | 0.57351 | 0.22007 | 0.14870 | 0.94228 | 0.63077 | 0.34400 | 0.10194 | 1.07671 | 3.894 | 43.26 |
27 | ASBO | Optimierung des adaptiven Sozialverhaltens | 0.76331 | 0.49253 | 0.32619 | 1.58202 | 0.79546 | 0.40035 | 0.26097 | 1.45677 | 0.26462 | 0.17169 | 0.18200 | 0.61831 | 3.657 | 40.63 |
28 | MEC | Evolutionäre Berechnung des Geistes | 0.69533 | 0.53376 | 0.32661 | 1.55569 | 0.72464 | 0.33036 | 0.07198 | 1.12698 | 0.52500 | 0.22000 | 0.04198 | 0.78698 | 3.470 | 38.55 |
29 | IWO | Optimierung mit invasiven Unkräutern | 0.72679 | 0.52256 | 0.33123 | 1.58058 | 0.70756 | 0.33955 | 0.07484 | 1.12196 | 0.42333 | 0.23067 | 0.04617 | 0.70017 | 3.403 | 37.81 |
30 | Micro-AIS | Künstliches Mikro-Immunsystem | 0.79547 | 0.51922 | 0.30861 | 1.62330 | 0.72956 | 0.36879 | 0.09398 | 1.19233 | 0.37667 | 0.15867 | 0.02802 | 0.56335 | 3.379 | 37.54 |
31 | COAm | Kuckuck-Optimierungsalgorithmus M | 0.75820 | 0.48652 | 0.31369 | 1.55841 | 0.74054 | 0.28051 | 0.05599 | 1.07704 | 0.50500 | 0.17467 | 0.03380 | 0.71347 | 3.349 | 37.21 |
32 | SDOm | Optimierung der Spiraldynamik M | 0.74601 | 0.44623 | 0.29687 | 1.48912 | 0.70204 | 0.34678 | 0.10944 | 1.15826 | 0.42833 | 0.16767 | 0.03663 | 0.63263 | 3.280 | 36.44 |
33 | NMm | Nelder-Mead-Verfahren M | 0.73807 | 0.50598 | 0.31342 | 1.55747 | 0.63674 | 0.28302 | 0.08221 | 1.00197 | 0.44667 | 0.18667 | 0.04028 | 0.67362 | 3.233 | 35.92 |
34 | FAm | Firefly-Algorithmus M | 0.58634 | 0.47228 | 0.32276 | 1.38138 | 0.68467 | 0.37439 | 0.10908 | 1.16814 | 0.28667 | 0.16467 | 0.04722 | 0.49855 | 3.048 | 33.87 |
35 | GSA | Algorithmus für die Schwerkraftsuche | 0.64757 | 0.49197 | 0.30062 | 1.44016 | 0.53962 | 0.36353 | 0.09945 | 1.00260 | 0.32667 | 0.12200 | 0.01917 | 0.46783 | 2.911 | 32.34 |
36 | BFO | Optimierung der bakteriellen Futtersuche | 0.61171 | 0.43270 | 0.31318 | 1.35759 | 0.54410 | 0.21511 | 0.05676 | 0.81597 | 0.42167 | 0.13800 | 0.03195 | 0.59162 | 2.765 | 30.72 |
37 | ABC | Künstliches Bienenvolk (Artificial Bee Colony, ABC) | 0.63377 | 0.42402 | 0.30892 | 1.36671 | 0.55103 | 0.21874 | 0.05623 | 0.82600 | 0.34000 | 0.14200 | 0.03102 | 0.51302 | 2.706 | 30.06 |
38 | BA | Fledermaus-Algorithmus | 0.59761 | 0.45911 | 0.35242 | 1.40915 | 0.40321 | 0.19313 | 0.07175 | 0.66810 | 0.21000 | 0.10100 | 0.03517 | 0.34617 | 2.423 | 26.93 |
39 | AAA | Künstlicher Algenalgorithmus (AAA) | 0.50007 | 0.32040 | 0.25525 | 1.07572 | 0.37021 | 0.22284 | 0.16785 | 0.76089 | 0.27846 | 0.14800 | 0.09755 | 0.52402 | 2.361 | 26.23 |
40 | SA | simuliertes Abkühlen | 0.55787 | 0.42177 | 0.31549 | 1.29513 | 0.34998 | 0.15259 | 0.05023 | 0.55280 | 0.31167 | 0.10033 | 0.02883 | 0.44083 | 2.289 | 25.43 |
41 | IWDm | intelligente Wassertropfen M | 0.54501 | 0.37897 | 0.30124 | 1.22522 | 0.46104 | 0.14704 | 0.04369 | 0.65177 | 0.25833 | 0.09700 | 0.02308 | 0.37842 | 2.255 | 25.06 |
42 | PSO | Partikelschwarmoptimierung | 0.59726 | 0.36923 | 0.29928 | 1.26577 | 0.37237 | 0.16324 | 0.07010 | 0.60572 | 0.25667 | 0.08000 | 0.02157 | 0.35823 | 2.230 | 24.77 |
43 | Gebote | Boids-Algorithmus | 0.43340 | 0.30581 | 0.25425 | 0.99346 | 0.35718 | 0.20160 | 0.15708 | 0.71586 | 0.27846 | 0.14277 | 0.09834 | 0.51957 | 2.229 | 24.77 |
44 | MA | Affen-Algorithmus | 0.59107 | 0.42681 | 0.31816 | 1.33604 | 0.31138 | 0.14069 | 0.06612 | 0.51819 | 0.22833 | 0.08567 | 0.02790 | 0.34190 | 2.196 | 24.40 |
45 | SFL | schlurfender Froschsprung | 0.53925 | 0.35816 | 0.29809 | 1.19551 | 0.37141 | 0.11427 | 0.04051 | 0.52618 | 0.27167 | 0.08667 | 0.02402 | 0.38235 | 2.104 | 23.38 |
Zusammenfassung
Ich habe zwei Versionen des Algorithmus vorgestellt: die ursprüngliche und eine modifizierte Version, die geringfügige Änderungen enthält, aber eine deutliche Leistungsverbesserung bietet. Dieser Artikel zeigt deutlich, dass selbst geringfügige Anpassungen an der Logik eines Algorithmus zu erheblichen Effizienzsteigerungen bei verschiedenen Aufgaben führen können. Es wird auch deutlich, dass komplexe Beschreibungen das Verständnis für die Funktionsweise eines Algorithmus erschweren können, was wiederum seine Verbesserung behindert. Im Gegenteil: Komplexe Konzepte, die in einfacher Sprache ausgedrückt werden, eröffnen den Weg zu effizienteren Lösungen.
Abbildung 1. Farbliche Abstufung der Algorithmen entsprechend den relevanten Tests Ergebnisse, die größer oder gleich 0,99 sind, werden weiß hervorgehoben
Abbildung 2. Histogramm der Algorithmus-Testergebnisse (Skala von 0 bis 100, je höher, desto besser, wobei 100 das maximal mögliche theoretische Ergebnis ist; im Archiv befindet sich ein Skript zur Berechnung der Bewertungstabelle)
Als der Artikel kurz vor der Veröffentlichung stand, hatte ich eine Idee, die ich testen wollte. Wie wäre es, wenn wir, der Logik der Autoren über Ziele und Bogenschützen folgend, die die „Roulette“-Methode für die Auswahl verwenden, die Größe der Ziele selbst umgekehrt proportional zur Qualität der gefundenen Lösungen ändern? Wenn sich die Lösung als gut erweist, sollte sie verfeinert und ihre Umgebung erkundet werden. Ist das Ergebnis unbedeutend, muss der Suchbereich erweitert werden, um neue, potenziell vielversprechende Gebiete zu ermitteln.
Abbildung 3. Die Anzahl der Pfeile, die die Ziele treffen, ist direkt proportional zur Qualität der Ziele selbst, während die Größe der Ziele umgekehrt proportional zu ihrer Qualität ist
Schauen wir uns den Code an, der die Idee verwendet, Ziele umgekehrt proportional zu ihrer Qualität zu erhöhen.
void C_AO_AAm::Moving () { //---------------------------------------------------------------------------- if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } //------------------------------------------------------------------------- // Calculate probability vector P and cumulative probability C double P [], C []; ArrayResize (P, popSize); ArrayResize (C, popSize); double F_worst = DBL_MAX; // a[ArrayMaximum(a, WHOLE_ARRAY, 0, popSize)].f; double sum = 0; for (int i = 0; i < popSize; i++) { if (a [i].f < F_worst) F_worst = a [i].f; } for (int i = 0; i < popSize; i++) { P [i] = a [i].f - F_worst; ////F_worst - a[i].f; sum += P [i]; } for (int i = 0; i < popSize; i++) { P [i] /= sum; C [i] = (i == 0) ? P [i] : C [i - 1] + P [i]; } double x; double maxFF = fB; double minFF = DBL_MAX; double prob1; double prob2; for (int i = 0; i < popSize; i++) { if (a [i].f < minFF) minFF = a [i].f; } for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { // Select archer (k) using cumulative probability int k = 0; double r = u.RNDprobab (); while (k < popSize - 1 && C [k] < r) k++; if (u.RNDbool () < inhProbab) { x = a [k].c [c]; } else { // Update position using Eq. (5) and (6) //double I = MathRound (1 + u.RNDprobab ()); double rnd = u.GaussDistribution (0, -1, 1, 8); /* if (a [k].f > a [i].f) { x = agent [i].cPrev [c] + rnd * (a [k].c [c] - I * agent [i].cPrev [c]); } else { x = agent [i].cPrev [c] + rnd * (agent [i].cPrev [c] - I * a [k].c [c]); } */ prob1 = u.Scale (a [i].f, minFF, maxFF, 0, 1); prob2 = u.Scale (a [k].f, minFF, maxFF, 0, 1); x = agent [i].cPrev [c] + rnd * (a [k].c [c] - agent [i].cPrev [c]) * (1 - prob1 - prob2); } a [i].c [c] = u.SeInDiSp (x, rangeMin [c], rangeMax [c], rangeStep [c]); } } } //—
1. Der kommentierte Abschnitt in der ursprünglichen Version verwendete das bedingte Konstrukt if-else, um zu bestimmen, wie die Position des Agenten aktualisiert werden soll. Diese Logik wurde entfernt und durch eine neue Berechnung ersetzt.
2. Drei neue Zeilen Code:
prob1 = u.Scale(a[i].f, minFF, maxFF, 0, 1); prob2 = u.Scale(a[k].f, minFF, maxFF, 0, 1); x = agent[i].cPrev[c] + rnd * (a[k].c[c] - agent[i].cPrev[c]) * (1 - prob1 - prob2);
Mit diesen Zeilen wird ein neuer Ansatz zur Berechnung der aktualisierten Position eingeführt:
a) Zwei Wahrscheinlichkeitswerte (prob1 und prob2) werden mit der Funktion Scale berechnet, die die Fitnesswerte der Agenten i und k im Bereich von 0 bis 1 auf der Grundlage der minimalen und maximalen Fitnesswerte minFF und maxFF normalisiert.
b) Dann wird die neue Position x anhand dieser Wahrscheinlichkeiten berechnet. Dabei werden die vorherige Position i des Agenten agent [i].cPrev [c], die Position k des ausgewählten Bogenschützen a [k].c [c] und den Zufallsfaktor rnd verwendet.
c) Nun wird die Bewegung durch die Summe der Fitnesswerte beider Agenten, subtrahiert von 1, beeinflusst. Dieser Faktor dient als Skalierungsfaktor, der es ermöglicht, die Zielscheibe im umgekehrten Verhältnis zur Fitness der gewählten Bogenschützen zu vergrößern oder zu verkleinern. Je weniger erfahren die Bogenschützen sind, desto größer ist die Streuung der Pfeile, aber die Verteilung der Trefferwahrscheinlichkeiten folgt immer noch einer Normalverteilung.
Schauen wir uns nun die Ergebnisse an:
AAm|Archery Algorithm M|50.0|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.9174358826544864
25 Hilly's; Func runs: 10000; result: 0.7087620527831496
500 Hilly's; Func runs: 10000; result: 0.42160091427958263
=============================
5 Forest's; Func runs: 10000; result: 0.9252690259821034
25 Forest's; Func runs: 10000; result: 0.7580206359203926
500 Forest's; Func runs: 10000; result: 0.353277934084795
=============================
5 Megacity's; Func runs: 10000; result: 0.6738461538461538
25 Megacity's; Func runs: 10000; result: 0.552
500 Megacity's; Func runs: 10000; result: 0.23738461538461658
=============================
All score: 5.54760 (61.64%)
Die Leistung des Algorithmus hat sich deutlich verbessert. In der folgenden Visualisierung sehen wir die sichere Konvergenz des Algorithmus und die Identifizierung signifikanter Bereiche der Funktionsoberfläche.
AAm mit der Testfunktion Hilly
Lassen Sie uns ein weiteres kleines Experiment durchführen. Die obigen Ergebnisse erhält man, indem man die Summe der Wahrscheinlichkeiten der Bogenschützen von eins subtrahiert.
//x = agent [i].cPrev [c] + rnd * (a [k].c [c] - agent [i].cPrev [c]) * (1 - prob1 - prob2); x = agent [i].cPrev [c] + rnd * (a [k].c [c] - agent [i].cPrev [c]) * (2 - prob1 - prob2);
Die wichtigste Änderung besteht darin, dass die Summe nicht von eins, sondern von zwei subtrahiert wird. Schauen wir uns an, wie sich eine so einfache Aktion auf das Verhalten des Algorithmus auswirken kann:
- In der vorherigen Version konnte das Ergebnis dieser Operation negativ sein, wenn die Fitness beider Bogenschützen hoch war, was zu einem „Mutationseffekt“ bei den Koordinaten des neuen Bogenschützen führte.
- In der neuen Version wird der Multiplikator einen Wert von 0 bis 2 haben.
Diese Änderung führt dazu, dass sich die Agenten umfassender bewegen und den Lösungsraum aggressiver erkunden, da die Agenten bei jeder Positionsaktualisierung größere Schritte machen.
Wie aus dem Ausdruck der Ergebnisse des Algorithmus ersichtlich ist, verbesserte diese Änderung die Konvergenz des Algorithmus bei mittelgroßen Funktionen, führte aber auch zu einer Verschlechterung bei hochdimensionalen Funktionen (gelb markiert), obwohl der Algorithmus insgesamt einen höheren Endwert erzielte.
AAm|Archery Algorithm M|50.0|0.3|
=============================
5 Hilly's; Func runs: 10000; result: 0.9053229410164233
25 Hilly's; Func runs: 10000; result: 0.8259118221071665
500 Hilly's; Func runs: 10000; result: 0.2631661675236262
=============================
5 Forest's; Func runs: 10000; result: 0.9714247249319152
25 Forest's; Func runs: 10000; result: 0.9091052022399436
500 Forest's; Func runs: 10000; result: 0.2847632249786224
=============================
5 Megacity's; Func runs: 10000; result: 0.7169230769230768
25 Megacity's; Func runs: 10000; result: 0.6378461538461538
500 Megacity's; Func runs: 10000; result: 0.10473846153846252
=============================
All score: 5.61920 (62.44%)
Das vorherige Ergebnis erscheint praktischer und wird als Hauptvariante der modifizierten Version des AAm-Algorithmus beibehalten. Ich werde die Bewertungstabelle mit thermischer Abstufung noch einmal vorstellen. AAm belegt nun einen würdigen 7. Platz. Der Algorithmus kann als sehr ausgewogen bezeichnet werden (gute Konvergenz bei Funktionen verschiedener Dimensionen) und kann für die Lösung verschiedener Probleme empfohlen werden.
Abbildung 4. Farbliche Abstufung der Algorithmen entsprechend den relevanten Tests Ergebnisse, die größer oder gleich 0,99 sind, werden weiß hervorgehoben
Vorteile und Nachteile von AAm:
Vorteile:
- Ziemlich schnell.
- Selbstanpassend.
- Nur ein externer Parameter.
- Gute Konvergenz.
- Gute Skalierbarkeit.
- Einfache Implementierung (trotz der komplexen Beschreibung durch die Autoren).
Nachteile
- Etwas anfällig für das Hängenbleiben bei niedrigdimensionalen Funktionen.
Die weitere Hinzufügung neuer Algorithmen zur Bewertungstabelle wird die Lesbarkeit erschweren. Daher habe ich beschlossen, die Zahl der Teilnehmer an der Bewertung auf 45 Algorithmen zu begrenzen, und der Wettbewerb wird nun im K.O.-Format durchgeführt. Um den Lesern den Zugang zu allen Artikeln in einer optisch ansprechenden Form zu erleichtern, habe ich eine HTML-Datei mit einer Liste aller bisher überprüften Algorithmen, sortiert nach ihrer Bewertung in einer Tabelle, vorbereitet. Diese Datei befindet sich schon seit einiger Zeit im Artikelarchiv, und wer sie zum ersten Mal öffnet, wird mit einer kleinen Überraschung konfrontiert.
Der Artikel wird von einem Archiv mit den aktuellen Versionen der Codes der Algorithmen begleitet. Der Autor des Artikels übernimmt keine Verantwortung für die absolute Richtigkeit der Beschreibung der kanonischen Algorithmen. An vielen von ihnen wurden Änderungen vorgenommen, um die Suchmöglichkeiten zu verbessern. Die in den Artikeln dargelegten Schlussfolgerungen und Urteile beruhen auf den Ergebnissen der Versuche.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/15782





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.