Community of Scientists Optimization (CoSO): Theorie
Inhalt
Einführung
Im Rahmen unserer weiteren Untersuchung von Optimierungsmethoden werden wir in diesem Artikel einen weiteren Ansatz zur Lösung von Optimierungsproblemen betrachten – den CoSO-Algorithmus (Community of Scientists Optimization), der auf der Simulation der Mechanismen der wissenschaftlichen Gemeinschaft basiert. Im Gegensatz zu klassischen bioinspirierten Algorithmen bildet CoSO die einzigartigen Merkmale wissenschaftlicher Tätigkeit nach: das Veröffentlichen von Ergebnissen in Fachzeitschriften, den Wettbewerb um Fördermittel, die Bildung von Forschungsgruppen und das Ausbalancieren zwischen der vertieften Untersuchung bekannter Bereiche und der Suche nach grundlegend neuen Lösungen. Der CoSO-Algorithmus wurde 2012 von zwei Wissenschaftlern, A. Milani und V. Santucci, entwickelt und veröffentlicht.
Ein interessantes Merkmal dieses Ansatzes ist die natürliche Selbstorganisation des Suchprozesses. Wie eine echte wissenschaftliche Gemeinschaft konzentriert der Algorithmus Ressourcen auf vielversprechende Bereiche, speichert und verbreitet die besten Lösungen durch den Mechanismus der Fachzeitschriften und erhält die notwendige Vielfalt durch die Finanzierung von „Außenseitern“. Die dynamisch sich ändernde Populationsgröße ermöglicht es dem Algorithmus, sich an die Besonderheiten eines bestimmten Problems anzupassen, ohne dass eine Feinabstimmung der Parameter erforderlich ist, was eine weitere Neuerung darstellt, da in der Regel mit einer konstanten Populationsgröße gearbeitet wird. In diesem Artikel werden wir uns eingehend mit den mathematischen Grundlagen des Algorithmus, seinen Schlüsselkomponenten und den Interaktionsmechanismen zwischen ihnen befassen.
Implementierung des Algorithmus
Der CoSO-Populationsalgorithmus basiert auf der Idee, das Verhalten von Forschern zu simulieren, die in einem mehrdimensionalen Raum nach optimalen Lösungen suchen, Wissen durch Veröffentlichungen in Fachzeitschriften austauschen und um begrenzte Ressourcen (Fördermittel) konkurrieren. Jeder Forscher ist ein Punkt im Suchraum. Er verfügt über: eine Position (an der er sucht), eine Bewegungsrichtung und Geldmittel für die Forschung. Wenn die Mittel aufgebraucht sind, wird der Forscher deaktiviert.
Jeder Forscher wird durch eine Reihe von Parametern repräsentiert: eine Position im Suchraum (x), eine Bewegungsrichtung (v), das persönlich beste Ergebnis (b), die Höhe der Mittel (m), eine Strategie zur Mittelverwaltung (s) und die Wahrscheinlichkeiten für die Auswahl verschiedener Fachzeitschriften (ρ).
Die Bewegung der Forscher wird durch die Formel zur Aktualisierung der Richtung bestimmt, die drei Komponenten kombiniert: Trägheit (die Tendenz, sich in die gleiche Richtung weiterzubewegen), eine kognitive Komponente (das Streben nach persönlichen Bestergebnissen) und eine soziale Komponente (den Einfluss der besten Ergebnisse aus Fachzeitschriften):
v {i, t} = ω · v {i, t-1} + φ₁ · β₁ · (b {i, t-1} - x {i, t-1}) + φ₂ · β₂ · Σⱼ [ρᵢⱼ · (J {j,c} - x {i, t-1})],
wobei ω = 0.7298 – Trägheitskoeffizient, φ₁ = φ₂ = 1.49618 – Beschleunigungskoeffizienten, β₁ und β₂ – Zufallszahlen aus [0,1], ρᵢⱼ – Wahrscheinlichkeit der Auswahl der Fachzeitschrift j durch Forscher i, J {j,c} – zufälliger Artikel aus der Fachzeitschrift j.
Nach der Aktualisierung der Richtung ändert sich die Position des Forschers gemäß einer einfachen Formel: x {i, t} = x {i, t-1} + v {i, t}.
Die Fachzeitschriften speichern die besten gefundenen Lösungen. Forscher lesen Fachzeitschriften und bewegen sich auf gute Lösungen zu, und nur die besten Ergebnisse schaffen es in die Fachzeitschrift. Die Fachzeitschriften im Algorithmus dienen als kollektives Gedächtnis und speichern die k besten Lösungen, die von allen Forschern gefunden wurden. Wenn ein Forscher ein neues Ergebnis erhält, reicht er es gemäß seiner Wahrscheinlichkeitsverteilung ρ in einer der Fachzeitschriften ein, das das Ergebnis nur akzeptiert, wenn es besser ist als das schlechteste der bereits veröffentlichten. Dies stellt eine kontinuierliche Verbesserung der Qualität der für die Gemeinschaft verfügbaren Informationen sicher.
Erfolgreiche Forscher erhalten mehr Finanzmittel. Ein Teil des Geldes geht an „Außenseiter“ – neue Forscher an zufälligen Orten. Auf diese Weise wird vermieden, dass man in lokalen Optima stecken bleibt. Der Mechanismus zur Verteilung von Mitteln imitiert die wettbewerbsorientierte Finanzierung in der Wissenschaft. Bei jeder Iteration geben die Forscher eine Einheit an Mitteln aus, und der gesamte ausgegebene Geldbetrag wird basierend auf der Roulette-Auswahl auf Rangbasis neu verteilt. Die Wahrscheinlichkeit, dass ein Forscher an Position i im globalen Ranking Mittel erhält, wird durch die Formel bestimmt:
P (i) = (N - i + 1) / (N · (N + 1) / 2),
wobei N die Anzahl der Forscher ist.
Ein Teil der Ω-Mittel ist für die Schaffung von „Außenseitern“ reserviert – neuen Forschern an zufälligen Positionen. Der Ω-Parameter wird adaptiv geändert, um ein Gleichgewicht zwischen Exploration und Exploitation aufrechtzuerhalten. Wenn die Standardabweichung der Fitnesswerte der Population σ kleiner als die anfängliche σ₀ wird, signalisiert dies Konvergenz und der Anteil der Außenseiter steigt:
Ω {t} = Ω {t-1} + (Ω {max} - Ω {min}) / 2 · ε⁺ für σ < σ₀, ansonsten Ω {t} = Ω {t-1} - (Ω {max} - Ω {min}) / 2 · ε⁻,
wobei Ω {min} = 0.2, Ω {max} = 0.5, ε⁺ = 0.2, ε⁻ = 0.1.
Erfolgreiche Wissenschaftler können Assistenten einstellen, die ihre Suche in der Nähe ihres Vorgesetzten beginnen. Dies hilft dabei, vielversprechende Bereiche im Detail zu erforschen. Erfolgreiche Forscher mit Mitteln m > 1 können neue Forscher hinzufügen. In diesem Fall behält der Forscher einen Teil der Mittel für sich, entsprechend seiner Strategie, und gibt den Rest für Neuzugänge aus.
Neue Forscher übernehmen die Eigenschaften des Betreuers (supervisor) mit geringfügigen Abweichungen: Die Position wird initialisiert als x {new} = x {supervisor} + N (0, σv), die Strategie als s {new} = N (s {supervisor}, σs) und die Journalwahrscheinlichkeiten als ρ {new, j} = N (ρ {supervisor, j}, σρ) ρ {new, j} = N (ρ {supervisor, j}, σρ), gefolgt von einer Normalisierung.
Der Suchprozess im Algorithmus lässt sich mit einer Gruppe von Menschen vergleichen, die im Wald Pilze sammeln: Jeder sucht an seinem eigenen Platz, und wenn jemand eine Pilzstelle findet, ruft er den anderen zu, dann geht ein Teil der Gruppe zu dieser Stelle, und der Rest sucht weiter nach neuen Plätzen. Diejenigen, die lange Zeit nichts finden, scheiden aus, aber die erfolgreichsten Pilzsammler bringen Freunde zu den Pilzstellen.
Die Leistung des Algorithmus beruht auf einer Kombination von Mechanismen: Fachzeitschriften erleichtern den Informationsaustausch und lenken die Suche auf vielversprechende Bereiche, wettbewerbsorientierte Finanzierung erzeugt Selektionsdruck durch das Ausscheiden ineffektiver Forscher, die Einstellung von Assistenten stellt die lokale Suche um gute Lösungen herum sicher, und Außenseiter verhindern eine vorzeitige Konvergenz.
Die dynamisch sich ändernde Populationsgröße ermöglicht es dem Algorithmus, sich an die Komplexität des Problems anzupassen, indem die Anzahl der Forscher in vielversprechenden Bereichen erhöht und in weniger vielversprechenden Bereichen verringert wird. All diese Mechanismen arbeiten zusammen, um ein selbstorganisierendes System zu schaffen, das in der Lage ist, Probleme in komplexen mehrdimensionalen Räumen zu lösen.

