English Русский Español Português
preview
Community of Scientists Optimization (CoSO): Praxis

Community of Scientists Optimization (CoSO): Praxis

MetaTrader 5Handel |
11 0
Andrey Dik
Andrey Dik

Inhalt

  1. Implementierung des Algorithmus
  2. Testergebnisse
  3. Zusammenfassung


Implementierung des Algorithmus

Im Folgenden setzen wir die Beschreibung der Implementierung des Algorithmus fort, die wir im ersten Teil des Artikels begonnen haben. Hier werden wir die Ergebnisse der experimentellen Tests an spezialisierten Testfunktionen präsentieren.

Die Funktion AssignFunds beschreibt den Mechanismus zur Verteilung der verfügbaren Mittel unter den Forschern im CoSO-Algorithmus. Diese Ressourcen repräsentieren Möglichkeiten zum Lernen, Bewegen oder zur Teilnahme an weiteren Prozessen, und ihre Verteilung beeinflusst die Dynamik der Entwicklung von Lösungen. Die Funktion akzeptiert einen Parameter: availableFunds – den Gesamtbetrag der zu verteilenden Fördermittel. Der Prozess ist in mehrere Phasen unterteilt.

Die Mittel werden in zwei Teile aufgeteilt. outsiderFunds wird berechnet, was ein Teil der für Außenseiter vorgesehenen Mittel ist. Dieser Betrag wird als Bruchteil der gesamten availableFunds berechnet, wobei omegaCurrent (ein Parameter, der den Anteil der Fördermittel für Außenseiter steuert) ein Koeffizient ist. Die verbleibenden Mittel, die in existingFunds gespeichert sind, werden aktiven Forschern zugewiesen.

    Verteilung der Fördermittel unter bestehenden Forschern. Dieser Teil wird nur ausgeführt, wenn eine globale Auswertung (globalReport) existiert. Wenn dessen Größe größer als null ist, wird totalRank berechnet – die Summe aller Ränge in arithmetischer Progression von 1 bis reportSize. Im Wesentlichen ist dies die Summe der verwendeten Gewichtungsfaktoren, um das Budget proportional zu verteilen. Die Mittel (existingFunds) werden dann einzeln verteilt: Für jedes Mittel wird eine Zufallszahl generiert, die mit totalRank multipliziert wird, und dies wird verwendet, um den Forscher auszuwählen. Es erfolgt eine Iteration über globalReport.

    Für jeden Datensatz in globalReport wird eine kumulative Summe cumSum berechnet, zu der ein Gewicht gleich (reportSize - i) addiert wird. Dies bedeutet, dass Forscher mit höheren Platzierungen im Bericht stärker gewichtet werden und daher eine bessere Chance auf den Erhalt von Fördermitteln haben. Wenn die Zufallszahl innerhalb des Intervalls liegt, das dem aktuellen Forscher zugeordnet ist (d. h. rnd <= cumSum), dann werden die Mittel dieses Forschers um 1 erhöht. Danach wird der Verteilungszyklus der aktuellen Mittel unterbrochen, und es folgt die Verteilung der nächsten.

    Erzeugung neuer Außenseiter. Schließlich wird die Funktion CreateOutsiders aufgerufen, wobei outsiderFunds übergeben wird. Diese Funktion verwendet dedizierte, für Außenseiter vorgesehene Mittel, um neue Forscher zu schaffen, oder mit anderen Worten, um neue Forschungswege zu initiieren.

      AssignFunds implementiert somit eine Strategie zur Verwaltung von Zuschüssen, die etablierte Forscher belohnt (durch existingFunds und rangbasierte Zuteilung) und gleichzeitig die Entstehung neuer Ideen oder Agenten stimuliert (durch outsiderFunds).

      //————————————————————————————————————————————————————————————————————
      void C_AO_CoSO::AssignFunds (int availableFunds)
      {
        // Funds for outsiders
        int outsiderFunds = (int)(availableFunds * omegaCurrent);
        int existingFunds = availableFunds - outsiderFunds;
      
        int reportSize = ArraySize (globalReport);
      
        // Distribute funds to existing researchers
        if (reportSize > 0)
        {
          int totalRank = reportSize * (reportSize + 1) / 2;
      
          for (int f = 0; f < existingFunds; f++)
          {
            double rnd = u.RNDprobab () * totalRank;
            double cumSum = 0;
      
            for (int i = 0; i < reportSize; i++)
            {
              cumSum += reportSize - i;
              if (rnd <= cumSum)
              {
                researchers [globalReport [i].index].m++;
                break;
              }
            }
          }
        }
      
        // Create outsiders
        CreateOutsiders (outsiderFunds);
      }
      //————————————————————————————————————————————————————————————————————
      

      Die Funktion CreateOutsiders beschreibt den Prozess der Schaffung neuer Forscher innerhalb des CoSO-Modells unter Verwendung von Ressourcen, die speziell für Außenseiter zugewiesen wurden. Diese neuen Forscher repräsentieren potenzielle Vielfalt oder neue Ideen, die in das System eingebracht werden. Die Funktion akzeptiert einen Parameter: outsiderFunds – die für die Erzeugung neuer Außenseiter vorgesehenen Fördermittel. Wenn outsiderFunds kleiner oder gleich null ist, bricht die Funktion sofort ab, da keine Mittel zur Erzeugung neuer Außenseiter vorhanden sind.

      Bestimmung der Anzahl neuer Forscher. maxNew wird festgelegt: die maximale Anzahl neuer Außenseiter, die zum aktuellen Zeitpunkt geschaffen werden können. Dieser Wert hängt von der aktuellen Populationsgröße ab. Wenn die Population groß ist (mehr als 100 Elemente), dann ist maxNew gleich 2 (um das Wachstum zu verlangsamen). Andernfalls ist maxNew 5. Dies ist ein Mechanismus zur Steuerung des Populationswachstums. Die tatsächliche Anzahl der neuen Forscher, die geschaffen werden, wird bestimmt. Sie wird zufällig im Bereich von eins bis zum Minimalwert von outsiderFunds und maxNew gewählt. Dies stellt sicher, dass die Anzahl der neuen Forscher das verfügbare Budget und das festgelegte Limit nicht überschreitet, und dann wird der Betrag der Fördermittel berechnet, den jeder neue Forscher erhält (einfach durch Division der gesamten outsiderFunds durch newResearchers).

      Der Zyklus der Schaffung neuer Forscher. Die Funktion erstellt in einer Schleife mehrmals neue Forscher: Zuerst sucht sie nach einem freien Platz im bestehenden Array der Forscher. Wenn ein freier Platz gefunden wird (idx != -1), wird dieser verwendet. Wenn kein freier Platz vorhanden ist, die aktuelle Populationsgröße jedoch kleiner als die maximal zulässige Größe (maxPopSize) ist, wird am Ende des Arrays ein neuer Platz hinzugefügt (idx = actualPopSize).

      Erweiterung des Arrays (falls erforderlich). Wenn kein freier Platz vorhanden ist und actualPopSize bereits gleich oder größer als maxPopSize ist, wird geprüft, ob die Größe des Forscher-Arrays erhöht werden kann. Wenn actualPopSize bereits maxPopSize erreicht, wird eine neue Maximalgröße (newMaxSize) als maxPopSize + 50 berechnet, jedoch nicht mehr als 500. Dies ist ein weiterer Mechanismus zur Begrenzung des Populationswachstums. Wenn das absolute Limit von 500 erreicht ist, wird die aktuelle Iteration übersprungen (es werden keine neuen Außenseiter erstellt). Andernfalls wird maxPopSize auf newMaxSize aktualisiert. Nach den Überprüfungen wird idx auf actualPopSize gesetzt, um den ersten neuen Speicherort zu verwenden. Wenn idx aus irgendeinem Grund nach allen Versuchen, einen Platz zu finden oder zu schaffen, immer noch -1 ist, wird die Erstellung des aktuellen Forschers übersprungen.

      Initialisierung eines neuen Forschers. Wenn der Speicherort idx erfolgreich gefunden oder erstellt wurde, wird researchers [idx].alive auf true gesetzt, wodurch der Forscher aktiv wird, der Betrag der Mittel oder die Motivation wird auf fundsPerNew gesetzt und die Stärke oder der Anfangswert des anderen Parameters wird mit einer Zufallszahl initialisiert.

      Initialisierung der Koordinaten (Position im Lösungsraum). Für jede Koordinate c (coords ist die Anzahl der Dimensionen) wird die Position mit einer Zufallszahl im angegebenen Bereich initialisiert. Dann wird researchers [idx].x [c] für den Abtastschritt mithilfe der Funktion SeInDiSp angepasst und die beste Position, die anfangs der aktuellen entspricht, wird ebenfalls auf researchers [idx].x [c] gesetzt. Die Änderungsrate oder der Änderungsvektor wird mit einer Zufallszahl initialisiert, die aus einer Normalverteilung mit gegebenen Parametern stammt.

      Initialisierung der Publikationswahrscheinlichkeiten für Fachzeitschriften (Publikationsjournale). Für jedes Journal j (journalsNum — Anzahl der Journale) wird die Wahrscheinlichkeit einer Veröffentlichung im Journal j mit einer Zufallszahl initialisiert. Anschließend wird NormalizeProbabilities für researchers[idx].rho aufgerufen, um sicherzustellen, dass die Summe aller rho für diesen Forscher gleich eins ist.

      Aktualisierung der Populationsgröße. Wenn ein neuer Forscher am Ende des Arrays hinzugefügt wurde, wird actualPopSize auf idx + 1 aktualisiert.

        Daher fügt CreateOutsiders der Population dynamisch neue Forscher hinzu, initialisiert sie zufällig im Lösungsraum und verteilt die zugewiesenen Mittel unter ihnen. Die Begrenzungsmechanismen maxNew und maxPopSize dienen dazu, die Populationsgröße zu kontrollieren und zu verhindern, dass sie unbegrenzt wächst.

        //————————————————————————————————————————————————————————————————————
        void C_AO_CoSO::CreateOutsiders (int outsiderFunds)
        {
          if (outsiderFunds <= 0) return;
        
          // Limit the number of new outsiders, especially if the population is already large
          int maxNew = (actualPopSize > 100) ? 2 : 5;
          int newResearchers = (int)(u.RNDfromCI (1, MathMin (outsiderFunds, maxNew)));
          int fundsPerNew = outsiderFunds / newResearchers;
        
          for (int i = 0; i < newResearchers; i++)
          {
            // Find free space
            int idx = -1;
            for (int j = 0; j < actualPopSize; j++)
            {
              if (!researchers [j].alive)
              {
                idx = j;
                break;
              }
            }
        
            if (idx == -1 && actualPopSize < maxPopSize)
            {
              idx = actualPopSize;
            }
        
            if (idx == -1) // No space, expand the array
            {
              if (actualPopSize >= maxPopSize)
              {
                // Limit population growth
                int newMaxSize = MathMin (maxPopSize + 50, 500);
                if (newMaxSize == maxPopSize) continue; // Limit reached, skip creation
        
                maxPopSize = newMaxSize;
                ArrayResize (researchers, maxPopSize);
                for (int j = actualPopSize; j < maxPopSize; j++)
                {
                  researchers [j].Init (coords, journalsNum);
                  researchers [j].alive = false;
                }
                idx = actualPopSize;
              }
            }
        
            if (idx == -1) continue; // Failed to create
        
            researchers [idx].alive = true;
            researchers [idx].m = fundsPerNew;
            researchers [idx].s = u.RNDprobab ();
        
            // Random initialization
            for (int c = 0; c < coords; c++)
            {
              researchers [idx].x [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);
              researchers [idx].x [c] = u.SeInDiSp (researchers [idx].x [c], rangeMin [c], rangeMax [c], rangeStep [c]);
              researchers [idx].b [c] = researchers [idx].x [c];
              researchers [idx].v [c] = u.GaussDistribution (0.0, -0.01, 0.01, 1);
            }
        
            // Initialize journal probabilities
            for (int j = 0; j < journalsNum; j++)
            {
              researchers [idx].rho [j] = u.RNDprobab ();
            }
            NormalizeProbabilities (researchers [idx].rho);
        
            if (idx >= actualPopSize) actualPopSize = idx + 1;
          }
        }
        //————————————————————————————————————————————————————————————————————
        

        Die Funktion HireResearchers beschreibt den Prozess der Einstellung neuer Forscher durch einen bestehenden Forscher, der über ausreichende Fördermittel verfügt. Dies ist ein Mechanismus zur Erstellung neuer Elemente (Lösungen) unter Berücksichtigung der Eigenschaften bestehender Elemente, was eine Form der Reproduktion oder Diversifizierung darstellt. Die Funktion nimmt einen Parameter entgegen: den Index des Betreuers – des Forschers, der neue Forscher einstellen wird. Wenn der betreffende Forscher über nicht mehr als eine Einheit an Fördermitteln verfügt, beendet die Funktion sofort die Ausführung. Dies bedeutet, dass für die Einstellung ausreichende Mittel erforderlich sind.

        Aufteilung der Mittel des Betreuers. Der Teil der Mittel, den der Betreuer für sich behält, wird berechnet. Dies ist das gesamte Kapital des Betreuers multipliziert mit researchers [idx].s. Die für die Einstellung verfügbaren Mittel werden berechnet. Dies sind die verbleibenden Mittel. Die Mittel des Betreuers werden aktualisiert. Wenn hireFunds kleiner oder gleich 0 ist, ist eine Einstellung nicht möglich und die Funktion bricht ab.

        Bestimmung der Anzahl der einzustellenden Forscher. Die maximale Anzahl neuer Forscher, die eingestellt werden kann, wird festgelegt. Wenn die aktuelle Population groß ist (mehr als 100), ist maxNew 1. Andernfalls ist maxNew 3. Dies ist ein Mechanismus zur Steuerung des Populationswachstums. Die tatsächliche Anzahl der neuen Forscher, die geschaffen werden, wird bestimmt. Es wird zufällig im Bereich von eins bis zum Minimalwert von hireFunds und maxNew ausgewählt. Der Betrag der Mittel, den jeder neu eingestellte Forscher erhält, wird berechnet (einfache Division von hireFunds durch newCount).

        Der Zyklus der Schaffung neuer Forscher (Rekrutierung). Die Funktion iteriert dann newCount-mal: Zuerst sucht sie nach einem freien Platz im bestehenden Array von Forschern. Freier Platz gilt als ein Index, bei dem das aktive Flag auf false gesetzt ist, und wenn freier Platz gefunden wird, wird dieser verwendet. Wenn kein freier Platz vorhanden ist, aber die aktuelle Populationsgröße kleiner als die maximal zulässige Größe ist, wird ein neuer Slot am Ende des Arrays hinzugefügt. 

        Überprüfung der Möglichkeit der Einstellung (wenn Grenzwerte erreicht sind). Wenn kein freier Platz vorhanden ist und actualPopSize bereits gleich oder größer als maxPopSize ist, oder actualPopSize bereits gleich oder größer als das absolute Limit von 500 ist, wird die Erstellung des aktuellen Forschers übersprungen (die Schleife geht zur nächsten Iteration über oder bricht ab). Wenn newIdx immer noch -1 ist, bedeutet dies, dass kein Platz für den neuen Forscher gefunden oder geschaffen werden kann und die aktuelle Iteration der Schleife übersprungen wird.

        Initialisierung eines neuen Forschers. Wenn der Platz erfolgreich gefunden wurde, wird researchers [newIdx].alive auf true gesetzt, wodurch der neue Forscher aktiv wird, und die Mittel des neuen Forschers werden auf fundsPerNew gesetzt. Der Parameter für die Tendenz des neuen Forschers wird mit einer Zufallszahl initialisiert, die aus einer Gauß-Verteilung gezogen wird. Der Mittelwert für diese Verteilung wird von researchers[idx].s (Betreuer-Parameter) übernommen und bedeutet, dass der neue Forscher seinem Betreuer ähnlich sein wird. Der Wert von s ist auf den Bereich von 0 bis 1 begrenzt.

        Vererbung von Eigenschaften vom Betreuer. Die beste Position oder das Wissen, das vom neuen Forscher gefunden wurde, wird direkt von der besten Position des Betreuers kopiert und ermöglicht es neuen Forschern, die Erfahrung zu erben.

        Initialisierung der Position (Koordinaten). Für jede c-Koordinate (coords — Anzahl der Dimensionen) wird die Position des neuen Forschers als die Position des Betreuers initialisiert, plus eine zufällige Störung, die aus einer Gauß-Verteilung stammt. Dies bedeutet, dass neue Forscher in der Nähe ihres Betreuers erscheinen, aber nicht genau am selben Ort. Die Position ist durch die angegebenen Grenzwerte begrenzt. Dann wird researchers [newIdx].x [c] für den Abtastschritt unter Verwendung der SeInDiSp-Funktion angepasst, der Änderungsvektor wird ebenfalls zufällig aus einer Normalverteilung initialisiert.

        Initialisierung der Journal- (Publikations-)Wahrscheinlichkeiten. Für jedes j-Journal (journalsNum — Anzahl der Journale) wird die Wahrscheinlichkeit der Publikation im j-Journal auf eine Zufallszahl initialisiert, die aus einer Gauß-Verteilung gezogen wird. Der Mittelwert für diese Verteilung wird aus der Betreuer-Wahrscheinlichkeit übernommen. Dies ermöglicht es neuen Forschern, die Journal-Präferenzen des Betreuers zu erben, jedoch mit einer gewissen zufälligen Variation. Negative rho-Werte werden auf 0 abgeschnitten. NormalizeProbabilities wird dann für researchers[newIdx].rho aufgerufen, um sicherzustellen, dass die Summe aller rho für diesen Forscher gleich eins ist.

        Aktualisierung der Populationsgröße. Wenn ein neuer Forscher am Ende des Arrays hinzugefügt wurde (newIdx ist gleich oder größer als actualPopSize), dann wird actualPopSize auf newIdx + 1 aktualisiert.

          Somit ermöglicht HireResearchers erfolgreichen Forschern die Reproduktion, wodurch neue Instanzen geschaffen werden, die einige ihrer Eigenschaften erben, jedoch mit einer gewissen zufälligen Variation. Dies fördert die Erkundung benachbarter Bereiche im Suchraum und die Verbreitung erfolgreicher Strategien, während die Gesamtpopulationsgröße kontrolliert wird.

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::HireResearchers (int idx)
          {
            if (researchers [idx].m <= 1) return;
          
            int keepFunds = (int)(researchers [idx].m * researchers [idx].s);
            int hireFunds = researchers [idx].m - keepFunds;
            researchers [idx].m = keepFunds;
          
            if (hireFunds <= 0) return;
          
            // Limit the number of people hired, especially in case of a large population
            int maxNew = (actualPopSize > 100) ? 1 : 3;
            int newCount = (int)(u.RNDfromCI (1, MathMin (hireFunds, maxNew)));
            int fundsPerNew = hireFunds / newCount;
          
            for (int i = 0; i < newCount; i++)
            {
              // Find free space
              int newIdx = -1;
              for (int j = 0; j < actualPopSize; j++)
              {
                if (!researchers [j].alive)
                {
                  newIdx = j;
                  break;
                }
              }
          
              if (newIdx == -1 && actualPopSize < maxPopSize)
              {
                newIdx = actualPopSize;
              }
          
              if (newIdx == -1) // No space
              {
                if (actualPopSize >= maxPopSize || actualPopSize >= 500) continue; // Skip creation when the limit is reached
              }
          
              if (newIdx == -1) continue; // Unable to find space
          
              researchers [newIdx].alive = true;
              researchers [newIdx].m = fundsPerNew;
              researchers [newIdx].s = u.GaussDistribution (researchers [idx].s, 0, 1, 1);
              if (researchers [newIdx].s < 0) researchers [newIdx].s = 0;
              if (researchers [newIdx].s > 1) researchers [newIdx].s = 1;
          
              // Inherit from a supervisor
              ArrayCopy (researchers [newIdx].b, researchers [idx].b, 0, 0, WHOLE_ARRAY);
          
              // Position near a supervisor
              for (int c = 0; c < coords; c++)
              {
                researchers [newIdx].x [c] = researchers [idx].x [c] + u.GaussDistribution (0.0, -0.01, 0.01, 1);
          
                // Boundary control
                if (researchers [newIdx].x [c] < rangeMin [c]) researchers [newIdx].x [c] = rangeMin [c];
                if (researchers [newIdx].x [c] > rangeMax [c]) researchers [newIdx].x [c] = rangeMax [c];
          
                researchers [newIdx].x [c] = u.SeInDiSp (researchers [newIdx].x [c], rangeMin [c], rangeMax [c], rangeStep [c]);
                researchers [newIdx].v [c] = u.GaussDistribution (0.0, -0.01, 0.01, 1);
              }
          
              // Perturbed journal probabilities
              for (int j = 0; j < journalsNum; j++)
              {
                researchers [newIdx].rho [j] = u.GaussDistribution (researchers [idx].rho [j], 0, 1, 1);
                if (researchers [newIdx].rho [j] < 0) researchers [newIdx].rho [j] = 0;
              }
              NormalizeProbabilities (researchers [newIdx].rho);
          
              if (newIdx >= actualPopSize) actualPopSize = newIdx + 1;
            }
          }
          //————————————————————————————————————————————————————————————————————
          

          Die Funktion ComputeStdDev wurde entwickelt, um die Standardabweichung der Zielfunktionswerte für alle aktiven Forscher in der Population zu berechnen. Sie ist ein Maß für die Streuung der Daten um den Mittelwert und kann im Kontext der Optimierung auf die Vielfalt der Lösungen in der aktuellen Population hinweisen.

          Berechnung des Mittelwerts:
          • Die Variablen mean (zum Akkumulieren der Summe der f-Werte) und count (zum Zählen der Anzahl der aktiven Forscher) werden initialisiert.
          • Die Funktion iteriert über alle Forscher im researchers-Array von 0 bis actualPopSize - 1.
          • Innerhalb der Schleife wird geprüft, ob der researchers[i] aktiv ist, da nur aktive Forscher bei den Berechnungen berücksichtigt werden sollten.
          • Wenn der Forscher aktiv ist, wird sein f-Wert zu mean addiert und count um 1 erhöht.
          • Nachdem die erste Schleife abgeschlossen ist, gibt die Funktion 0 zurück, falls count immer noch 0 ist (keine aktiven Forscher gefunden).
          • Schließlich wird mean durch count geteilt, um den durchschnittlichen f-Wert über alle aktiven Forscher hinweg zu erhalten.
          Varianzberechnung:
          • Die Variable variance wird auf 0 initialisiert.
          • Die Funktion iteriert erneut über alle Forscher im researchers-Array.
          • Die Bedingung für aktive Forscher wird erneut geprüft.
          • Für jeden aktiven Forscher wird das Quadrat der Differenz zwischen seinem f-Wert und dem bereits berechneten mean berechnet. Diese quadrierte Differenz wird zur variance addiert.
          • Nach Abschluss des zweiten Zyklus wird variance durch count geteilt. Dies ergibt die Varianz der f-Werte für aktive Forscher. 
          Berechnen und zurückgeben der Standardabweichung. Die Funktion gibt die Quadratwurzel der berechneten variance zurück. Dies ist die Standardabweichung.
          //————————————————————————————————————————————————————————————————————
          double C_AO_CoSO::ComputeStdDev ()
          {
            if (actualPopSize == 0) return 0;
          
            double mean = 0;
            int count = 0;
          
            for (int i = 0; i < actualPopSize; i++)
            {
              if (researchers [i].alive)
              {
                mean += researchers [i].f;
                count++;
              }
            }
          
            if (count == 0) return 0;
            mean /= count;
          
            double variance = 0;
            for (int i = 0; i < actualPopSize; i++)
            {
              if (researchers [i].alive)
              {
                variance += MathPow (researchers [i].f - mean, 2);
              }
            }
            variance /= count;
          
            return MathSqrt (variance);
          }
          //————————————————————————————————————————————————————————————————————
          

          Die Funktion UpdateOmega passt den Parameter omegaCurrent dynamisch an, der einen Anteil an Außenseitern oder eine Wahrscheinlichkeit für die Wahl eines Außenseiters im Algorithmusverhalten darstellt. Der Zweck dieser Funktion besteht darin, die Explorations-/Exploitationsstrategie adaptiv in Abhängigkeit vom aktuellen Zustand der Forscherpopulation zu steuern, nämlich deren Streuung im Suchraum.

          Die Funktion ruft zunächst ComputeStdDev() auf, um currentSigma zu bestimmen — die aktuelle Standardabweichung der Zielfunktionswerte für aktive Forscher. Ein hohes currentSigma bedeutet eine große Vielfalt an Lösungen, während ein niedriges currentSigma deren Konvergenz bedeutet.

          Fall 1: Populationskonvergenz (currentSigma < sigma0). Wenn die aktuelle Standardabweichung geringer als ein vordefinierter sigma0-Schwellenwert ist, ist dies ein Zeichen dafür, dass die Forscher beginnen, zu konvergieren oder sich um bestimmte Lösungen zu gruppieren. In diesem Fall geht der Algorithmus zur Phase der Exploitation (Verfeinerung) der gefundenen Lösungen über. Um eine vorzeitige Konvergenz zu einem lokalen Optimum zu vermeiden und eine weitere Exploration sowie die Suche nach besseren Lösungen zu fördern, wird der Anteil an Außenseitern (omegaCurrent) erhöht. Der Anstieg wird als (omegaMax - omegaMin) / 2.0 * epsilonPlus berechnet. Hier definieren omegaMax und omegaMin die Ober- und Untergrenzen für omegaCurrent, und epsilonPlus ist ein positiver Koeffizient, der die Anstiegsrate steuert. Das Ziel ist es, Elementen, die vom allgemeinen Trend abweichen oder völlig neue Ansätze darstellen, mehr Gewicht zu verleihen.

          Fall 2: Populationsdivergenz oder fehlende Konvergenz (currentSigma >= sigma0). Wenn die Standardabweichung größer oder gleich dem Schwellenwert sigma0 ist, bedeutet dies, dass die Population noch stark verteilt ist oder sich in einem frühen Stadium der Erkundung befindet. In diesem Fall nimmt der Anteil der Außenseiter (omegaCurrent) ab. Die Anpassung erfolgt gemäß (omegaMax - omegaMin) / 2.0 * epsilonMinus berechnet, dabei hängt die tatsächliche Änderungsrichtung vom Vorzeichen von epsilonMinus ab. Dies geschieht, um zu verhindern, dass der Algorithmus zu viele Ressourcen für eine zufällige Erkundung verschwendet, wenn die Population bereits ausreichend divers ist und er sich auf vielversprechendere Bereiche konzentrieren kann.

          Bereichsgrenze (omegaCurrent). Nach der Änderung von omegaCurrent stellt die Funktion sicher, dass ihr Wert innerhalb des angegebenen Bereichs bleibt; wenn omegaCurrent unter omegaMin fällt, wird er auf omegaMin gesetzt, und wenn er omegaMax überschreitet, wird er auf omegaMax gesetzt, wodurch verhindert wird, dass der Parameter vernünftige Betriebsgrenzen überschreitet.

          Im Allgemeinen implementiert die Funktion UpdateOmega eine adaptive Strategie. Wenn eine Population von Forschern Anzeichen einer schnellen Konvergenz (geringe Standardabweichung) zeigt, erhöht der Algorithmus die Wahrscheinlichkeit, Außenseiter (oder Elemente, die die aktuelle Struktur stören könnten) auszuwählen, um lokale Optima zu vermeiden und eine neue Suche oder die Erkundung eines breiteren Raums zu fördern. Umgekehrt reduziert der Algorithmus bei einer noch weit verteilten Population die Betonung von Ausreißern, um sich auf eine systematischere Erkundung oder Nutzung bereits entdeckter vielversprechender Bereiche zu konzentrieren. 

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::UpdateOmega ()
          {
            double currentSigma = ComputeStdDev ();
          
            if (currentSigma < sigma0)
            {
              // Increase the proportion of outsiders at convergence
              omegaCurrent += (omegaMax - omegaMin) / 2.0 * epsilonPlus;
            }
            else
            {
              // Reduce the share of outsiders
              omegaCurrent -= (omegaMax - omegaMin) / 2.0 * epsilonMinus;
            }
          
            // Limit the range
            if (omegaCurrent < omegaMin) omegaCurrent = omegaMin;
            if (omegaCurrent > omegaMax) omegaCurrent = omegaMax;
          }
          //————————————————————————————————————————————————————————————————————
          

          Die Funktion NormalizeProbabilities dient dazu, ein Array numerischer Werte probs so zu transformieren, dass sie eine gültige Wahrscheinlichkeitsverteilung darstellen. Das heißt, nach Ausführung der Funktion ist die Summe aller Elemente im Array probs gleich eins. Die Variable sum wird mit 0 initialisiert. Sie wird verwendet, um die Summe aller Elemente im Array probs zu akkumulieren. Es wird eine Schleife gestartet, die alle Elemente dieses Arrays durchläuft. Innerhalb der Schleife wird jeder Wert von probs[i] zur Variablen sum addiert. 

          Wenn die berechnete sum positiv ist, wird eine zweite Schleife gestartet, die ebenfalls alle Elemente des Arrays probs durchläuft. Innerhalb dieser Schleife wird jedes Element des Arrays durch sum dividiert. Als Ergebnis dieser Division wird jeder Wert von probs[i] zu einem entsprechenden Anteil der Gesamtsumme, und die Summe aller Elemente im Array wird gleich 1. Dies ist ein Standard-Normalisierungsverfahren.

          Wenn sum 0 oder negativ ist, was für Wahrscheinlichkeiten normalerweise nicht erwartet wird, aber von der Funktion gehandhabt wird, bedeutet dies, dass es nichts gibt, womit die ursprünglichen Werte normalisiert werden könnten. Zum Beispiel waren alle anfänglichen Wahrscheinlichkeiten null. In diesem Fall geht die Funktion in eine Gleichverteilung über. val wird als (1.0 / size) berechnet. Dies bedeutet, dass jedes Element im Array die gleiche Wahrscheinlichkeit hat, sodass die Summe insgesamt 1 ergibt. Die dritte Schleife wird gestartet, die alle Elemente des probs-Arrays durchläuft. Innerhalb dieser Schleife wird jedem Element der berechnete Wert von val zugewiesen. Somit wird jedes Element des Arrays gleich (1 / size) und ihre Summe wird 1 sein.

          Diese Funktion ist eine allgemeine Hilfsmethode, um sicherzustellen, dass eine Menge von Gewichten oder Roh-Wahrscheinlichkeiten als gültige Wahrscheinlichkeitsverteilung verwendet werden kann (wobei korrekt bedeutet, dass die Summe aller Wahrscheinlichkeiten 1 ist). Dies ist bei vielen Algorithmen wichtig, wie etwa bei wahrscheinlichkeitsbasierten Auswahlverfahren, Roulette- oder Monte-Carlo-Methoden, bei denen eine ordnungsgemäße Normalisierung Fehler verhindert und ein korrektes statistisches Verhalten sicherstellt. 

          //————————————————————————————————————————————————————————————————————
          void C_AO_CoSO::NormalizeProbabilities (double &probs [])
          {
            double sum = 0;
            int size = ArraySize (probs);
          
            for (int i = 0; i < size; i++)
            {
              sum += probs [i];
            }
          
            if (sum > 0)
            {
              for (int i = 0; i < size; i++)
              {
                probs [i] /= sum;
              }
            }
            else
            {
              // Even distribution
              double val = 1.0 / size;
              for (int i = 0; i < size; i++)
              {
                probs [i] = val;
              }
            }
          }
          //————————————————————————————————————————————————————————————————————
          

          Die Funktion CompactPopulation verwaltet die Größe und Zusammensetzung der Forschungspopulation im Algorithmus. Das Hauptziel besteht darin, die am wenigsten effektiven Forscher zu entfernen und die Population bei Bedarf auf eine überschaubare Größe zu reduzieren, um die Effizienz und Leistung des Algorithmus aufrechtzuerhalten.

          Zählen der aktiven Forscher. Die Variable aliveCount (Anzahl der Überlebenden) wird auf 0 initialisiert. Als Nächstes durchläuft die Schleife alle Forscher in der aktuellen Population (von 0 bis actualPopSize - 1). Für jeden Forscher wird dessen Status überprüft (researchers [i].alive). Wenn der Forscher aktiv ist (seine Eigenschaft alive ist true), wird aliveCount um eins erhöht.

            Bedingung für Verdichtung/Reduzierung. Nach dem Zählen der Anzahl der lebenden Forscher prüft die Funktion, ob eine Verdichtung durchgeführt werden muss. Dies geschieht, wenn eine von zwei Bedingungen erfüllt ist: Die Anzahl der aktiven Forscher aliveCount ist kleiner als 75 % der aktuellen Gesamtpopulationsgröße actualPopSize, oder die aktuelle Populationsgröße actualPopSize ist größer als 200 (selbst wenn die meisten von ihnen aktiv sind, wird die Population als zu groß angesehen und muss reduziert werden).

            Die erste Phase der Verdichtung (Entfernung von inaktiven Forschern). Wenn eine der Bedingungen für die Verdichtung erfüllt ist, beginnt der Prozess. Ein neuer Index wird auf 0 initialisiert. Dieser Index zeigt auf den nächsten freien Platz am Anfang des researchers-Arrays, an den aktive Forscher verschoben werden. Es wird eine Schleife gestartet, die alle Forscher durchläuft (von 0 bis actualPopSize - 1). Innerhalb der Schleife wird geprüft, ob der aktuelle Forscher aktiv ist und ob er sich bereits an der richtigen Stelle befindet; falls nicht, muss er im Array nach vorn verschoben werden.

            Der Forscher wird an die Position newIdx kopiert. Normalerweise wird in solchen Fällen (researchers [i].alive = false) gesetzt, um den ursprünglichen Forscher als gelöscht oder inaktiv zu markieren, auch wenn er bereits kopiert wurde. Dies ist eine Bereinigung. newIdx wird um eins erhöht, um auf die nächste Position für den nächsten aktiven Forscher zu zeigen. Nach Abschluss dieses Zyklus befinden sich alle lebenden Forscher am Anfang des researchers-Arrays. Die Populationsgröße wird auf aliveCount aktualisiert.

            Die zweite Phase der Verdichtung (Reduzierung einer großen Population). Nach der ersten Phase (in der Inaktive entfernt und Lebende verschoben wurden) prüft die Funktion, ob actualPopSize immer noch 150 überschreitet. Dies ist eine verschachtelte Bedingung – sie ist nur erfüllt, wenn die Population bereits bereinigt wurde oder viele inaktive Forscher enthielt. Wenn actualPopSize größer als 150 ist, bedeutet dies, dass die Population selbst nach dem Entfernen der inaktiven Forscher noch zu groß ist und auf die maximal zulässige Größe von 150 reduziert werden muss. Dazu wird eine Sortierung nach Fitness durchgeführt. Danach befinden sich die Forscher mit der besten Fitness am Anfang des Arrays.

            Entfernen der schlechtesten Forscher. Alle Forscher ab dem 150. Element (also diejenigen, die nach dem Sortieren am Ende gelandet sind) werden als inaktiv markiert (researchers [i].alive = false). Ihr m-Parameter wird ebenfalls zurückgesetzt. Schließlich wird actualPopSize auf 150 gesetzt, wodurch die Population effektiv auf die gewünschte Maximalgröße zugeschnitten wird. Diese Funktion stellt sicher, dass die Population:
            1. Keine ungenutzten Individuen ansammelt, die Speicherplatz beanspruchen und die Verarbeitung verlangsamen können.
            2. Nicht unkontrolliert wächst, was sich ebenfalls negativ auf Produktivität und Effizienz auswirken und zu einer vorzeitigen Lähmung führen kann.
            3. Ein gewisses Qualitätsniveau beibehält, indem die schlechtesten Individuen aussortiert werden, wenn die Populationsgröße kritisch wird.
            //————————————————————————————————————————————————————————————————————
            void C_AO_CoSO::CompactPopulation ()
            {
              // Count living researchers
              int aliveCount = 0;
              for (int i = 0; i < actualPopSize; i++)
              {
                if (researchers [i].alive) aliveCount++;
              }
            
              // If there are too many dead, compactify
              if (aliveCount < actualPopSize * 0.75 || actualPopSize > 200)
              {
                int newIdx = 0;
                for (int i = 0; i < actualPopSize; i++)
                {
                  if (researchers [i].alive)
                  {
                    if (i != newIdx)
                    {
                      // Copy the living researcher to a new location
                      researchers [newIdx] = researchers [i];
                      researchers [i].alive = false;
                    }
                    newIdx++;
                  }
                }
                actualPopSize = aliveCount;
            
                // If the population is still too large, limit it
                if (actualPopSize > 150)
                {
                  // Sort by 'fitness' and keep the best
                  for (int i = 0; i < actualPopSize - 1; i++)
                  {
                    for (int j = i + 1; j < actualPopSize; j++)
                    {
                      if (researchers [i].f < researchers [j].f)
                      {
                        S_Researcher temp = researchers [i];
                        researchers [i] = researchers [j];
                        researchers [j] = temp;
                      }
                    }
                  }
            
                  // Kill the worst
                  for (int i = 150; i < actualPopSize; i++)
                  {
                    researchers [i].alive = false;
                    researchers [i].m = 0;
                  }
                  actualPopSize = 150;
                }
              }
            }
            //————————————————————————————————————————————————————————————————————
            

            Die verbleibende Methode Revision im CoSO-Algorithmus startet eine Schleife, die alle Individuen im Array a vom Index 0 bis aSize - 1 durchläuft. Innerhalb der Schleife wird für jedes Individuum a[i] die Bedingung if (a [i].f > fB) geprüft. Wenn sich herausstellt, dass der Wert der Zielfunktion des aktuellen Individuums größer als der aktuelle globale beste Wert ist, wird fB auf den neuen besten Wert aktualisiert: fB = a[i].f. Der Index dieses besten Individuums wird gespeichert. 

            Nachdem die Schleife, die über alle Individuen im Array a iteriert hat, abgeschlossen ist, wird die Bedingung if (bestIND != -1) geprüft. Diese Bedingung ist true, wenn mindestens ein Individuum gefunden wurde, dessen Zielfunktion besser war als der vorherige Wert von fB. Wenn ein neues bestes Individuum gefunden wurde (bestIND ist ungleich -1), wird die Funktion ArrayCopy aufgerufen, welche die c-Parameter des gefundenen besten Individuums in das globale Array cB kopiert.

            Der Hauptzweck dieser Methode besteht darin, den aktuellen Zustand der vom Algorithmus zum gegebenen Zeitpunkt gefundenen global besten Lösung beizubehalten. In evolutionären Algorithmen wie CoSO wird das Konzept des global Besten ständig überwacht und aktualisiert, sobald bessere Lösungen gefunden werden. Dieses global beste Ergebnis wird dann verwendet, um die Suche zu steuern. Im Wesentlichen speichert diese Funktion bei jeder Iteration des Algorithmus „die beste Lösung“.

            //————————————————————————————————————————————————————————————————————
            void C_AO_CoSO::Revision ()
            {
              int bestIND = -1;
              int aSize = ArraySize (a);
            
              for (int i = 0; i < aSize; i++)
              {
                if (a [i].f > fB)
                {
                  fB = a [i].f;
                  bestIND = i;
                }
              }
            
              if (bestIND != -1)
              {
                ArrayCopy (cB, a [bestIND].c, 0, 0, WHOLE_ARRAY);
              }
            }
            //————————————————————————————————————————————————————————————————————
            


            Testergebnisse

            Der CoSO-Algorithmus funktioniert recht gut und liefert solide Ergebnisse. Sie können natürlich mit den Parametern experimentieren.
            CoSO|Community of Scientist Optimization|10.0|150.0|3.0|10.0|0.7|
            =============================
            5 Hilly's; Func runs: 10000; result: 0.8047081198587067
            25 Hilly's; Func runs: 10000; result: 0.5429326559833119
            500 Hilly's; Func runs: 10000; result: 0.30916988715342353
            =============================
            5 Forest's; Func runs: 10000; result: 0.7383405771205314
            25 Forest's; Func runs: 10000; result: 0.38224371519203115
            500 Forest's; Func runs: 10000; result: 0.20600693936217676
            =============================
            5 Megacity's; Func runs: 10000; result: 0.553846153846154
            25 Megacity's; Func runs: 10000; result: 0.2550769230769231
            500 Megacity's; Func runs: 10000; result: 0.11129230769230862
            =============================
            All score: 3.90362 (43.37%)

            Dies ist das erste Mal, dass ich auf eine so ungewöhnliche Visualisierung eines Algorithmus gestoßen bin, was an der mehrschichtigen Implementierungslogik liegt.

            Hilly

            CoSO mit der Testfunktion Hilly

            Forest

            CoSO mit der Testfunktion Forest

            Megacity

            CoSO mit der Testfunktion Megacity

            Basierend auf den Ergebnissen wird der CoSO-Algorithmus zu Informationszwecken in die Rangliste aufgenommen. Ich möchte darauf hinweisen, dass unsere Tabelle kompakter wird und Ergebnisse unter 45 % bereits ihre Grenzen überschreiten.

            # 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 Code-Lock-Algorithmus (joo) 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) Evolutionsstrategien 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 (joo) 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 TETA Zeit-Evolutions-Reise-Algorithmus (Joo) 0.91362 0.82349 0.31990 2.05701 0.97096 0.89532 0.29324 2.15952 0.73462 0.68569 0.16021 1.58052 5.797 64.41
            7 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
            8 BOAm Billard-Optimierungsalgorithmus M 0.95757 0.82599 0.25235 2.03590 1.00000 0.90036 0.30502 2.20538 0.73538 0.52523 0.09563 1.35625 5.598 62.19
            9 AAm Algorithmus für das Bogenschießen M 0.91744 0.70876 0.42160 2.04780 0.92527 0.75802 0.35328 2.03657 0.67385 0.55200 0.23738 1.46323 5.548 61.64
            10 ESG Entwicklung sozialer Gruppen (joo) 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
            11 SIA Simuliertes isotropes Annealing (Joo) 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
            12 EOm extremal_optimization_M 0.76166 0.77242 0.31747 1.85155 0.99999 0.76751 0.23527 2.00277 0.74769 0.53969 0.14249 1.42987 5.284 58.71
            13 BBO biogeografisch basierte Optimierung 0.94912 0.69456 0.35031 1.99399 0.93820 0.67365 0.25682 1.86867 0.74615 0.48277 0.17369 1.40261 5.265 58.50
            14 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
            15 DA dialektischer Algorithmus 0.86183 0.70033 0.33724 1.89940 0.98163 0.72772 0.28718 1.99653 0.70308 0.45292 0.16367 1.31967 5.216 57.95
            16 BHAm Algorithmus für schwarze Löcher M 0.75236 0.76675 0.34583 1.86493 0.93593 0.80152 0.27177 2.00923 0.65077 0.51646 0.15472 1.32195 5.196 57.73
            17 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
            18 RFO Optimierung des Royal Flush (joo) 0.83361 0.73742 0.34629 1.91733 0.89424 0.73824 0.24098 1.87346 0.63154 0.50292 0.16421 1.29867 5.089 56.55
            19 AOSm Suche nach atomaren Orbitalen M 0.80232 0.70449 0.31021 1.81702 0.85660 0.69451 0.21996 1.77107 0.74615 0.52862 0.14358 1.41835 5.006 55.63
            20 TSEA Schildkrötenpanzer-Evolutionsalgorithmus (joo) 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
            21 BSA Backtracking-Suchalgorithmus 0.97309 0.54534 0.29098 1.80941 0.99999 0.58543 0.21747 1.80289 0.84769 0.36953 0.12978 1.34700 4.959 55.10
            22 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
            23 SRA Algorithmus für erfolgreiche Gastronomen (joo) 0.96883 0.63455 0.29217 1.89555 0.94637 0.55506 0.19124 1.69267 0.74923 0.44031 0.12526 1.31480 4.903 54.48
            24 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
            25 BIO Optimierung der Blutvererbung (joo) 0.81568 0.65336 0.30877 1.77781 0.89937 0.65319 0.21760 1.77016 0.67846 0.47631 0.13902 1.29378 4.842 53.80
            26 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
            27 DEA Algorithmus zur Echoortung bei Delfinen 0.75995 0.67572 0.34171 1.77738 0.89582 0.64223 0.23941 1.77746 0.61538 0.44031 0.15115 1.20684 4.762 52.91
            28 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
            29 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
            30 BCOm Optimierung mit 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
            31 ABO Optimierung des afrikanischen Büffels 0.83337 0.62247 0.29964 1.75548 0.92170 0.58618 0.19723 1.70511 0.61000 0.43154 0.13225 1.17378 4.634 51.49
            32 (PO)ES (PO) Evolutionsstrategien 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
            33 FBA Fraktal-basierter Algorithmus 0.79000 0.65134 0.28965 1.73099 0.87158 0.56823 0.18877 1.62858 0.61077 0.46062 0.12398 1.19537 4.555 50.61
            34 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
            35 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
            36 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
            37 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
            38 AEO Algorithmus zur Optimierung auf der Grundlage künstlicher Ökosysteme 0.91380 0.46713 0.26470 1.64563 0.90223 0.43705 0.21400 1.55327 0.66154 0.30800 0.28563 1.25517 4.454 49.49
            39 CAm Kamel-Algorithmus M 0.78684 0.56042 0.35133 1.69859 0.82772 0.56041 0.24336 1.63149 0.64846 0.33092 0.13418 1.11356 4.444 49.37
            40 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
            41 CMAES Anpassung der Kovarianzmatrix mittels Evolutionsstrategie 0.76258 0.72089 0.00000 1.48347 0.82056 0.79616 0.00000 1.61672 0.75846 0.49077 0.00000 1.24923 4.349 48.33
            42 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
            43 SOA einfacher Optimierungsalgorithmus 0.91520 0.46976 0.27089 1.65585 0.89675 0.37401 0.16984 1.44060 0.69538 0.28031 0.10852 1.08422 4.181 46.45
            44 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
            45 ACMO Optimierung atmosphärischer Wolkenmodelle 0.90321 0.48546 0.30403 1.69270 0.80268 0.37857 0.19178 1.37303 0.62308 0.24400 0.10795 0.97503 4.041 44.90
            CoSO community_of_scientist_optimization 0.80471 0.54293 0.30917 1.65681 0.73834 0.38224 0.20600 1.32658 0.55384 0.25507 0.11129 0.92020 3.904 43.37
            RW Random Walk 0.48754 0.32159 0.25781 1.06694 0.37554 0.21944 0.15877 0.75375 0.27969 0.14917 0.09847 0.52734 2.348 26.09


            Zusammenfassung

            Der CoSO-Algorithmus zeigt durchschnittliche Ergebnisse bei den Testfunktionen und erreicht 43 % der maximal möglichen Leistung. Natürlich hatte ich beeindruckendere Ergebnisse erwartet. Die Testumgebung bietet eine erweiterte Menge an Funktionen, einschließlich standardmäßiger und bekannter Funktionen, bei denen jeder weiter mit der Parameterauswahl sowie der Funktionsauswahl experimentieren kann, um die Fähigkeiten des Algorithmus besser auszuschöpfen.

            Der Hauptnachteil der aktuellen Implementierung ist ihre hohe Rechenkomplexität. Die Mehrschichtarchitektur mit Protokollen, dynamischer Ressourcenzuweisung und adaptivem Populationsmanagement verursacht einen erheblichen Rechenaufwand. Der Algorithmus ist spürbar langsamer als andere Populationsmethoden, was seine Anwendbarkeit auf Probleme einschränkt, die schnelle Lösungen erfordern.

            Die konzeptionelle Basis von CoSO ist jedoch von erheblichem Interesse. Die Modellierung der wissenschaftlichen Gemeinschaft führt einzigartige Mechanismen ein, die angewendet wurden: Eine dynamische Population passt Rechenressourcen automatisch an die Komplexität des Problems an, ein Journalsystem stellt einen effizienten Informationsaustausch sicher, ohne die besten Lösungen zu verlieren, wettbewerbsorientierte Finanzierung erzeugt eine natürliche Selektion ohne strenge Regeln, und ein Rekrutierungsmechanismus versucht, das Dilemma zwischen lokaler und globaler Suche zu lösen.

            Das Verbesserungspotenzial ist deutlich. CoSO sollte nicht als fertige Lösung betrachtet werden, sondern als vielversprechende Forschungsplattform. Der Algorithmus eröffnet eine neue Richtung in der evolutionären Optimierung, in der die sozialen Mechanismen menschlicher Gemeinschaften zu einer Quelle algorithmischer Strategien werden. Bei entsprechender Entwicklung kann CoSO seine Nische in Aufgaben finden, bei denen Anpassungsfähigkeit und Widerstandsfähigkeit gegenüber Veränderungen wichtig sind und die Rechenzeit nicht kritisch ist.

            Tabelle

            Abbildung 1. Farbcodierter Vergleich von Algorithmen über verschiedene Tests hinweg

            Histogramm

            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)

            Vor- und Nachteile von CoSO:

            Vorteile:

            1. eine gute Grundlage für die Entwicklung neuer Varianten des Algorithmus.

            Nachteile:

            1. eine große Anzahl von externen Parametern;
            2. eine Tendenz zur Stagnation bei einigen Problemen;
            3. langsam.

            Ein Archiv mit den neuesten Versionen des Algorithmus-Codes ist dem Artikel beigefügt. 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 Experimente.


            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/18935

            Beigefügte Dateien |
            CoSO.zip (257.36 KB)
            Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
            In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
            Gaußsche Prozesse für maschinellen Lernen (Teil 2): Implementierung und Testen eines Klassifizierungsmodells in MQL5 Gaußsche Prozesse für maschinellen Lernen (Teil 2): Implementierung und Testen eines Klassifizierungsmodells in MQL5
            In diesem Abschnitt betrachten wir die Implementierung der wichtigsten Schnittstellen der Bibliothek für Gaußsche Prozesse in MQL5: IKernel, ILikelihood und IInference. Wir werden auch deren Funktionsweise an synthetischen Daten demonstrieren und Indikatoren für Klassifizierung und Regression implementieren und ihre Funktionsweise im Online-Modus demonstrieren – mit erneutem Training des Modells bei jeder neuen Bar.
            Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
            In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
            Quantenneuronales Netzwerk in MQL5 (Teil III): Ein virtueller Quantenprozessor auf Basis von Qubits Quantenneuronales Netzwerk in MQL5 (Teil III): Ein virtueller Quantenprozessor auf Basis von Qubits
            Der Artikel konzentriert sich auf die Erstellung eines Handelssystems mit einem echten Quantensimulator anstelle von mathematischen Analogien. Das System verwendet 3 virtuelle Qubits, Quantengatter und Superpositionsprinzipien zur Marktanalyse. Es ist als Handels-EA für MetaTrader 5 in MQL5 implementiert. Die wichtigste Errungenschaft ist der Übergang von der Simulation zu echten Quantenprinzipien der Finanzinformationsverarbeitung.