CStdSerialize *ClassFactory::CreateObject(std::string strClassType, std::string strObjectType, bool bThrowError)
{
	CStdSerialize *lpObject=NULL;

	strClassType = Std_ToUpper(Std_Trim(strClassType));

	if(strClassType == "EXTERNALSTIMULUS")
		lpObject = CreateExternalStimulus(strObjectType, bThrowError);
	else if(strClassType == "NEURALMODULE")
		lpObject = CreateNeuralModule(strObjectType, bThrowError);
	else if(strClassType == "DATACOLUMN")
		lpObject = CreateDataColumn(strObjectType, bThrowError);
	else if(strClassType == "GAIN")
		lpObject = CreateGain(strObjectType, bThrowError);
	else if(strClassType == "NEURON")
		lpObject = CreateNeuron(strObjectType, bThrowError);
	else if(strClassType == "SYNAPSE")
		lpObject = CreateSynapse(strObjectType, bThrowError);
	else if(strClassType == "SYNAPSETYPE")
		lpObject = CreateSynapseType(strObjectType, bThrowError);
	else if(strClassType == "IONCHANNEL")
		lpObject = CreateIonChannel(strObjectType, bThrowError);
	else
	{
		lpObject = NULL;
		if(bThrowError)
			THROW_PARAM_ERROR(Std_Err_lInvalidClassType, Std_Err_strInvalidClassType, "ClassType", strClassType);
	}

	return lpObject;
}
void NeuronSpeedTest(uint iterations, uint inputLength, ActivationFunctionPtr actFunction)
{
	Neuron* neuron;
	uint i;
	double* inputVector;
	StopWatch stopWatch;
	TimeInterval timeInterval;

	inputVector = ALLOC_ARRAY(double, inputLength);
	for(i = 0; i < inputLength; i++)
	{
		inputVector[i] = i;
	}

	neuron = CreateNeuron(inputLength, actFunction);

	Reset(&stopWatch);
	Start(&stopWatch);

	for(i = 0; i < iterations; i++)
	{
		ComputeNeuronOutput(neuron, inputVector);
	}

	Stop(&stopWatch);

	CalcElapsedMilliSeconds(&stopWatch);
	ToTimeIntervalStruct(&stopWatch, &timeInterval);

	printf("NEURON SPEED TEST:\nPARAMETRS:\n iterations: %d\n input length: %d\n", iterations, inputLength);
	printf("ELAPSED TIME:\n");
	printf(" milliseconds: %d\n", timeInterval.Miliseconds);
	printf(" seconds: %d\n", timeInterval.Seconds);
	printf(" minets: %d\n", timeInterval.Minets);
	printf(" hours: %d\n", timeInterval.Hours);
	printf("\n");

	free(inputVector);
	DisposeNeuron(neuron);
}
// Процедура линейного системогенеза, которая преобразует сеть из пулов в сеть из нейронов, как будто это одно и тоже (эволюция нейронных сетей, а не пулов)
void AgentLinearPrimarySystemogenesis(TNeuralNetwork* PrimaryNetwork, TPoolNetwork* PoolNetwork)
{
   EraseNeuralNetwork(PrimaryNetwork);

   TNeuralPool* CurrentPool = PoolNetwork->PoolsStructure;
   TNeuron* CurrentNeuron = PrimaryNetwork->NetworkStructure;
   int NeuronsQuantity = 0;
   // Проходим по всем пулам и создаем нейроны
   while (CurrentPool != NULL)
   {
      if (CurrentNeuron == NULL)
      {
         PrimaryNetwork->NetworkStructure = CreateNeuron(++NeuronsQuantity, CurrentPool->Type, CurrentPool->BiasMean, CurrentPool->Layer, true, CurrentPool, CurrentPool->ID, NULL, NULL, NULL);
         CurrentNeuron = PrimaryNetwork->NetworkStructure;
      }
      else
      {
         CurrentNeuron->next = CreateNeuron(++NeuronsQuantity, CurrentPool->Type, CurrentPool->BiasMean, CurrentPool->Layer, true, CurrentPool,  CurrentPool->ID, NULL, NULL, NULL);
         CurrentNeuron = CurrentNeuron->next;
      }
      CurrentPool = CurrentPool->next;
   }
   CurrentPool = PoolNetwork->PoolsStructure;
   CurrentNeuron = PrimaryNetwork->NetworkStructure;
   int SynapsesQuantity = 0; // Количество синапсов сети
   int PredConnectionQuantity = 0; // Количество предикторных связей

   while (CurrentPool != NULL)
   {
      // Создаем синапсы
      TPoolConnection* CurrentConnection = CurrentPool->ConnectednessSet;
      TSynapse* CurrentSynapse = CurrentNeuron->InSynapses;
      // Пока мы не прошли все входные связи текущего пула
      while (CurrentConnection != NULL)
      {
         if (CurrentConnection->Enabled)
         {
            if (CurrentSynapse == NULL) // Если нет еще ни одного синапса у текущего нейрона
            {
               CurrentNeuron->InSynapses = CreateSynapse(++SynapsesQuantity, CurrentConnection->WeightMean, CurrentConnection->Enabled, GetPointer2Neuron(PrimaryNetwork, CurrentConnection->PrePool->ID), CurrentNeuron, NULL);
               CurrentSynapse = CurrentNeuron->InSynapses;
            }
            else
            {
               CurrentSynapse->next = CreateSynapse(++SynapsesQuantity, CurrentConnection->WeightMean, CurrentConnection->Enabled, GetPointer2Neuron(PrimaryNetwork, CurrentConnection->PrePool->ID), CurrentNeuron, NULL);
               CurrentSynapse = CurrentSynapse->next;
            }
         }
         CurrentConnection = CurrentConnection->next;
      }
      // Создаем все предикторные связи
      TPoolPredConnection* CurrentPoolPredConnection = CurrentPool->PredConnectednessSet;
      TPredConnection* CurrentPredConnection= CurrentNeuron->PredConnections;
      // Пока мы не прошли все входные связи текущего пула
      while (CurrentPoolPredConnection != NULL)
      {
         if (CurrentPoolPredConnection->Enabled)
         {
            if (CurrentPredConnection == NULL) // Если нет еще ни одной связи у текущего нейрона
            {
               CurrentNeuron->PredConnections = CreatePredConnection(++PredConnectionQuantity, CurrentPoolPredConnection->Enabled, GetPointer2Neuron(PrimaryNetwork, CurrentPoolPredConnection->PrePool->ID), CurrentNeuron, NULL);
               CurrentPredConnection = CurrentNeuron->PredConnections;
            }
            else
            {
               CurrentPredConnection->next = CreatePredConnection(++PredConnectionQuantity, CurrentPoolPredConnection->Enabled, GetPointer2Neuron(PrimaryNetwork, CurrentPoolPredConnection->PrePool->ID), CurrentNeuron, NULL);
               CurrentPredConnection = CurrentPredConnection->next;
            }
         }

         CurrentPoolPredConnection = CurrentPoolPredConnection->next;
      }
      CurrentPool = CurrentPool->next;
      CurrentNeuron = CurrentNeuron->next;
   }
   // Заполняем данные про построенную сеть
   PrimaryNetwork->NeuronQuantity = NeuronsQuantity;
   PrimaryNetwork->SynapseQuantity = SynapsesQuantity;
   PrimaryNetwork->PredConnectionQuantity = PredConnectionQuantity;
}
// Построение ПОЛНОЙ (без отбора) первичной нейронной сети из генотипа (структуры пулов)
void BuildPrimaryNetwork(TNeuralNetwork* PrimaryNetwork, TPoolNetwork* PoolNetwork, double DevelopSynapseProbability, double DevelopPredConnectionProbability)
{
   int NeuronsQuantity = 0; // Количество нейронов в первичной сети
   TNeuralPool* CurrentPool= PoolNetwork->PoolsStructure; // Ссылка на текущий пул
   TNeuron* CurrentNeuron = PrimaryNetwork->NetworkStructure; // Ссылка на текущий нейрон
   int MaxCapacity = 0; // Максимальная размерность пула
   // Находим максимальную размерность пула
   for (int PoolNumber = 0; PoolNumber < PoolNetwork->PoolQuantity; PoolNumber++)
   {
      if (CurrentPool->Capacity > MaxCapacity)
         MaxCapacity = CurrentPool->Capacity;
      CurrentPool = CurrentPool->next;
   }
   // Создаем двумерный массив ссылок на все нейроны первичной сети, разбитых на принадлежность к пулу (чтобы потом их не искать, когда добавляем связи)
	//printf("%i ", MaxCapacity);
   //TNeuron* PoolAndNetworkStructure[PoolNetwork->PoolQuantity][MaxCapacity];
   TNeuron*** PoolAndNetworkStructure = new TNeuron**[PoolNetwork->PoolQuantity];
   for (int i=0; i<PoolNetwork->PoolQuantity; ++i)
      PoolAndNetworkStructure[i] = new TNeuron*[MaxCapacity];

   CurrentPool = PoolNetwork->PoolsStructure;
   // Проходим по всем пулам и создаем нейроны
   for (int PoolNumber = 0; PoolNumber < PoolNetwork->PoolQuantity; PoolNumber++)
   {
      // Создаем все нейроны пула
      for (int NeuronNumber = 0; NeuronNumber < CurrentPool->Capacity; NeuronNumber++)
      {
         if (CurrentNeuron == NULL) // Если в сети нет еще ни одного нейрона
         {
            PrimaryNetwork->NetworkStructure = CreateNeuron(++NeuronsQuantity, CurrentPool->Type, NormalDistribution(CurrentPool->BiasMean, CurrentPool->BiasVariance), CurrentPool->Layer, true, CurrentPool, CurrentPool->ID, NULL, NULL, NULL);
            CurrentNeuron = PrimaryNetwork->NetworkStructure;
         }
         else
         {
            CurrentNeuron->next = CreateNeuron(++NeuronsQuantity, CurrentPool->Type, NormalDistribution(CurrentPool->BiasMean, CurrentPool->BiasVariance), CurrentPool->Layer, true, CurrentPool, CurrentPool->ID, NULL, NULL, NULL);
            CurrentNeuron = CurrentNeuron->next;
         }
         PoolAndNetworkStructure[PoolNumber][NeuronNumber] = CurrentNeuron;
      }

      CurrentPool = CurrentPool->next;
   }
   CurrentPool = PoolNetwork->PoolsStructure;
   CurrentNeuron = PrimaryNetwork->NetworkStructure;
   int SynapsesQuantity = 0; // Количество синапсов сети
   int PredConnectionQuantity = 0; // Количество предикторных связей
   // Проходимсся по всем пулам и создаем синапсы
   for (int PoolNumber = 0; PoolNumber < PoolNetwork->PoolQuantity; ++PoolNumber)
   {
      for (int NeuronNumber = 0; NeuronNumber < CurrentPool->Capacity; ++NeuronNumber)
      {
         // Создаем синапсы
         TPoolConnection* CurrentConnection = CurrentPool->ConnectednessSet;
         TSynapse* CurrentSynapse = CurrentNeuron->InSynapses;
         // Пока мы не прошли все входные связи текущего пула
         while (CurrentConnection != NULL)
         {
            /*// Определяем количество входных связей для текущего нейрона от нейронов пресинаптического пула
            int CurrentSynapsesQuantity = rand() % 0.2*CurrentConnection->PrePool->Capacity;
            int PreNeuronNumber[CurrentSynapsesQuantity]; // Номера пресинаптических нейронов из текущего пресинаптического пула
            GenerateRandomNumbers(1, CurrentConnection->PrePool->Capacity, CurrentSynapsesQuantity, PreNeuronNumber);
            BubbleSort(PreNeuronNumber, CurrentSynapsesQuantity);

            for (int i=0; i<CurrentSynapsesQuantity; i++) // Создаем все текущие синапсы
            {
               if (CurrentSynapse = NULL) // Если нет еще ни одного синапса у текущего нейрона
               {
                  CurrentNeuron->InSynapses = CreateSynapse(++SynapsesQuantity, NormalDistribution(CurrentConnection->WeightMean, CurrentConnection->WeightVariance), CurrentConnection->Enabled, PoolAndNetworkStructure[CurrentConnection->PrePool->ID-1][PreNeuronNumber[i]-1], CurrentNeuron, NULL);
                  CurrentSynapse = CurrentNeuron->InSynapses;
               }
               else
               {
                  CurrentSynapse->next = CreateSynapse(++SynapsesQuantity, NormalDistribution(CurrentConnection->WeightMean, CurrentConnection->WeightVariance), CurrentConnection->Enabled, PoolAndNetworkStructure[CurrentConnection->PrePool->ID-1][PreNeuronNumber[i]-1], CurrentNeuron, NULL);
                  CurrentSynapse = CurrentSynapse->next;
               }
            }*/
            // Проходимся по всем потенциальным пресинаптическим нейронам и определяем развивается ли связь
            if (CurrentConnection->Enabled)
                  for (int CurrentPreNeuronNumber = 0; CurrentPreNeuronNumber < CurrentConnection->PrePool->Capacity; ++CurrentPreNeuronNumber )
                  {
                     if (UniformDistribution(0, 1) <= DevelopSynapseProbability)
                     {
                        if (CurrentSynapse == NULL) // Если нет еще ни одного синапса у текущего нейрона
                        {
                           CurrentNeuron->InSynapses = CreateSynapse(++SynapsesQuantity, NormalDistribution(CurrentConnection->WeightMean, CurrentConnection->WeightVariance), CurrentConnection->Enabled, PoolAndNetworkStructure[CurrentConnection->PrePool->ID-1][CurrentPreNeuronNumber], CurrentNeuron, NULL);
                           CurrentSynapse = CurrentNeuron->InSynapses;
                        }
                        else
                        {
                           CurrentSynapse->next = CreateSynapse(++SynapsesQuantity, NormalDistribution(CurrentConnection->WeightMean, CurrentConnection->WeightVariance), CurrentConnection->Enabled, PoolAndNetworkStructure[CurrentConnection->PrePool->ID-1][CurrentPreNeuronNumber], CurrentNeuron, NULL);
                           CurrentSynapse = CurrentSynapse->next;
                        }
                     }
                  }

            CurrentConnection = CurrentConnection->next;
         }

         //Создаем предикторные связи
         TPoolPredConnection* CurrentPredConnection = CurrentPool->PredConnectednessSet;
         TPredConnection* CurrentPredSynapse = CurrentNeuron->PredConnections;
         // Пока мы не прошли все входные предикторные связи текущего пула
         while (CurrentPredConnection != NULL)
         {
            /*// Определяем количество входных предикторных связей для текущего нейрона от нейронов пресинаптического пула
            int CurrentPredSynapsesQuantity = rand() % 0.2*CurrentPredConnection->PrePool->Capacity;
            int PreNeuronNumber[CurrentPredSynapsesQuantity]; // Номера пресинаптических нейронов из текущего пресинаптического пула
            GenerateRandomNumbers(1, CurrentPredConnection->PrePool->Capacity, CurrentPredSynapsesQuantity, PreNeuronNumber);
            BubbleSort(PreNeuronNumber, CurrentPredSynapsesQuantity);

            for (int i=0; i<CurrentPredSynapsesQuantity; i++) // Создаем все текущие предикторные связи
            {
               if (CurrentPredSynapse = NULL) // Если нет еще ни одной предикторной связи у текущего нейрона
               {
                  CurrentNeuron->PredConnections = CreatePredConnection(++PredConnectionQuantity, CurrentPredConnection->Enabled, PoolAndNetworkStructure[CurrentPredConnection->PrePool->ID-1][PreNeuronNumber[i]-1], CurrentNeuron, NULL);
                  CurrentPredSynapse = CurrentNeuron->PredConnections;
               }
               else
               {
                  CurrentPredSynapse->next = CreatePredConnection(++PredConnectionQuantity, CurrentPredConnection->Enabled, PoolAndNetworkStructure[CurrentPredConnection->PrePool->ID-1][PreNeuronNumber[i]-1], CurrentNeuron, NULL);
                  CurrentPredSynapse = CurrentPredSynapse->next;
               }
            }*/
            // Проходимся по всем потенциальным пресинаптическим нейронам для текущей предикторной связи и определяем развивается ли связь
            if (CurrentPredConnection->Enabled)
               for (int CurrentPreNeuronNumber = 0; CurrentPreNeuronNumber < CurrentPredConnection->PrePool->Capacity; ++CurrentPreNeuronNumber)
               {
                  if (UniformDistribution(0, 1) <= DevelopPredConnectionProbability)
                  {
                     if (CurrentPredSynapse == NULL) // Если нет еще ни одного синапса у текущего нейрона
                     {
                        CurrentNeuron->PredConnections = CreatePredConnection(++PredConnectionQuantity, CurrentPredConnection->Enabled, PoolAndNetworkStructure[CurrentPredConnection->PrePool->ID-1][CurrentPreNeuronNumber], CurrentNeuron, NULL);
                        CurrentPredSynapse = CurrentNeuron->PredConnections;
                     }
                     else
                     {
                        CurrentPredSynapse->next = CreatePredConnection(++PredConnectionQuantity, CurrentPredConnection->Enabled, PoolAndNetworkStructure[CurrentPredConnection->PrePool->ID-1][CurrentPreNeuronNumber], CurrentNeuron, NULL);
                        CurrentPredSynapse = CurrentPredSynapse->next;
                     }
                  }
               }

            CurrentPredConnection = CurrentPredConnection->next;
         }

         CurrentNeuron = CurrentNeuron->next;
      }
      CurrentPool = CurrentPool->next;
   }

   for (int i=0; i<PoolNetwork->PoolQuantity; ++i)
      delete [](PoolAndNetworkStructure[i]);
   delete []PoolAndNetworkStructure;

   // Заполняем данные про построенную сеть
   PrimaryNetwork->NeuronQuantity = NeuronsQuantity;
   PrimaryNetwork->SynapseQuantity = SynapsesQuantity;
   PrimaryNetwork->PredConnectionQuantity = PredConnectionQuantity;
}