From dea4bde628df6e78cc0417506c633b0292b66319 Mon Sep 17 00:00:00 2001 From: JQSakaJoo Date: Tue, 30 Jun 2026 00:36:33 +0400 Subject: [PATCH] Add NBE --- .../Math/AOs/PopulationAO/#C_AO_enum.mqh | Bin 40280 -> 40644 bytes .../AO_NBE_NumaokaBacterialEvolution.mqh | 433 ++++++++++++++++++ MQL5/Include/Math/AOs/PopulationAO/links.html | 1 + README.md | 1 + 4 files changed, 435 insertions(+) create mode 100644 MQL5/Include/Math/AOs/PopulationAO/AO_NBE_NumaokaBacterialEvolution.mqh diff --git a/MQL5/Include/Math/AOs/PopulationAO/#C_AO_enum.mqh b/MQL5/Include/Math/AOs/PopulationAO/#C_AO_enum.mqh index bccdb560e436c33e47029d7636011cf32cff4304..3addc2554c4103f88dd068d182b939f29a1ef0dc 100644 GIT binary patch delta 140 zcmcbyi|NQ-rVYy^MEw|?7+e|R8T=SZ8FCpC8S)vj84@Qa3J6bTVilU4$D^@%nZ!F? zR 1.0) + pPlasmid = 1.0; + if(transFrac <= 0.0) + transFrac = 0.01; + if(transFrac > 1.0) + transFrac = 1.0; + if(cost < 0.0) + cost = 0.0; + if(pDeath < 0.0) + pDeath = 0.0; + if(pDeath > 1.0) + pDeath = 1.0; + } + + bool Init(const double &rangeMinP [], + const double &rangeMaxP [], + const double &rangeStepP [], + const int epochsP = 0); + + void Moving(); + void Revision(); + + //--- видимые параметры + double stepSize; // стартовый масштаб движения + double pPlasmid; // вероятность переноса + double transFrac; // доля coords для плазмиды + double cost; // метаболическая стоимость + double pDeath; // средовая гибель + +private: + //--- данные (массивы структур) + S_Bacteroid bro []; // [popSize] — бактероиды + int actType []; // [popSize] 0=движение, 1=перенос (на эпоху) + int allIdx []; // [popSize] — 0..popSize-1 + int living []; // [popSize] — живые в текущем Revision + + int transLen; // длина плазмиды (из transFrac) + + //--- прогресс прогона (для отжига шага) + int epochsDen; + int epochNow; + + //--- константы + double E0; // стартовая энергия + double Emax; // потолок энергии + double STEP_MIN_RATIO; + + //--- вспомогательные + double Gauss(); + double StepNow(); + int RouletteByE(int &pool [], int n, int exclude); + void Respawn(int i); + }; +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Init | +//+------------------------------------------------------------------+ +bool C_AO_NBE::Init(const double &rangeMinP [], + const double &rangeMaxP [], + const double &rangeStepP [], + const int epochsP = 0) + { + if(!StandardInit(rangeMinP, rangeMaxP, rangeStepP)) + return false; + +//--- длина плазмиды + transLen = (int)MathRound(transFrac * coords); + if(transLen < 1) + transLen = 1; + if(transLen > coords) + transLen = coords; + +//--- прогресс / константы + epochsDen = (epochsP > 1) ? epochsP - 1 : 1; + epochNow = 0; + E0 = 1.0; + Emax = 5.0; + STEP_MIN_RATIO = 0.025; + +//--- буферы + ArrayResize(bro, popSize); + ArrayResize(actType, popSize); + ArrayResize(allIdx, popSize); + ArrayResize(living, popSize); + + for(int i = 0; i < popSize; i++) + { + bro [i].Init(coords); + allIdx [i] = i; + } + +//--- стартовая популяция + for(int i = 0; i < popSize; i++) + Respawn(i); + + return true; + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Respawn — случайный генотип, стартовая энергия | +//+------------------------------------------------------------------+ +void C_AO_NBE::Respawn(int i) + { + for(int c = 0; c < coords; c++) + bro [i].c [c] = u.SeInDiSp(u.RNDfromCI(rangeMin [c], rangeMax [c]), + rangeMin [c], rangeMax [c], rangeStep [c]); + bro [i].f = -DBL_MAX; + bro [i].E = E0; + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Gauss — стандартное нормальное (Box–Muller) | +//+------------------------------------------------------------------+ +double C_AO_NBE::Gauss() + { + double u1 = u.RNDfromCI(0.0, 1.0); + double u2 = u.RNDfromCI(0.0, 1.0); + if(u1 < 1e-15) + u1 = 1e-15; + return MathSqrt(-2.0 * MathLog(u1)) * MathCos(2.0 * M_PI * u2); + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| StepNow — масштаб движения с линейным отжигом | +//+------------------------------------------------------------------+ +double C_AO_NBE::StepNow() + { + double t = (double)epochNow / (double)epochsDen; + if(t > 1.0) + t = 1.0; + return stepSize * (STEP_MIN_RATIO + (1.0 - STEP_MIN_RATIO) * (1.0 - t)); + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| RouletteByE — индекс из pool[0..n-1], взвешенный по энергии, | +//| с исключением exclude (или -1) | +//+------------------------------------------------------------------+ +int C_AO_NBE::RouletteByE(int &pool [], int n, int exclude) + { + double sum = 0.0; + for(int k = 0; k < n; k++) + { + int idx = pool [k]; + if(idx == exclude) + continue; + double e = bro [idx].E; + if(e < 1e-12) + e = 1e-12; + sum += e; + } + + if(sum <= 0.0) + { + int idx = pool [u.RNDminusOne(n)]; + return idx; + } + + double r = u.RNDprobab() * sum; + double acc = 0.0; + for(int k = 0; k < n; k++) + { + int idx = pool [k]; + if(idx == exclude) + continue; + double e = bro [idx].E; + if(e < 1e-12) + e = 1e-12; + acc += e; + if(acc >= r) + return idx; + } + return pool [n - 1]; + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Moving | +//| Каждый бактероид этой эпохой делает ЛИБО плазмидный перенос, | +//| ЛИБО хемотаксис-движение. Кандидат пишется в a[i].c. | +//+------------------------------------------------------------------+ +void C_AO_NBE::Moving() + { +//--- первый прогон: генотипы -> слоты для первичной оценки + if(!revision) + { + for(int i = 0; i < popSize; i++) + for(int c = 0; c < coords; c++) + a [i].c [c] = bro [i].c [c]; + return; + } + + epochNow++; + double step = StepNow(); + + for(int i = 0; i < popSize; i++) + { + //--- стартуем кандидата с текущего генотипа + for(int c = 0; c < coords; c++) + a [i].c [c] = bro [i].c [c]; + + if(popSize > 1 && u.RNDprobab() < pPlasmid) + { + //--- ПЛАЗМИДНЫЙ ПЕРЕНОС: блок от донора (рулетка по энергии) + actType [i] = 1; + + int donor = RouletteByE(allIdx, popSize, i); + int span = coords - transLen + 1; + if(span < 1) + span = 1; + int start = u.RNDminusOne(span); + + for(int t = 0; t < transLen; t++) + { + int c = start + t; + if(c < coords) + a [i].c [c] = bro [donor].c [c]; + } + } + else + { + //--- ХЕМОТАКСИС: покоординатное гауссово движение + actType [i] = 0; + + for(int c = 0; c < coords; c++) + { + double rng = rangeMax [c] - rangeMin [c]; + double v = bro [i].c [c] + Gauss() * step * rng; + a [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]); + } + } + } + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| Revision | +//| Приёмка хода -> энергобаланс -> гибель -> деление. | +//+------------------------------------------------------------------+ +void C_AO_NBE::Revision() + { +//--- глобальный лучший + for(int i = 0; i < popSize; i++) + { + if(a [i].f > fB) + { + fB = a [i].f; + ArrayCopy(cB, a [i].c, 0, 0, coords); + } + } + +//--- первичная фиксация + if(!revision) + { + for(int i = 0; i < popSize; i++) + { + bro [i].f = a [i].f; + bro [i].E = E0; + } + revision = true; + return; + } + +//--- приёмка хода: перенос безусловно, движение — greedy + for(int i = 0; i < popSize; i++) + { + if(actType [i] == 1) + { + for(int c = 0; c < coords; c++) + bro [i].c [c] = a [i].c [c]; + bro [i].f = a [i].f; + } + else + { + if(a [i].f >= bro [i].f) + { + for(int c = 0; c < coords; c++) + bro [i].c [c] = a [i].c [c]; + bro [i].f = a [i].f; + } + //--- иначе откат: bro[i] остаётся прежним + } + } + +//--- энергобаланс: приход ~ популяционно-относительной адаптированности + double fmin = DBL_MAX; + double fmax = -DBL_MAX; + for(int i = 0; i < popSize; i++) + { + if(bro [i].f < fmin) + fmin = bro [i].f; + if(bro [i].f > fmax) + fmax = bro [i].f; + } + double span = fmax - fmin; + if(span < 1e-12) + span = 1e-12; + + for(int i = 0; i < popSize; i++) + { + double gain = (bro [i].f - fmin) / span; // [0,1] + bro [i].E += gain - cost; + if(bro [i].E > Emax) + bro [i].E = Emax; + } + +//--- гибель: энергетическая (E<=0) или средовая (pDeath) + int nLiving = 0; + bool dead []; + ArrayResize(dead, popSize); + + for(int i = 0; i < popSize; i++) + { + bool die = (bro [i].E <= 0.0) || (u.RNDprobab() < pDeath); + dead [i] = die; + if(!die) + { + living [nLiving] = i; + nLiving++; + } + } + +//--- заполнение освободившихся слотов делением (или массовый респаун) + if(nLiving == 0) + { + for(int i = 0; i < popSize; i++) + Respawn(i); + return; + } + + double step = StepNow(); + + for(int i = 0; i < popSize; i++) + { + if(!dead [i]) + continue; + + //--- родитель — энергичный живой (рулетка по энергии) + int p = RouletteByE(living, nLiving, -1); + + //--- деление: потомок = мутированная копия родителя рядом + for(int c = 0; c < coords; c++) + { + double rng = rangeMax [c] - rangeMin [c]; + double v = bro [p].c [c] + Gauss() * step * rng; + bro [i].c [c] = u.SeInDiSp(v, rangeMin [c], rangeMax [c], rangeStep [c]); + } + + //--- энергия делится пополам + double half = bro [p].E * 0.5; + bro [i].E = half; + bro [p].E = bro [p].E - half; + + //--- фитнес потомка оценится на следующей эпохе; оценка-заглушка + bro [i].f = bro [p].f; + } + } +//+------------------------------------------------------------------+ \ 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 891c7f2..d5aa4ba 100644 --- a/MQL5/Include/Math/AOs/PopulationAO/links.html +++ b/MQL5/Include/Math/AOs/PopulationAO/links.html @@ -109,6 +109,7 @@ CSA(Crow)crow search algorithm ACMOatmospheric cloud model optimization ADAMmadaptive moment estimation M + NBEnumaoka bacterial evolution CryStAlmcrystal structure algorithm M BOAbutterfly optimization algorithm CoSOcommunity of scientist optimization diff --git a/README.md b/README.md index 8f98f8f..a16d367 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ CLA_L (competitive learning algorithm) CSA(CROW) (crow search algorithm) ACMO (atmospheric cloud model optimization) ADAMm (adaptive moment estimation) +NBE (numaoka bacterial evolution) CryStAlm (crystal structure algorithm M) BOA (butterfly optimization algorithm) CoSO (community of scientist optimization)