Abb. 1. Der CoSO-Algorithmus in Aktion
Das Bild zeigt Folgendes:
- Der Suchraum, in dem sich die Forscher (grüne Kreise) in Richtung des Optimums bewegen; ihre Bewegungsvektoren sind dargestellt.
- Wissenschaftliche Fachzeitschriften speichern die besten gefundenen Lösungen, Forscher lesen diese und veröffentlichen ihre Ergebnisse.
- Mittelverteilung – ein Finanzierungsmechanismus in mehrdimensionalen Räumen mit dem adaptiven Parameter Ω für Außenseiter.
- Die Formel zur Aktualisierung der Richtung – die mathematische Grundlage für die Bewegung der Forscher.
- Die Schlüsselmechanismen – eine Legende mit Forschertypen: aktiv (mit Mitteln), inaktiv (ohne Mittel), Neuzugänge und Außenseiter mit zufälligen Positionen.
Die Pfeile zeigen die Informationsflüsse (grau), Bewegungen (blau) und Mittel (orange) an. Lassen Sie uns nun den Algorithmus in Pseudocode skizzieren.
1. INITIALISIERUNG:
– Erzeugung von 10 Forschern an zufälligen Positionen
– Jedem Forscher 15 Einheiten an Mitteln zuweisen (150 / 10)
– Jeder erhält:
* Zufällige Sparstrategie (von 0 bis 1)
* Zufällige Fachzeitschriftenpräferenzen
* Anfängliche Bewegungsrichtung (leicht zufällig)
– 3 leere Fachzeitschriften erstellen
– Merke dir die anfängliche Populationsverteilung
2. HAUPTZYKLUS (wiederhole die angegebene Anzahl an Malen):
2.1. BEWERTUNG DER ERGEBNISSE:
Für jeden lebenden Forscher:
– Berechne die Qualität der aktuellen Position f(x)
– Wenn das Ergebnis besser ist als ein persönlicher Rekord:
* Aktualisiere den persönlichen Bestwert
2.2. PUBLIKATION IN FACHZEITSCHRIFTEN:
Für jeden lebenden Forscher:
– Wähle eine Fachzeitschrift gemäß deinen persönlichen Präferenzen
– Versuche, das Ergebnis zu veröffentlichen:
* Die Fachzeitschrift akzeptiert das Ergebnis, wenn es in den Top 10 ist.
* Der schwächste Artikel wird entfernt
2.3. KOSTENRECHNUNG UND BERICHTERSTATTUNG:
– Sammle alle ausgegebenen Mittel (1 von jedem)
– Erstelle ein Ranking der lebenden Forscher
– Markiere diejenigen als „tot“, denen das Geld ausgegangen ist
2.4. MITTELVERTEILUNG:
– Anteil für Außenseiter bestimmen (20-50%)
– Den Rest unter den vorhandenen Forschern verteilen:
* Je höher das Ranking, desto größer die Chancen
* Gewichtete Roulette-Auswahl verwenden
2.5. AUSSENSEITER ERSTELLEN:
– Die zugewiesenen Mittel für 1-5 Neulinge ausgeben
– An zufälligen Positionen platzieren
– Gleiche Anteile des zugewiesenen Budgets geben
2.6. ASSISTENTEN EINSTELLEN:
Für jeden wohlhabenden Forscher (Mittel > 1):
– Einen Teil gemäß der Strategie für sich behalten
– 1-3 Assistenten für den Rest einstellen:
* Neben sich platzieren
* Eigene Erfahrung mit geringfügigen Änderungen teilen
2.7. AUSWAHL DER BEWEGUNGSRICHTUNG:
Für jeden lebenden Forscher berechnen:
New_direction =
0.7 × Old_direction + // Trägheit
1.5 × Randomness × (Personal_record - Position) + // Zum eigenen Bestwert
1.5 × Randomness × Sum_by_journals // Zu den besten Lösungen der Fachzeitschriften
(Journal_weight × (Journal_article - Position))
2.8. BEWEGUNG:
Für jeden lebenden Forscher:
– Einen Schritt machen: New_position = Old_position + Direction
– Wenn die Grenzen überschritten werden, zurückbewegen
2.9. DIVERSITÄTSKONTROLLE:
– Messen der aktuellen Populationsstreuung
– Wenn die Streuung abgenommen hat (konvergierend):
* Erhöhen des Anteils der Außenseiter um 10%
– SONST:
* Verringern des Anteils der Außenseiter um 5%
2.10. VERWALTUNG DER POPULATIONSGRÖSSE:
– Wenn mehr als 25 % tot sind oder insgesamt mehr als 200 vorhanden sind:
* Entfernen der Toten aus dem Array
– Wenn mehr als 150 übrig sind:
* Nur die besten 150 behalten
3. ERGEBNIS:
– Rückgabe der besten gefundenen Lösung
Kommen wir nun zur praktischen Umsetzung des CoSO-Algorithmus. Schreiben wir drei Datenstrukturen. Die erste Struktur, S_Journal_Entry, repräsentiert einen einzelnen Fachzeitschrifteneintrag, der Folgendes enthält:
- fitness – ein numerischer Wert, der die „Qualität“ oder „Fitness“ eines gegebenen Eintrags widerspiegelt.
- decision[] - dynamisches Array, das die mit diesem Eintrag verbundenen Parameter speichert.
- entries [] – dynamisches Array von S_Journal_Entry-Einträgen.
- length – aktuelle Anzahl der Einträge in der Fachzeitschrift.
- maxLength – maximale Anzahl an Datensätzen, die die Fachzeitschrift speichern kann.
Die Init-Methode initialisiert die Fachzeitschrift, indem sie die maximale Länge festlegt, Speicher für Einträge zuweist und jeden Eintrag mit einem minimalen Fitnesswert initialisiert. Die Add-Methode wird verwendet, um einen neuen Eintrag zur Fachzeitschrift hinzuzufügen. Die Besonderheit dieser Methode besteht darin, dass sie die Fachzeitschrift nach Fitnesswerten sortiert hält. Wenn ein neuer Eintrag schlechter ist als der schlechteste Eintrag in einer bereits gefüllten Fachzeitschrift, wird er nicht hinzugefügt. Andernfalls wird mittels binärer Suche Platz für den neuen Eintrag gefunden, dann werden bestehende Einträge verschoben, um Platz zu schaffen, und der neue Eintrag wird eingefügt; wenn die Fachzeitschrift noch nicht voll ist, wird seine „length“ erhöht.
Die dritte Struktur, S_Researcher, beschreibt den „Forscher“ oder „Agenten“. Sie enthält eine Reihe von Parametern:
- x [] – aktuelle Position des Forschers (Array von Koordinaten)
- v [] – Richtungs- oder Geschwindigkeitsvektor der Bewegung des Forschers
- b [] – die beste Position, die vom jeweiligen Forscher individuell gefunden wurde
- rho [] – Array von Publikationswahrscheinlichkeiten in verschiedenen Fachzeitschriften. Der Forscher interagiert mit mehreren „Fachzeitschriften“ oder Informationsquellen
- s – Strategie zur Mittelverwaltung
- m – Höhe der Mittel (Ganzzahl)
- f – Fitness der aktuellen Forscherposition
- fb – Fitness der besten vom Forscher gefundenen Position
- alive – Flag, das die Aktivität des Forschers anzeigt
//———————————————————————————————————————————————————————————————————— // Structure for the journal struct S_Journal_Entry { double fitness; double decision []; void Init (int coords) { ArrayResize (decision, coords); fitness = -DBL_MAX; } }; // Journal structure struct S_Journal { S_Journal_Entry entries []; int length; int maxLength; void Init (int maxLen, int coords) { maxLength = maxLen; length = 0; ArrayResize (entries, maxLen); for (int i = 0; i < maxLen; i++) { entries [i].Init (coords); entries [i].fitness = -DBL_MAX; // Initialize with the minimum value } } void Add (double fit, const double &coord []) { // Quick check - if it is the worst and the journal is full, do not add if (length >= maxLength && fit <= entries [length - 1].fitness) return; int insertPos = length; // Find the insertion position (binary search) if (length > 0) { int left = 0; int right = length - 1; while (left <= right) { int mid = (left + right) / 2; if (entries [mid].fitness < fit) right = mid - 1; else left = mid + 1; } insertPos = left; } // If we insert at the end and the journal is full if (insertPos >= maxLength) return; // Shift the elements if (length < maxLength) length++; for (int i = length - 1; i > insertPos; i--) { entries [i].fitness = entries [i - 1].fitness; ArrayCopy (entries [i].decision, entries [i - 1].decision, 0, 0, WHOLE_ARRAY); } // Insert a new element entries [insertPos].fitness = fit; ArrayCopy (entries [insertPos].decision, coord, 0, 0, WHOLE_ARRAY); } }; // Extended researcher structure struct S_Researcher { double x []; // current position double v []; // movement direction double b []; // personal best result double rho []; // probabilities of publication in journals double s; // funds management strategy int m; // amount of funds double f; // fitness of the current position double fb; // fitness of the best position bool alive; // activity flag void Init (int coords, int journalsNum) { if (ArraySize (x) != coords) { ArrayResize (x, coords); ArrayResize (v, coords); ArrayResize (b, coords); } if (ArraySize (rho) != journalsNum) { ArrayResize (rho, 0); ArrayResize (rho, journalsNum); } f = -DBL_MAX; fb = -DBL_MAX; m = 0; s = 0.5; alive = true; } };
Lassen Sie uns die Klasse C_AO_CoSO schreiben, die eine Implementierung des Optimierungsalgorithmus „Community of Scientists Optimization“ (CoSO) ist. Die Klasse C_AO_CoSO erbt von der Basisklasse C_AO und setzt das Vorhandensein gemeinsamer Eigenschaften und Methoden für verschiedene Optimierungsalgorithmen voraus.
Standardwerte für verschiedene CoSO-Steuerungsparameter werden festgelegt:
- Anfangsgröße der Population der „Forscher“;
- Gesamtmenge an „Geldmitteln“ (Ressourcen), die zugewiesen werden können (in der Metapher der Wissenschaftler könnten dies Zuschüsse sein, die sie für ihre „Arbeit“ (Suche nach einer Lösung) verwenden);
- Anzahl der „Fachzeitschriften“, in denen Forscher ihre „Entdeckungen“ (beste Lösungen) veröffentlichen können;
- maximale Anzahl von Artikeln/Entdeckungen, die eine „Fachzeitschrift“ enthalten kann;
- „Trägheits“-Parameter, der den Einfluss der vorherigen Bewegungsrichtung steuert.
- phi1 = 1,5 – kognitiver Parameter spiegelt den individuellen Einfluss auf die Bewegung des Forschers wider (das Streben nach eigenen besten Entdeckungen);
- phi2 = 1,5 – sozialer Parameter bestimmt, wie stark sich der Forscher auf Veröffentlichungen in Fachzeitschriften konzentriert;
- omegaMin = 0,2 – Mindestprozentsatz an „Außenseitern“;
- omegaMax = 0,5 – Maximalprozentsatz an „Außenseitern“;
- epsilonPlus = 0,2 – Schritt zur Erhöhung der Diversität;
- epsilonMinus = 0,1 – Schritt zur Verringerung der Diversität.
Init() – Methode zur Initialisierung des Algorithmus. Sie akzeptiert Suchbereiche (Min-, Max-Werte) und Schritte für jeden Parameter sowie die Anzahl der EpochenP.
Moving() – Methode dient dem „Bewegen“ (Aktualisieren der Positionen) der Forscher im Suchraum, basierend auf ihren „Geschwindigkeiten“ und „Richtungen“.
Revision() – Methode veranlasst die Aktualisierung der besten globalen Lösung, die bis zum aktuellen Zeitpunkt von allen Forschern gefunden wurde.
Private Felder: dynamisches Array von S_Researcher-Strukturen. Jedes Element dieser Struktur repräsentiert einen „Forscher“ und enthält Informationen über dessen aktuelle Position, Geschwindigkeit, gefundene beste Lösung, „alive“, „fitness“ (f) usw. Das dynamische Array von S_Journal-Strukturen, wobei jede Struktur eine Sammlung der besten Lösungen speichert, die von Forschern in einer bestimmten „Fachzeitschrift“ veröffentlicht wurden. Aktueller Prozentsatz an „Außenseitern“. Anfängliche Standardabweichung. Aktuelle tatsächliche Populationsgröße. Sie kann sich während der Ausführung des Algorithmus ändern. Maximal zulässige Populationsgröße.
struct S_GlobalReport – eine verschachtelte Struktur zum Speichern von Informationen über die beste globale Lösung: „fitness“ (der Wert der Zielfunktion) und „index“ (der Index des Forschers, der diese Lösung gefunden hat).
S_GlobalReport globalReport [] – Array zum Speichern globaler Berichte.
Private Algorithmusmethoden:
- UpdateDirection() – Aktualisiert die Bewegungsrichtung (oder „Geschwindigkeit“) für einen bestimmten Forscher mit dem Index idx.
- SubmitToJournal() – Ermöglicht es einem Forscher mit dem Index, seine aktuell beste Lösung in einem der „Fachzeitschriften“ zu „veröffentlichen“.
- AssignFunds() – Methode zur Verteilung von „Mitteln“ unter Forschern. In CoSO können Zuschüsse das Verhalten oder die Fähigkeit von Forschern zur Suche beeinflussen.
- HireResearchers() – Methode erstellt neue Forscher.
- CreateOutsiders() – erstellt „Außenseiter“, spezielle Forscher, die aggressivere oder zufälligere Suchen durchführen können, um zu vermeiden, in lokalen Optima stecken zu bleiben.
- ComputeStdDev() – Berechnet die Standardabweichung einer Population und dient als Indikator für die „Vielfalt“ oder „Konvergenz“ einer Population.
- UpdateOmega() – Aktualisiert den aktuellen Parameter omegaCurrent.
- SelectJournal() – Wählt eine Fachzeitschrift für die Veröffentlichung basierend auf den angegebenen Wahrscheinlichkeiten aus.
- NormalizeProbabilities() – Normalisiert das Array der Wahrscheinlichkeiten, sodass deren Summe eins ergibt.
- CompactPopulation() – Methode zum „Kompaktieren“ einer Population, bei der die am wenigsten effektiven Forscher entfernt werden, d. h. Verwaltung der Populationsgröße.
//———————————————————————————————————————————————————————————————————— class C_AO_CoSO : public C_AO { public: //---------------------------------------------------------- ~C_AO_CoSO () { } C_AO_CoSO () { ao_name = "CoSO"; ao_desc = "Community of Scientist Optimization"; ao_link = "https://www.mql5.com/en/articles/18886"; popSize = 30; // initial population size totalFunds = 150; // total amount of funds journalsNum = 3; // number of journals journalLen = 10; // journal length omega = 0.7; // inertia parameter ArrayResize (params, 5); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "totalFunds"; params [1].val = totalFunds; params [2].name = "journalsNum"; params [2].val = journalsNum; params [3].name = "journalLen"; params [3].val = journalLen; params [4].name = "omega"; params [4].val = omega; //---------------------------------------------------------------- phi1 = 1.5; // cognitive parameter phi2 = 1.5; // social parameter omegaMin = 0.2; // minimum percentage of outsiders omegaMax = 0.5; // maximum percentage of outsiders epsilonPlus = 0.2; // diversity increase step epsilonMinus = 0.1; // diversity reduction step } void SetParams () { popSize = (int)params [0].val; totalFunds = (int)params [1].val; journalsNum = (int)params [2].val; journalLen = (int)params [3].val; omega = params [4].val; } bool Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0); void Moving (); void Revision (); //------------------------------------------------------------------ int totalFunds; // total amount of funds int journalsNum; // number of journals int journalLen; // journal length double omega; // inertia parameter double phi1; // cognitive parameter double phi2; // social parameter double omegaMin; // minimum percentage of outsiders double omegaMax; // maximum percentage of outsiders double epsilonPlus; // diversity increase step double epsilonMinus; // diversity reduction step private: //--------------------------------------------------------- S_Researcher researchers []; // array of researchers S_Journal journals []; // array of journals double omegaCurrent; // current percentage of outsiders double sigma0; // initial standard deviation int actualPopSize; // current population size int maxPopSize; // maximum population size double socialComponent []; // cache for the social component struct S_GlobalReport { double fitness; int index; }; S_GlobalReport globalReport []; // Algorithm methods void UpdateDirection (int idx); void SubmitToJournal (int idx); void AssignFunds (int availableFunds); void HireResearchers (int idx); void CreateOutsiders (int outsiderFunds); double ComputeStdDev (); void UpdateOmega (); int SelectJournal (const double &probs []); void NormalizeProbabilities (double &probs []); void CompactPopulation (); }; //————————————————————————————————————————————————————————————————————
Die Init-Methode ist Teil der Klasse C_AO_CoSO und ist dafür verantwortlich, alle notwendigen Strukturen und Parameter vorzubereiten, bevor der Algorithmus ausgeführt wird. Zuerst erfolgt eine Standardinitialisierung in Bezug auf die Bereiche der Suchparameter (Minimal-, Maximalwerte und Schrittweite), wobei die Anzahl der Epochen (epochsP) festgelegt wird. Wenn diese Standardinitialisierung fehlschlägt, gibt die Funktion „false“ zurück. Anschließend werden die internen Zustandsvariablen des Algorithmus initialisiert:
- actualPopSize – aktuelle Größe der Forschungspopulation,
- maxPopSize – maximal zulässige Populationsgröße (oder der für Forscher zugewiesene Speicher),
- sigma0 – Anfangswert der Standardabweichung, der später berechnet wird,
- omegaCurrent – aktueller „omega“-Parameter, initialisiert als arithmetisches Mittel zwischen omegaMin und omegaMax.
Als Nächstes folgt die Überprüfung der Gültigkeit der Eingabeparameter:
- totalFunds – der Gesamtbetrag der „Mittel“ sollte nicht geringer sein als die Populationsgröße; jedem Forscher sollte ein bestimmter Betrag an Mitteln oder Zuschüssen zugewiesen werden;
- journalsNum – die Anzahl der „Fachzeitschriften“ sollte mindestens eins betragen;
- journalLen – die Länge jeder „Fachzeitschrift“ sollte ebenfalls mindestens 1 betragen;
- omega (globaler Parameter) – sollte im Bereich von 0,0 bis 1,0 liegen.
Nach der Überprüfung der Parameter erfolgt ein „vollständiges Löschen vorheriger Durchläufe“, was bedeutet, dass die Größen der dynamischen Arrays „researchers“, „journals“, „globalReport“ und „socialComponent“ auf null zurückgesetzt werden; der Algorithmus startet immer von einem sauberen Zustand aus. Die bereits erwähnten Zustandsvariablen (actualPopSize, maxPopSize, sigma0) werden erneut zurückgesetzt.
Dann werden die „Fachzeitschriften“ initialisiert: Das Array journals wird entsprechend journalsNum in der Größe angepasst. Jede Fachzeitschrift in diesem Array wird mit einer vorgegebenen Länge journalLen und einer vorgegebenen Anzahl an coords-Koordinaten initialisiert.
Initialisierung der Forscher. maxPopSize wird auf mindestens das Dreifache von popSize (der Populationsgröße) gesetzt. Dies schafft eine „Reserve“ für mögliche Änderungen der Populationsgröße (der Algorithmus erstellt neue Forscher). fundsPerResearcher wird berechnet – der Geldbetrag, der jedem Forscher zugewiesen wird (der Gesamtbetrag der Mittel wird durch die Populationsgröße geteilt). Als Nächstes folgt ein Durchlauf durch alle Forscher.
Jeder Forscher wird mit einer Anzahl von Koordinaten coords und der Anzahl journalsNum an Fachzeitschriften initialisiert. Das alive-Flag wird nur für die ersten popSize-Forscher auf true gesetzt, die übrigen sind noch inaktiv. Aktiven Forschern wird der berechnete Geldbetrag fundsPerResearcher zugewiesen. Ihre Fondsmanagement-Strategie s wird zufällig initialisiert. Ihre Positionen x, besten persönlichen Positionen b und Bewegungsvektoren v werden initialisiert. Die Positionen von x und b werden zufällig im vorgegebenen Bereich gesetzt (rangeMin - rangeMax, unter Berücksichtigung von rangeStep). Die Bewegungsvektoren v werden auf einen kleinen Zufallswert aus einer Normalverteilung initialisiert. Die rho-Wahrscheinlichkeiten für jede Fachzeitschrift werden auf Zufallswerte initialisiert.
Die Funktion NormalizeProbabilities wird aufgerufen, welche diese Wahrscheinlichkeiten normalisiert. Nach der Initialisierung aller Forscher wird die anfängliche Standardabweichung sigma0 berechnet, welche die Streuung der Forscherpositionen über alle Koordinaten hinweg charakterisiert. Falls sigma0 gleich null ist (zum Beispiel, wenn sich alle Forscher am selben Punkt befinden), wird es auf 1.0 gesetzt, um eine Division durch 0 zu verhindern. Der Parameter omegaCurrent wird erneut auf den Durchschnitt zwischen omegaMin und omegaMax gesetzt.
Am Ende werden die Positionen aller initialisierten Forscher (popSize) in das „Standard-Agenten-Array“ von a kopiert. Somit bereitet die Init-Funktion die Umgebung vollständig für den Betrieb des Optimierungsalgorithmus vor, indem sie alle „Forscher“-Agenten, deren Parameter, „Fachzeitschriften“ zum Speichern der Ergebnisse sowie interne Parameter zur Steuerung des Algorithmus initialisiert.
//———————————————————————————————————————————————————————————————————— bool C_AO_CoSO::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ // Initialize state variables actualPopSize = 0; maxPopSize = 0; sigma0 = 0; omegaCurrent = omegaMin + (omegaMax - omegaMin) / 2.0; // Check the parameters validity if (totalFunds < popSize) totalFunds = popSize; if (journalsNum < 1) journalsNum = 1; if (journalLen < 1) journalLen = 1; if (omega < 0.0) omega = 0.0; if (omega > 1.0) omega = 1.0; // Complete reset of data from previous runs ArrayResize (researchers, 0); ArrayResize (journals, 0); ArrayResize (globalReport, 0); ArrayResize (socialComponent, 0); // Reset parameters actualPopSize = 0; maxPopSize = 0; sigma0 = 0; // Initialize the journals ArrayResize (journals, journalsNum); for (int i = 0; i < journalsNum; i++) { journals [i].Init (journalLen, coords); } // Initialize the array of researchers with a reserve maxPopSize = MathMin (popSize * 3, 300); // Limit the maximum size ArrayResize (researchers, maxPopSize); ArrayResize (socialComponent, coords); actualPopSize = popSize; int fundsPerResearcher = totalFunds / popSize; for (int i = 0; i < maxPopSize; i++) { researchers [i].Init (coords, journalsNum); researchers [i].alive = (i < popSize); if (i < popSize) { researchers [i].m = fundsPerResearcher; researchers [i].s = u.RNDprobab (); // Initialize a position for (int c = 0; c < coords; c++) { researchers [i].x [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]); researchers [i].x [c] = u.SeInDiSp (researchers [i].x [c], rangeMin [c], rangeMax [c], rangeStep [c]); researchers [i].b [c] = researchers [i].x [c]; researchers [i].v [c] = u.GaussDistribution (0.0, -0.01, 0.01, 1); } // Initialize journal probabilities for (int j = 0; j < journalsNum; j++) { researchers [i].rho [j] = u.RNDprobab (); } NormalizeProbabilities (researchers [i].rho); } } // Calculate the initial standard deviation sigma0 = ComputeStdDev (); if (sigma0 == 0) sigma0 = 1.0; // Protection against zero divide omegaCurrent = omegaMin + (omegaMax - omegaMin) / 2.0; // Copy the researchers to the standard array of agents for (int i = 0; i < popSize; i++) { ArrayCopy (a [i].c, researchers [i].x, 0, 0, WHOLE_ARRAY); } return true; } //————————————————————————————————————————————————————————————————————
Die Moving-Methode ist der zentrale Teil des iterativen Prozesses des Algorithmus; sie führt einen Suchschritt in Richtung einer optimalen Lösung aus und simuliert das Verhalten der „Forscher“ sowie deren Interaktion. Zu Beginn der Funktion wird, falls dies der erste Aufruf nach der Initialisierung ist (revision = false), einfach „revision“ auf true gesetzt und die Funktion beendet. Im Folgenden sind die Hauptschritte des Algorithmus aufgeführt, die bei jeder Iteration ausgeführt werden.
Aktualisierung der Fitness der Forscher. Für jeden aktiven Forscher (aus der aktuellen Population) wird dessen Fitnesswert aus dem allgemeinen a-Array entnommen, das die Ergebnisse der Fitnessbewertung aller Agenten speichert. Anschließend wird geprüft, ob die aktuelle Fitness des Forschers besser ist als seine zuvor aufgezeichnete beste persönliche Fitness; falls dies der Fall ist, wird fb aktualisiert und die beste Position b des Forschers wird ebenfalls als dessen aktuelle Position x gespeichert.
Einreichen der Ergebnisse bei Fachzeitschriften. Jeder aktive Forscher „reicht“ seine aktuellen Ergebnisse (aktuelle Fitness und Position) bei einer der „Fachzeitschriften“ ein. Die Details dieses Prozesses sind in der Funktion SubmitToJournal gekapselt, die basierend auf den rho-Wahrscheinlichkeiten des Forschers eine Fachzeitschrift auswählt und das Ergebnis dort hinzufügt, sofern es gut genug ist.
Erstellen eines globalen Berichts und Berechnung der verfügbaren Mittel. In diesem Schritt wird der Status der Forscher neu bewertet und die Ressourcen für die Verteilung werden vorbereitet. Für jeden lebenden Forscher verringert sich die Anzahl seiner „Mittel“ (m) um eins, was die Kosten der aktuellen Iteration symbolisiert. Der Gesamtbetrag der availableFunds nimmt zu. Wenn der Forscher nach der Verwendung der Mittel noch über Restmittel verfügt (m > 0), gilt er als arbeitsfähig und wird in den „globalen Bericht“ aufgenommen. Wenn die Mittel aufgebraucht sind, „stirbt“ der Forscher (alive = false). Es wird ein globalReport erstellt – ein Array, das die Fitness und den Index nur derjenigen Forscher enthält, die aktiv bleiben und über Mittel verfügen.
Sortieren des globalen Berichts. Die Elemente im globalReport werden mithilfe eines einfachen Bubble-Sort-Algorithmus nach absteigendem „Fitness“-Wert (von am besten bis am schlechtesten) sortiert. Dies ermöglicht es, die erfolgreichsten Forscher schnell zu identifizieren.
Mittelverteilung. Die Funktion AssignFunds wird aufgerufen, um die availableFunds unter den aktiven Forschern neu zu verteilen, wobei die besten Forscher (wie durch globalReport bestimmt) mehr Mittel erhalten, was ihre weitere Aktivität fördert, während weniger erfolgreiche Forscher möglicherweise weniger oder gar nichts erhalten, was in zukünftigen Iterationen potenziell zu ihrem „Tod“ führen kann.
Einstellung neuer Forscher durch bestehende. Aktuelle Forscher, die noch über ausreichende Mittel verfügen (m > 1), können neue Forscher „einstellen“. Dies ist ein Mechanismus zur Vergrößerung der Population oder zur Schaffung neuer Agenten auf der Grundlage erfolgreicher bestehender Agenten. Details finden Sie in der Methode HireResearchers.
Aktualisierung von Richtung und Position. Für jeden aktiven Forscher wird die Funktion UpdateDirection aufgerufen, die den neuen Bewegungsvektor v des Forschers auf der Grundlage seines persönlichen besten Ergebnisses b, des besten Ergebnisses aus den Fachzeitschriften, der sozialen Komponente oder anderer Algorithmusfaktoren berechnet. Die Position x des Forschers wird durch Addition des Bewegungsvektors v aktualisiert. Die Position wird auf Bereichsüberschreitungsfehler geprüft und gegebenenfalls angepasst sowie auf den nächsten akzeptablen rangeStep „diskretisiert“ oder „gerundet“.
Aktualisierung des Diversitätsparameters. Die Funktion UpdateOmega wird aufgerufen, die den Parameter omegaCurrent des Algorithmus anpasst. Dieser Parameter wird verwendet, um das Gleichgewicht zwischen Exploration (Finden neuer Bereiche) und Exploitation (Verfeinerung der gefundenen Lösungen) zu steuern, wobei er während des Laufs des Algorithmus dynamisch geändert wird, um die Populationsdiversität aufrechtzuerhalten.
Populationsverdichtung. Die Funktion CompactPopulation wird aufgerufen, um inaktive (alive = false) Forscher aus dem „researchers“-Array zu entfernen, wodurch dessen Größe effektiv reduziert und Speicher freigegeben wird.
Kopieren der Positionen in das Agents-Array. Schließlich werden die aktuellen Positionen aller aktiven Forscher in das a-Array kopiert. Die Größe von a wird entsprechend actualPopSize aktualisiert. Die globale Variable popSize wird ebenfalls auf die neue actualPopSize aktualisiert.
Somit kapselt die Moving-Funktion den vollständigen Lebenszyklus einer Iteration des CoSO-Algorithmus, einschließlich Bewertung, sozialer Interaktion („Fachzeitschriften“), Ressourcenmanagement, dynamischer Populationsänderung und Agentenbewegung im Suchraum.
//———————————————————————————————————————————————————————————————————— void C_AO_CoSO::Moving () { if (!revision) { revision = true; return; } //--- CoSO basic steps: // 1. Updating 'fitness' of researchers from the agents array int aSize = ArraySize (a); for (int i = 0, j = 0; i < actualPopSize && j < aSize; i++) { if (!researchers [i].alive) continue; researchers [i].f = a [j].f; // Update the personal best if (researchers [i].f > researchers [i].fb) { researchers [i].fb = researchers [i].f; ArrayCopy (researchers [i].b, researchers [i].x, 0, 0, WHOLE_ARRAY); } j++; } // 2. Submit results to journals for (int i = 0; i < actualPopSize; i++) { if (researchers [i].alive) SubmitToJournal (i); } // 3. Collect a global report and calculate available funds int availableFunds = 0; int reportSize = 0; // Preliminary calculation of the report size for (int i = 0; i < actualPopSize; i++) { if (!researchers [i].alive) continue; researchers [i].m--; // Spend 1 unit of funds per iteration availableFunds++; if (researchers [i].m > 0) reportSize++; else researchers [i].alive = false; } // Fill out the global report ArrayResize (globalReport, reportSize); int idx = 0; for (int i = 0; i < actualPopSize && idx < reportSize; i++) { if (researchers [i].alive && researchers [i].m > 0) { globalReport [idx].fitness = researchers [i].f; globalReport [idx].index = i; idx++; } } // 4. Quick sorting of a global report for (int i = 0; i < reportSize - 1; i++) { for (int j = i + 1; j < reportSize; j++) { if (globalReport [i].fitness < globalReport [j].fitness) { S_GlobalReport temp = globalReport [i]; globalReport [i] = globalReport [j]; globalReport [j] = temp; } } } // 5. Distribution of funds AssignFunds (availableFunds); // 6. Hire new researchers by existing ones for (int i = 0; i < actualPopSize; i++) { if (researchers [i].alive && researchers [i].m > 1) HireResearchers (i); } // 7. Update the direction and position for each researcher for (int i = 0; i < actualPopSize; i++) { if (!researchers [i].alive) continue; UpdateDirection (i); // Update position for (int c = 0; c < coords; c++) { researchers [i].x [c] += researchers [i].v [c]; // Boundary control if (researchers [i].x [c] < rangeMin [c]) researchers [i].x [c] = rangeMin [c]; if (researchers [i].x [c] > rangeMax [c]) researchers [i].x [c] = rangeMax [c]; researchers [i].x [c] = u.SeInDiSp (researchers [i].x [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } // 8. Update the diversity parameter UpdateOmega (); // 9. Population compactification CompactPopulation (); // 10. Copy positions to the array of agents to calculate 'fitness' ArrayResize (a, actualPopSize); idx = 0; for (int i = 0; i < maxPopSize && idx < actualPopSize; i++) { if (researchers [i].alive) { a [idx].Init (coords); ArrayCopy (a [idx].c, researchers [i].x, 0, 0, WHOLE_ARRAY); idx++; } } popSize = actualPopSize; // Update the population size } //————————————————————————————————————————————————————————————————————
Die Funktion UpdateDirection ist für die Aktualisierung des Bewegungsvektors von v für einen einzelnen Forscher im CoSO-Algorithmus verantwortlich. Dieser Prozess ist entscheidend für die Bewegung von Agenten (Forschern) im Suchraum und ermöglicht es ihnen, neue Bereiche zu erkunden und Informationen zu nutzen, die sowohl persönlich als auch von anderen Agenten gewonnen wurden. Die Funktion erhält den Parameter idx, also den Index des Forschers, dessen Richtung aktualisiert werden soll.
Zu Beginn der Funktion werden zwei Zufallsvariablen zwischen 0 und 1 generiert: beta1, das als Koeffizient für die persönliche Komponente verwendet wird, und beta2, das als Koeffizient für die soziale Komponente verwendet wird. Als Nächstes berechnen wir eine soziale Komponente, während das socialComponent-Array zurückgesetzt wird, um sicherzustellen, dass es vor jeder neuen Berechnung sauber ist.
Die Schleife durchläuft dann alle dem Algorithmus zur Verfügung stehenden „Fachzeitschriften“ und prüft für jede Fachzeitschrift, ob sie Einträge enthält (Länge > 0), da eine leere Fachzeitschrift keine Informationen für die soziale Komponente liefern kann. Wenn die Fachzeitschrift nicht leer ist, wird ein Eintrag (entryIdx) zufällig daraus ausgewählt.
Für jede Koordinate (Dimension des Suchraums) wird die soziale Komponente aktualisiert. Der Beitrag eines ausgewählten Fachzeitschriftenintrags wird berechnet als die Wahrscheinlichkeit, dass ein Forscher die Fachzeitschrift auswählt (rho[j]) * (Position des ausgewählten Artikels in der Fachzeitschrift – aktuelle Position des Forschers). Diese Beiträge werden über alle Fachzeitschriften hinweg summiert, um den Gesamteinfluss der sozialen Informationen auf die Bewegung der Forscher zu bilden. Nach der Berechnung der sozialen Komponente wird der Bewegungsvektor des Forschers, (v [c]) = Trägheitskomponente + persönliche Komponente + soziale Komponente, aktualisiert.
Analysieren wir jeden Teil:
Trägheitskomponente: omega * researchers [idx]. v [c]. Hier ist omega der Trägheitskoeffizient. Er bestimmt, wie stark der Forscher seine bisherige Bewegungsrichtung beibehält. Ein großer Wert bedeutet, dass der Forscher sich weiterhin in dieselbe Richtung bewegt; ein kleiner Wert bedeutet, dass er unter dem Einfluss anderer Faktoren schneller die Richtung ändert.
Persönliche Komponente: phi1 * beta1 * (researchers [idx]. b [c] – researchers [idx]. x [c]), wobei phi1 ein Beschleunigungsfaktor ist, der mit der persönlichen Erfahrung verbunden ist, und beta1 ein Zufallsfaktor, der Stochastik hinzufügt.
(researchers [idx]. b [c] – researchers [idx]. x [c]) ist ein Vektor, der von der aktuellen Position des Forschers auf dessen beste bisher gefundene persönliche Position (fb) zeigt. Diese Komponente zieht den Forscher zurück zu seinen eigenen erfolgreichen Orten.
- eine gewisse Trägheitsbewegung beibehalten;
- sich an die eigenen besten Funde „erinnern“ und zu diesen zurückkehren;
- die erfolgreichen Ergebnisse anderer Forscher untersuchen und ihnen folgen.
Infolgedessen berechnet „UpdateDirection“ einen neuen Bewegungsvektor für den Forscher, der im nächsten Schritt verwendet wird, um dessen Position im Suchraum tatsächlich zu aktualisieren.
//———————————————————————————————————————————————————————————————————— void C_AO_CoSO::UpdateDirection (int idx) { double beta1 = u.RNDprobab (); double beta2 = u.RNDprobab (); // Social component ArrayInitialize (socialComponent, 0); for (int j = 0; j < journalsNum; j++) { if (journals [j].length > 0) { int entryIdx = u.RNDminusOne (journals [j].length); for (int c = 0; c < coords; c++) { socialComponent [c] += researchers [idx].rho [j] * (journals [j].entries [entryIdx].decision [c] - researchers [idx].x [c]); } } } // Update direction for (int c = 0; c < coords; c++) { researchers [idx].v [c] = omega * researchers [idx].v [c] + phi1 * beta1 * (researchers [idx].b [c] - researchers [idx].x [c]) + phi2 * beta2 * socialComponent [c]; } } //————————————————————————————————————————————————————————————————————
Die Funktion „SubmitToJournal“ beschreibt den Prozess, bei dem ein einzelner Forscher seine aktuellen Ergebnisse in einer der verfügbaren „Fachzeitschriften“ „veröffentlicht“. Dies ist ein Schlüsselmechanismus für die Informationsverbreitung und das soziale Lernen innerhalb des CoSO-Algorithmus. Die Funktion verwendet den Parameter idx – den Index des Forschers, der seine Ergebnisse bei der Fachzeitschrift einreichen möchte. Der Funktionsablauf besteht aus zwei Hauptschritten:
Auswahl einer Fachzeitschrift. Zunächst wird die Hilfsfunktion „SelectJournal“ aufgerufen. Diese Funktion verwendet das Array rho des Forschers als Eingabe. Das rho-Array (das Wahrscheinlichkeiten oder Präferenzen darstellt) bestimmt, wie wahrscheinlich es ist, dass ein bestimmter Forscher seine Ergebnisse bei einer bestimmten Fachzeitschrift einreicht. Die Funktion SelectJournal wählt basierend auf diesen Wahrscheinlichkeiten zufällig eine der verfügbaren Fachzeitschriften aus und gibt deren Index (journalIdx) zurück.
Hinzufügen eines Eintrags zu einer Fachzeitschrift. Sobald eine Fachzeitschrift ausgewählt ist, wird die Add-Methode für diese aufgerufen. Der Methode werden zwei Parameter übergeben:
- researchers [idx]. f – aktueller Fitnesswert des Forschers. Dies ist die „Qualität“ oder der „Erfolg“ der gefundenen Lösung.
- researchers [idx]. x – aktuelle Position (Koordinaten im Suchraum) des Forschers. Dies ist die Lösung, die diesen Fitnesswert erzeugt hat.
Die Add-Methode in der ausgewählten Fachzeitschrift (der Fachzeitschrift mit dem Index journalIdx) ist dafür verantwortlich, diese Informationen tatsächlich hinzuzufügen. Somit bewahrt die Fachzeitschrift kollektives Wissen oder bewährte Verfahren, die von verschiedenen Forschern entdeckt wurden.
Im Allgemeinen simuliert SubmitToJournal die Veröffentlichung wissenschaftlicher Ergebnisse, wobei Forscher wählen, wo sie ihre Arbeit einreichen, und diese Arbeit dann für andere sichtbar wird. Dies ermöglicht es dem Algorithmus, erfolgreiche Lösungen innerhalb der Agentenpopulation anzusammeln und zu verteilen.
//———————————————————————————————————————————————————————————————————— void C_AO_CoSO::SubmitToJournal (int idx) { int journalIdx = SelectJournal (researchers [idx].rho); journals [journalIdx].Add (researchers [idx].f, researchers [idx].x); } //————————————————————————————————————————————————————————————————————
Die Funktion SelectJournal ist darauf ausgelegt, basierend auf festgelegten Wahrscheinlichkeiten eine Fachzeitschrift aus einer Menge verfügbarer Fachzeitschriften auszuwählen. Dies ist eine Implementierung der Roulette-Selektion oder proportionalen Selektion, bei der jede Fachzeitschrift ein bestimmtes „Gewicht“ oder eine bestimmte „Präferenz“ hat. Die Funktion nimmt einen Parameter entgegen: probs[] – ein Array von Gleitkommazahlen, die die Wahrscheinlichkeiten oder relativen Präferenzen für die Auswahl der jeweiligen Fachzeitschrift darstellen.
Die Funktion arbeitet wie folgt: Zuerst wird eine Zufallszahl rnd generiert, die gleichmäßig zwischen 0 (einschließlich) und 1 (ausschließlich) verteilt ist; diese wird verwendet, um zu bestimmen, welche Fachzeitschrift ausgewählt wird. Die Variable cumSum wird auf null initialisiert und akkumuliert die Summen der Wahrscheinlichkeiten, während sie das probs-Array durchläuft.
Behandlung eines Extremfalls. Wenn die Schleife endet und keine Fachzeitschrift ausgewählt wurde (was theoretisch aufgrund extrem geringer Genauigkeit der Berechnungen passieren könnte, wenn rnd 1 ist und die Summe aller probs genau 1 ergibt, oder wenn die Summe der probs geringfügig kleiner als 1 ist), gibt die Funktion den Index der letzten Fachzeitschrift (probsSize - 1) zurück. Dies stellt sicher, dass die Fachzeitschrift immer ausgewählt wird, selbst in Grenz- oder pathologischen Fällen.
Im Wesentlichen erstellt diese Funktion eine Reihe von „Slots“ auf dem Zahlenstrahl von 0 bis 1, wobei die Länge jedes Slots proportional zur Wahrscheinlichkeit der entsprechenden Fachzeitschrift ist. Dann wirft sie einen „Pfeil“ (rnd-Zufallszahl) und beobachtet, in welchem Bereich er landet. Dies stellt sicher, dass Fachzeitschriften mit höheren Wahrscheinlichkeiten häufiger ausgewählt werden.
//———————————————————————————————————————————————————————————————————— int C_AO_CoSO::SelectJournal (const double &probs []) { double rnd = u.RNDprobab (); double cumSum = 0; int probsSize = ArraySize (probs); for (int i = 0; i < probsSize; i++) { cumSum += probs [i]; if (rnd <= cumSum) return i; } return probsSize - 1; } //————————————————————————————————————————————————————————————————————
Schlussfolgerung
Wir haben uns die Theorie des CoSO-Algorithmus sowie einen Teil der Implementierung der Algorithmus-Methoden im Code im Detail angesehen. Der Umfang des Materials erwies sich als deutlich größer als zu Beginn der Arbeit erwartet, und ich habe beschlossen, den Artikel in zwei Teile aufzuteilen. Der Algorithmus selbst ist äußerst interessant und vielschichtig, mit einer tiefen, mehrschichtigen Logik, die eine sorgfältige Betrachtung verdient.
Im zweiten Teil werde ich die spezifischen Methoden weiter beschreiben sowie den Algorithmus testen und Schlussfolgerungen zu seiner Leistung präsentieren.
Im Artikel verwendete Programme
| # | Name | Typ | Beschreibung |
|---|---|---|---|
| 1 | #C_AO.mqh | Include | Übergeordnete Klasse von Populationsoptimierungsalgorithmen |
| 2 | #C_AO_enum.mqh | Include | Enumeration der Algorithmen zur Populationsoptimierung |
| 3 | TestFunctions.mqh | Include | Bibliothek mit Testfunktionen |
| 4 | TestStandFunctions.mqh | Include | Bibliothek mit Funktionen für die Testumgebung |
| 5 | Utilities.mqh | Include | Bibliothek mit Hilfsfunktionen |
| 6 | CalculationTestResults.mqh | Include | Skript zur Berechnung der Ergebnisse in der Vergleichstabelle |
| 7 | Testing AOs.mq5 | Skript | Die einheitliche Testumgebung für alle Algorithmen zur Populationsoptimierung |
| 8 | Simple use of population optimization algorithms.mq5 | Skript | Ein einfaches Beispiel für die Verwendung von Algorithmen zur Populationsoptimierung ohne Visualisierung |
| 9 | Test_AO_CoSO.mq5 | Skript | CoSO-Testumgebung |
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/18886
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Von der Grundstufe zur Mittelstufe: FileSave und FileLoad
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Quantenneuronales Netzwerk in MQL5 (Teil II): Training eines neuronalen Netzwerkes mit Backpropagation unter Verwendung von ALGLIB-Markov-Matrizen
- 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.