Для примера, возьмем обработку одного из режимов сна:
-
//Псевдокод, похожий на Мозгокод:
-
//Для краткости записи, (neuron.activation>const) будет записываться как (neuron>const),
-
//(neuron.activation>neuron.threshold) будет записываться как (neuron>t)
-
для всех нейрокластеров
-
{
-
switch(neuroCluster)
-
{
-
case (nIn>0 && nEn>0)режим_выделения; break;
-
case (nIn>t && nEn>t) ->VA nOut; break;
-
case (nIn>0 && nEn==0)->V nFd; break;
-
}
-
}
При попытке реализации этого псевдокода на С++, возникает много инструкций сравнения, причем более громоздких. Вместо case (nIn>0 && nEn>0){} нужно будет писать либо if(0 < nIn->activation && nIn->activation < nIn->thrNorm && 0 < nEn->activation){…}, либо предусмотреть, чтобы сценарий с активацией нейрона, превышающей порог, проверялся раньше, чем на превышение только нуля. Можно использовать макросы, например
-
#define ACTIVATED_BEFORE_THRESHOLD(n) (0 < n->activation && n->activation < n->thrrNorm)
Но тогда к if-ам нужно будет везде ставить else – иначе компилятор может решить, что при исполнении внутренних инструкций активация и порог могли измениться, и начать производить сравнения снова. Кроме того, при изменении названий полей активации и порога у нейронов разных типов, придется применять другие макросы, например, с префиксом типа мозга. Код становится более «мозго-зависимым». Можно использовать inline-функции класса нейрона, называемые одинаково у нейронов разных типов. Но желательно еще и не делать лишних сравнений. Компилятор не знает, что порог всегда будет не меньше нуля, и не сможет оптимизировать исполнение сокращением количества сравнений. Попытка сделать оптимизацию вручную усложнит код. Код теряет наглядность. Решение – явно разбить активацию на отрезки с применением inline-функций, одинаковых в разных мозгах:
-
//Threshold Type
-
enum ThrType
-
{
-
EqLess0 = 0,//activation is Equal or Less 0
-
Greater0 = 1,//activation is greater than 0 and less than threshold
-
GreaterT = 2,//activation is greater or equal to threshold
-
};
-
-
class neuronB2: public CommonNeuron
-
{
-
public:
-
operator ThrType()const
-
{
-
const signal_t & a = …;//активация за текущий цикл
-
const signal_t & t = thrNorm;//нормализированный порог
-
-
ThrType ret = EqLess0;
-
if(a>0)
-
{
-
if(a>=t)
-
ret = GreaterT;
-
else
-
ret = Greater0;
-
}
-
return ret;
-
}
-
…
-
}
-
-
void BrainB2::someFunc()
-
{
-
for all clusters()
-
{
-
…
-
const ThrType tNin = *nIn;
-
const ThrType tNEn = *nEn;
-
-
if(tIn==GreaterT && tEn==GreaterT) {…}
-
if(tIn==Greater0 && tEn==EqLess0) {…}
-
if(tIn==Greater0 && tEn==Greater0) {…}
-
}
-
}
Конечно, код с использованием ThrType целесообразно использовать только в случае нескольких сложных проверок, иначе он становится менее эффективным, чем простой вызов inline-функции типа neuron::isActive() с единственным сравнением порога с активацией.