From b2d0c0066bced071e7aaee427d089b137707ede2 Mon Sep 17 00:00:00 2001 From: JQSakaJoo Date: Sun, 14 Jun 2026 22:52:07 +0400 Subject: [PATCH] Add COA(Coyote) --- .../Math/AOs/PopulationAO/#C_AO_enum.mqh | Bin 39486 -> 39874 bytes .../AO_COA_CoyoteOptimizationAlgorithm.mqh | 380 ++++++++++++++++++ MQL5/Include/Math/AOs/PopulationAO/links.html | 1 + README.md | 1 + 4 files changed, 382 insertions(+) create mode 100644 MQL5/Include/Math/AOs/PopulationAO/AO_COA_CoyoteOptimizationAlgorithm.mqh diff --git a/MQL5/Include/Math/AOs/PopulationAO/#C_AO_enum.mqh b/MQL5/Include/Math/AOs/PopulationAO/#C_AO_enum.mqh index 24d69373a55f3bc8d18d89aafe11dd9120190aec..36e4b0931673bc82721eb970c78d8f466474c8eb 100644 GIT binary patch delta 132 zcmdnDh3U|CrVaa81)UlE85|kn8JrpN87hIeWb#Ko>B;vbtR^oIVcC3$^@qk}nLZ9) zxHLm5gU)2jU|CM6a)#8&3w`W2@6wxK2vW$6q;N80j;bJ<=|JTV%i=ftC48_10CWx~ AxBvhE delta 28 mcmV+%0OS9{w*tPj0 0.3. | +//+------------------------------------------------------------------+ +class C_AO_COA_Coyote : public C_AO + { +public: + ~C_AO_COA_Coyote() {} + C_AO_COA_Coyote() + { + ao_name = "COA(Coyote)"; + ao_desc = "Coyote Optimization Algorithm"; + ao_link = "https://www.mql5.com/ru/articles/23053"; + + popSize = 20; + nCoy = 5; + + ArrayResize(params, 2); + params [0].name = "popSize"; + params [0].val = popSize; + params [1].name = "nCoy"; + params [1].val = nCoy; + + nPacks = popSize / nCoy; + } + + void SetParams() + { + popSize = (int)params [0].val; + nCoy = (int)params [1].val; + + nPacks = popSize / nCoy; + } + + bool Init(const double &rangeMinP [], + const double &rangeMaxP [], + const double &rangeStepP [], + const int epochsP = 0); + + void Moving(); + void Revision(); + + //--- видимые параметры + int nCoy; // койотов в стае (оригинал: 5) + +private: + int nPacks; // число стай = popSize / nCoy + double pLeave; // вероятность обмена между стаями: 0.005*nCoy^2 + double probPup; // (1 - Ps)/2, Ps = 1/coords + + int packs []; // [nPacks * nCoy] — индексы агентов по стаям + int ages []; // [popSize] — возраст койота + bool isPup []; // [popSize] — слот щенка в текущую эпоху + + //--- snapshot для greedy acceptance + double snap_c []; // [popSize * coords] + double snap_f []; // [popSize] + + //--- рабочие буферы + double medBuf []; // [nCoy] — для медианы + double tend []; // [coords] — социальная тенденция стаи + int pdr []; // [coords] — перестановка измерений (щенок) + int mask []; // [coords] — 0: шум, 1: родитель 1, 2: родитель 2 + }; +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Init | +//+------------------------------------------------------------------+ +bool C_AO_COA_Coyote::Init(const double &rangeMinP [], + const double &rangeMaxP [], + const double &rangeStepP [], + const int epochsP = 0) + { + if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP)) + return false; + +//--- начальная случайная популяция в cP[] (Eq. 2) + for(int i = 0; i < popSize; i++) + for(int c = 0; c < coords; c++) + a [i].cP [c] = u.RNDfromCI(rangeMin [c], rangeMax [c]); + +//--- параметры, зависящие от nCoy и coords + pLeave = 0.005 * (double)nCoy * (double)nCoy; // Eq. 4 + probPup = (coords > 0) ? (1.0 - 1.0 / (double)coords) * 0.5 : 0.0; // (1-Ps)/2 + +//--- буферы + ArrayResize(snap_c, popSize * coords); + ArrayResize(snap_f, popSize); + ArrayResize(packs, nPacks * nCoy); + ArrayResize(ages, popSize); + ArrayResize(isPup, popSize); + ArrayResize(medBuf, nCoy); + ArrayResize(tend, coords); + ArrayResize(pdr, coords); + ArrayResize(mask, coords); + + ArrayInitialize(ages, 0); + ArrayInitialize(isPup, false); + +//--- случайное распределение койотов по стаям (Fisher–Yates) + for(int i = 0; i < popSize; i++) + packs [i] = i; + for(int j = popSize - 1; j > 0; j--) + { + int r = u.RNDminusOne(j + 1); + int tmp = packs [j]; + packs [j] = packs [r]; + packs [r] = tmp; + } + + return true; + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Moving | +//| | +//| Структура эпохи: | +//| 1. snapshot популяции; | +//| 2. редкий обмен койотами между стаями (Eq. 4); | +//| 3. для каждой стаи: альфа, тенденция-медиана, слот щенка; | +//| 4. социальные ходы (Eq. 12) для всех, кроме слота щенка; | +//| 5. в слот щенка — кроссовер двух родителей + шум (Alg. 1). | +//+------------------------------------------------------------------+ +void C_AO_COA_Coyote::Moving() + { +//--- первый прогон: cP -> c, чтобы внешний цикл оценил FF + if(!revision) + { + for(int i = 0; i < popSize; i++) + for(int c = 0; c < coords; c++) + a [i].c [c] = u.SeInDiSp(a [i].cP [c], rangeMin [c], rangeMax [c], rangeStep [c]); + return; + } + +//--- snapshot текущей популяции + for(int i = 0; i < popSize; i++) + { + for(int c = 0; c < coords; c++) + snap_c [i * coords + c] = a [i].c [c]; + snap_f [i] = a [i].f; + } + +//--- обмен койотами между стаями (Eq. 4) + if(nPacks > 1 && u.RNDprobab() < pLeave) + { + int p1 = u.RNDminusOne(nPacks); + int p2 = p1; + while(p2 == p1) + p2 = u.RNDminusOne(nPacks); + + int c1 = u.RNDminusOne(nCoy); + int c2 = u.RNDminusOne(nCoy); + + int tmp = packs [p1 * nCoy + c1]; + packs [p1 * nCoy + c1] = packs [p2 * nCoy + c2]; + packs [p2 * nCoy + c2] = tmp; + } + + ArrayInitialize(isPup, false); + +//--- операции внутри каждой стаи + for(int p = 0; p < nPacks; p++) + { + int base = p * nCoy; + + //--- альфа стаи (Eq. 5): максимум фитнеса (стенд максимизирует) + int aIdx = packs [base]; + for(int k = 1; k < nCoy; k++) + { + int idx = packs [base + k]; + if(snap_f [idx] > snap_f [aIdx]) + aIdx = idx; + } + + //--- социальная тенденция (Eq. 6): покоординатная медиана стаи + for(int c = 0; c < coords; c++) + { + for(int k = 0; k < nCoy; k++) + medBuf [k] = snap_c [packs [base + k] * coords + c]; + ArraySort(medBuf); + tend [c] = (nCoy % 2 == 1) ? medBuf [nCoy / 2] + : 0.5 * (medBuf [nCoy / 2 - 1] + medBuf [nCoy / 2]); + } + + //--- слот щенка: худший фитнес, при равенстве — старший возраст + int wK = 0; + for(int k = 1; k < nCoy; k++) + { + int idx = packs [base + k]; + int wIdx = packs [base + wK]; + if(snap_f [idx] < snap_f [wIdx] || + (snap_f [idx] == snap_f [wIdx] && ages [idx] > ages [wIdx])) + wK = k; + } + int pupIdx = packs [base + wK]; + isPup [pupIdx] = true; + + //--- движение койотов стаи + for(int k = 0; k < nCoy; k++) + { + int i = packs [base + k]; + + if(i == pupIdx) + { + //--- РОЖДЕНИЕ ЩЕНКА (Eq. 7, Alg. 1) ------------------------- + // два случайных различных родителя из стаи + int k1 = u.RNDminusOne(nCoy); + int k2 = k1; + while(k2 == k1) + k2 = u.RNDminusOne(nCoy); + int par1 = packs [base + k1]; + int par2 = packs [base + k2]; + + //--- перестановка измерений (Fisher–Yates) + for(int c = 0; c < coords; c++) + pdr [c] = c; + + for(int j = coords - 1; j > 0; j--) + { + int r = u.RNDminusOne(j + 1); + int tmp = pdr [j]; + pdr [j] = pdr [r]; + pdr [r] = tmp; + } + + //--- маска: гарантированно по одной координате от каждого + // родителя, остальные — родитель 1 / родитель 2 / шум + ArrayInitialize(mask, 0); + mask [pdr [0]] = 1; + if(coords > 1) + mask [pdr [1]] = 2; + for(int j = 2; j < coords; j++) + { + double r = u.RNDprobab(); + if(r < probPup) + mask [pdr [j]] = 1; + else + if(r > 1.0 - probPup) + mask [pdr [j]] = 2; + // иначе 0 — равномерный шум по координате + } + + for(int c = 0; c < coords; c++) + { + double v; + if(mask [c] == 1) + v = snap_c [par1 * coords + c]; + else + if(mask [c] == 2) + v = snap_c [par2 * coords + c]; + else + v = u.RNDfromCI(rangeMin [c], rangeMax [c]); + + a [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]); + } + } + else + { + //--- СОЦИАЛЬНЫЙ ХОД (Eq. 12) -------------------------------- + // rc1, rc2 — различные, не совпадающие с k + int k1 = k; + while(k1 == k) + k1 = u.RNDminusOne(nCoy); + int k2 = k; + while(k2 == k || k2 == k1) + k2 = u.RNDminusOne(nCoy); + int rc1 = packs [base + k1]; + int rc2 = packs [base + k2]; + + //--- r1, r2 — скаляры на агента, как в оригинале + double r1 = u.RNDprobab(); + double r2 = u.RNDprobab(); + + for(int c = 0; c < coords; c++) + { + double v = snap_c [i * coords + c] + + r1 * (snap_c [aIdx * coords + c] - snap_c [rc1 * coords + c]) + + r2 * (tend [c] - snap_c [rc2 * coords + c]); + + a [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]); + } + } + } // k + } // p + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Revision | +//| | +//| Стандартное обновление fB/cB + адаптация (Eq. 14): кандидат | +//| принимается только при СТРОГОМ улучшении, иначе откат к | +//| снапшоту (касается и социальных ходов, и щенка). Возраст всех | +//| койотов растёт на 1 за эпоху; прижившийся щенок обнуляет | +//| возраст слота. | +//+------------------------------------------------------------------+ +void C_AO_COA_Coyote::Revision() + { +//--- обновление личных и глобального лучших + for(int i = 0; i < popSize; i++) + { + if(a [i].f > a [i].fB) + { + a [i].fB = a [i].f; + ArrayCopy(a [i].cB, a [i].c, 0, 0, coords); + } + if(a [i].f > fB) + { + fB = a [i].f; + ArrayCopy(cB, a [i].c, 0, 0, coords); + } + } + + if(!revision) + { + revision = true; + return; + } + +//--- адаптация (Eq. 14): принятие только при строгом улучшении + for(int i = 0; i < popSize; i++) + { + bool accepted = (a [i].f > snap_f [i]); + + if(!accepted) + { + for(int c = 0; c < coords; c++) + a [i].c [c] = snap_c [i * coords + c]; + a [i].f = snap_f [i]; + } + + //--- возраст + ages [i]++; + if(isPup [i] && accepted) + ages [i] = 0; + } + } +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQL5/Include/Math/AOs/PopulationAO/links.html b/MQL5/Include/Math/AOs/PopulationAO/links.html index bb6fa65..ccf5ed4 100644 --- a/MQL5/Include/Math/AOs/PopulationAO/links.html +++ b/MQL5/Include/Math/AOs/PopulationAO/links.html @@ -57,6 +57,7 @@ CTAcomet tail algorithm (joo) TETAtime evolution travel algorithm (joo) SDSmstochastic diffusion search M + COA(Coyote)coyote optimization algorithm ECBOenhanced colliding bodies optimization BOAmbilliards optimization algorithm M AAmarchery algorithm M diff --git a/README.md b/README.md index 69b27a3..3ce295f 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ P_O_ES ((P+O) evolution strategies) CTA (Comet Tail Algorithm, joo) TETA (time evolution travel algorithm, joo) SDSm (stochastic diffusion search M) +COA(Coyote)(coyote optimization algorithm) ECBO (enhanced colliding bodies optimization) BOAm (billiards optimization algorithm M) AAm (archery algorithm M)