Matrix RandomMatrix (int N, long seed)
//
// Returns a N by N matrix with uniformly distributed deviates in the
// range [-0.5,0.5]. The index range for the matrix returned will be (1,N,1,N).
// If the seed argument is omitted or set to Zero then you will get a
// new random matrix whenever you call this function.
// If you supply a seed (negative and positive numbers are
// n o t distinct) you can reproduce the matrix of random numbers.
// The random generator Rnd() is used.
//
{
    static Ran002 rnd;
    static UniformDistribution U(-0.5,0.5,&rnd);

    if (seed) { // a seed was given
        rnd = Ran002(seed);
        U   = UniformDistribution(-0.5,0.5,&rnd);
    }

    if (N < 1) return NullMatrix;
    Matrix R(1,N,1,N);

    double *r = R.Store();
    for (int i = 0; i < R.Elements(); i++) r[i] = U();

    return R.Value();
}
void Node_Parameter::UpdateValue(double newstate, double newtime)
{
	if (UniformDistribution(0, 1)<ParameterUpdateChance)
	{
		CurValue += (rand() % ParameterUpdateRange - ParameterUpdateRange / 2)*ParameterUpdateStep;
	}
	return;
}
Exemple #3
0
// Процедура самообучения агента на одном такте времени
void AgentLearning(TNeuralNetwork* AgentNeuralNetwork, TLearningSettings* LearningSettings)
{
   TNeuron* CurrentNeuron = AgentNeuralNetwork->NetworkStructure;
   //int MismatchCheck[AgentNeuralNetwork->NeuronQuantity]; // Массив признаков рассогласованности нейронов сети
   int* MismatchCheck = new int[AgentNeuralNetwork->NeuronQuantity]; // Массив признаков рассогласованности нейронов сети

   // Сначала определяем рассогласованность всех нейронов (чтобы избежать проверки рассогласованности вновь включающихся нейронов)
   while (CurrentNeuron != NULL)
   {
      if ((CurrentNeuron->Type == 1) && (CurrentNeuron->Active))// Если нейрон внутренний и он активен
         MismatchCheck[CurrentNeuron->ID - 1] = MismatchDetection(CurrentNeuron, LearningSettings->MismatchSignificanceTreshold); // Определяем есть ли рассогласование
      else
         MismatchCheck[CurrentNeuron->ID - 1] = 0;
      CurrentNeuron = CurrentNeuron->next;
   }
   // Проводим процедуру обучения
   CurrentNeuron = AgentNeuralNetwork->NetworkStructure;
   while (CurrentNeuron != NULL)
   {
      if (MismatchCheck[CurrentNeuron->ID - 1]) // Если есть рассогласование
      {
         TNeuron* ActivatedNeuron = FindMostActiveNeuron(AgentNeuralNetwork, CurrentNeuron);
         if (ActivatedNeuron != NULL) // Если найден хотя бы один подходящий нейрон в родительском пуле (он еще не активен и был возбужден на текущем шаге)
         {
            AgentNeuralNetwork->SynapseQuantity += ModifySynapseStructure(ActivatedNeuron); // Модифицируем его синаптические веса
            double WeightValue = 0;
            if (MismatchCheck[CurrentNeuron->ID - 1] == 1) // Если это первый тип рассогласования
               WeightValue = UniformDistribution(0.5, 1);
            else // Если это второй тип рассогласования
               WeightValue = - UniformDistribution(0.5, 1);
            // Добавляем связь между рассогласованным и включающимся нейроном
            AgentNeuralNetwork->SynapseQuantity += AddInterPoolConnection(ActivatedNeuron, CurrentNeuron, AgentNeuralNetwork->SynapseQuantity, WeightValue);
            AgentNeuralNetwork->PredConnectionQuantity += ModifyPredConnectionsStructure(ActivatedNeuron, CurrentNeuron, AgentNeuralNetwork->PredConnectionQuantity);
            ActivatedNeuron->Active = true;
            ActivatedNeuron->CurrentOut = 0;
         }
      }
      CurrentNeuron = CurrentNeuron->next;
   }
   delete []MismatchCheck;
   fix_synapses_id(AgentNeuralNetwork);
   fix_pred_connections_id(AgentNeuralNetwork);
}
bool Node_Parameter::Mutation(Node** node)
{
	double mutatechance = UniformDistribution(0, 1);
	if (mutatechance<NonOperationMutateChance)
	{
		(*node) = new Node_State();
		return true;
	}
	else if (mutatechance<2*NonOperationMutateChance)
	{
		(*node) = new Node_Time();
		return true;
	}
	return false;
}
void GazeboOdometryPlugin::Load(physics::ModelPtr _model,
                                sdf::ElementPtr _sdf) {
  if (kPrintOnPluginLoad) {
    gzdbg << __FUNCTION__ << "() called." << std::endl;
  }

  // Store the pointer to the model
  model_ = _model;
  world_ = model_->GetWorld();

  SdfVector3 noise_normal_position;
  SdfVector3 noise_normal_quaternion;
  SdfVector3 noise_normal_linear_velocity;
  SdfVector3 noise_normal_angular_velocity;
  SdfVector3 noise_uniform_position;
  SdfVector3 noise_uniform_quaternion;
  SdfVector3 noise_uniform_linear_velocity;
  SdfVector3 noise_uniform_angular_velocity;
  const SdfVector3 zeros3(0.0, 0.0, 0.0);

  odometry_queue_.clear();

  if (_sdf->HasElement("robotNamespace"))
    namespace_ = _sdf->GetElement("robotNamespace")->Get<std::string>();
  else
    gzerr << "[gazebo_odometry_plugin] Please specify a robotNamespace.\n";

  node_handle_ = gazebo::transport::NodePtr(new transport::Node());

  // Initialise with default namespace (typically /gazebo/default/)
  node_handle_->Init();

  if (_sdf->HasElement("linkName"))
    link_name_ = _sdf->GetElement("linkName")->Get<std::string>();
  else
    gzerr << "[gazebo_odometry_plugin] Please specify a linkName.\n";
  link_ = model_->GetLink(link_name_);
  if (link_ == NULL)
    gzthrow("[gazebo_odometry_plugin] Couldn't find specified link \""
            << link_name_ << "\".");

  if (_sdf->HasElement("covarianceImage")) {
    std::string image_name =
        _sdf->GetElement("covarianceImage")->Get<std::string>();
    covariance_image_ = cv::imread(image_name, CV_LOAD_IMAGE_GRAYSCALE);
    if (covariance_image_.data == NULL)
      gzerr << "loading covariance image " << image_name << " failed"
            << std::endl;
    else
      gzlog << "loading covariance image " << image_name << " successful"
            << std::endl;
  }

  if (_sdf->HasElement("randomEngineSeed")) {
    random_generator_.seed(
        _sdf->GetElement("randomEngineSeed")->Get<unsigned int>());
  } else {
    random_generator_.seed(
        std::chrono::system_clock::now().time_since_epoch().count());
  }
  getSdfParam<std::string>(_sdf, "poseTopic", pose_pub_topic_, pose_pub_topic_);
  getSdfParam<std::string>(_sdf, "poseWithCovarianceTopic",
                           pose_with_covariance_stamped_pub_topic_,
                           pose_with_covariance_stamped_pub_topic_);
  getSdfParam<std::string>(_sdf, "positionTopic", position_stamped_pub_topic_,
                           position_stamped_pub_topic_);
  getSdfParam<std::string>(_sdf, "transformTopic", transform_stamped_pub_topic_,
                           transform_stamped_pub_topic_);
  getSdfParam<std::string>(_sdf, "odometryTopic", odometry_pub_topic_,
                           odometry_pub_topic_);
  getSdfParam<std::string>(_sdf, "parentFrameId", parent_frame_id_,
                           parent_frame_id_);
  getSdfParam<std::string>(_sdf, "childFrameId", child_frame_id_,
                           child_frame_id_);
  getSdfParam<SdfVector3>(_sdf, "noiseNormalPosition", noise_normal_position,
                          zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseNormalQuaternion",
                          noise_normal_quaternion, zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseNormalLinearVelocity",
                          noise_normal_linear_velocity, zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseNormalAngularVelocity",
                          noise_normal_angular_velocity, zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseUniformPosition", noise_uniform_position,
                          zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseUniformQuaternion",
                          noise_uniform_quaternion, zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseUniformLinearVelocity",
                          noise_uniform_linear_velocity, zeros3);
  getSdfParam<SdfVector3>(_sdf, "noiseUniformAngularVelocity",
                          noise_uniform_angular_velocity, zeros3);
  getSdfParam<int>(_sdf, "measurementDelay", measurement_delay_,
                   measurement_delay_);
  getSdfParam<int>(_sdf, "measurementDivisor", measurement_divisor_,
                   measurement_divisor_);
  getSdfParam<double>(_sdf, "unknownDelay", unknown_delay_, unknown_delay_);
  getSdfParam<double>(_sdf, "covarianceImageScale", covariance_image_scale_,
                      covariance_image_scale_);

  parent_link_ = world_->GetEntity(parent_frame_id_);
  if (parent_link_ == NULL && parent_frame_id_ != kDefaultParentFrameId) {
    gzthrow("[gazebo_odometry_plugin] Couldn't find specified parent link \""
            << parent_frame_id_ << "\".");
  }

  position_n_[0] = NormalDistribution(0, noise_normal_position.X());
  position_n_[1] = NormalDistribution(0, noise_normal_position.Y());
  position_n_[2] = NormalDistribution(0, noise_normal_position.Z());

  attitude_n_[0] = NormalDistribution(0, noise_normal_quaternion.X());
  attitude_n_[1] = NormalDistribution(0, noise_normal_quaternion.Y());
  attitude_n_[2] = NormalDistribution(0, noise_normal_quaternion.Z());

  linear_velocity_n_[0] =
      NormalDistribution(0, noise_normal_linear_velocity.X());
  linear_velocity_n_[1] =
      NormalDistribution(0, noise_normal_linear_velocity.Y());
  linear_velocity_n_[2] =
      NormalDistribution(0, noise_normal_linear_velocity.Z());

  angular_velocity_n_[0] =
      NormalDistribution(0, noise_normal_angular_velocity.X());
  angular_velocity_n_[1] =
      NormalDistribution(0, noise_normal_angular_velocity.Y());
  angular_velocity_n_[2] =
      NormalDistribution(0, noise_normal_angular_velocity.Z());

  position_u_[0] = UniformDistribution(-noise_uniform_position.X(),
                                       noise_uniform_position.X());
  position_u_[1] = UniformDistribution(-noise_uniform_position.Y(),
                                       noise_uniform_position.Y());
  position_u_[2] = UniformDistribution(-noise_uniform_position.Z(),
                                       noise_uniform_position.Z());

  attitude_u_[0] = UniformDistribution(-noise_uniform_quaternion.X(),
                                       noise_uniform_quaternion.X());
  attitude_u_[1] = UniformDistribution(-noise_uniform_quaternion.Y(),
                                       noise_uniform_quaternion.Y());
  attitude_u_[2] = UniformDistribution(-noise_uniform_quaternion.Z(),
                                       noise_uniform_quaternion.Z());

  linear_velocity_u_[0] = UniformDistribution(
      -noise_uniform_linear_velocity.X(), noise_uniform_linear_velocity.X());
  linear_velocity_u_[1] = UniformDistribution(
      -noise_uniform_linear_velocity.Y(), noise_uniform_linear_velocity.Y());
  linear_velocity_u_[2] = UniformDistribution(
      -noise_uniform_linear_velocity.Z(), noise_uniform_linear_velocity.Z());

  angular_velocity_u_[0] = UniformDistribution(
      -noise_uniform_angular_velocity.X(), noise_uniform_angular_velocity.X());
  angular_velocity_u_[1] = UniformDistribution(
      -noise_uniform_angular_velocity.Y(), noise_uniform_angular_velocity.Y());
  angular_velocity_u_[2] = UniformDistribution(
      -noise_uniform_angular_velocity.Z(), noise_uniform_angular_velocity.Z());

  // Fill in covariance. We omit uniform noise here.
  Eigen::Map<Eigen::Matrix<double, 6, 6> > pose_covariance(
      pose_covariance_matrix_.data());
  Eigen::Matrix<double, 6, 1> pose_covd;

  pose_covd << noise_normal_position.X() * noise_normal_position.X(),
      noise_normal_position.Y() * noise_normal_position.Y(),
      noise_normal_position.Z() * noise_normal_position.Z(),
      noise_normal_quaternion.X() * noise_normal_quaternion.X(),
      noise_normal_quaternion.Y() * noise_normal_quaternion.Y(),
      noise_normal_quaternion.Z() * noise_normal_quaternion.Z();
  pose_covariance = pose_covd.asDiagonal();

  // Fill in covariance. We omit uniform noise here.
  Eigen::Map<Eigen::Matrix<double, 6, 6> > twist_covariance(
      twist_covariance_matrix_.data());
  Eigen::Matrix<double, 6, 1> twist_covd;

  twist_covd << noise_normal_linear_velocity.X() *
                    noise_normal_linear_velocity.X(),
      noise_normal_linear_velocity.Y() * noise_normal_linear_velocity.Y(),
      noise_normal_linear_velocity.Z() * noise_normal_linear_velocity.Z(),
      noise_normal_angular_velocity.X() * noise_normal_angular_velocity.X(),
      noise_normal_angular_velocity.Y() * noise_normal_angular_velocity.Y(),
      noise_normal_angular_velocity.Z() * noise_normal_angular_velocity.Z();
  twist_covariance = twist_covd.asDiagonal();

  // Listen to the update event. This event is broadcast every
  // simulation iteration.
  updateConnection_ = event::Events::ConnectWorldUpdateBegin(
      boost::bind(&GazeboOdometryPlugin::OnUpdate, this, _1));
}
// Функция отбора активирующихся нейронов
void NeuronsSelection(TNeuralNetwork* PrimaryNetwork, double* const _SummaryPotential, int ActivationNeuronsQuantity)
{
	double* const SummaryPotential = new double[PrimaryNetwork->NeuronQuantity];
	memcpy(SummaryPotential, _SummaryPotential, sizeof(double) * PrimaryNetwork->NeuronQuantity);

	int InputOuputNeuronsQuantity = 0;
   TNeuron* CurrentNeuron = PrimaryNetwork->NetworkStructure;
   // Считаем кол-во входных и выходных нейронов
   while (CurrentNeuron != NULL)
   {
      if (CurrentNeuron->Type != 1)
         ++InputOuputNeuronsQuantity;
      CurrentNeuron = CurrentNeuron->next;
   }

   // Вариант с использованием рулеточного алгоритма
   // Работаем только с той частью списка, в которой записаны интер-нейроны
   // Сначала нормируем все значения - так чтобы у нейронов с отрицательным потенциалом была возможность отобраться
   double MinPotential = 0;
   // Ищем минимальный отрицательный суммарный потенциал
   for (int CurrentNeuron = InputOuputNeuronsQuantity; CurrentNeuron<PrimaryNetwork->NeuronQuantity; CurrentNeuron++)
      if (MinPotential > SummaryPotential[CurrentNeuron])
         MinPotential = SummaryPotential[CurrentNeuron];
   // Инвертируем оставшиеся потенциалы
   for (int CurrentNeuron = InputOuputNeuronsQuantity; CurrentNeuron<PrimaryNetwork->NeuronQuantity; CurrentNeuron++)
      SummaryPotential[CurrentNeuron] -= MinPotential - 1; // Делаем так, чтобы ни у одного нейрона не было нулевого суммарного потенциала
   
   double TotalPotential = 0;
   double CurrentNeuronsQuantity = 0;
   for (int CurrentNeuron = InputOuputNeuronsQuantity; CurrentNeuron < PrimaryNetwork->NeuronQuantity; CurrentNeuron++)
      TotalPotential += SummaryPotential[CurrentNeuron];
   const double CheckEmpty = -5000.0F; // Признак выбранного элемента

   // Пока есть хотя бы один нейрон с ненулевым суммарным потенциалом и не набрано достаточно кол-во нейронов - прогоняем рулеточный алгоритм
   while (CurrentNeuronsQuantity<ActivationNeuronsQuantity)
   {
      double RandomPotential = UniformDistribution(0, TotalPotential, false, false);//(rand()%1000/1000.0) * TotalPotential;
      double CurrentPotential = 0;
      int CurrentNeuronNum = InputOuputNeuronsQuantity;
		//char tmp_str[10000];
		//strcpy(tmp_str, "");
      while (RandomPotential > CurrentPotential)
		{
         CurrentPotential += max(SummaryPotential[CurrentNeuronNum++], 0.0);
			//sprintf(tmp_str, "%s%i: %.4f : %.4f |\t", tmp_str, CurrentNeuronNum-1, max(SummaryPotential[CurrentNeuronNum-1], 0.0), CurrentPotential);
		}
		if (CurrentNeuronNum > PrimaryNetwork->NeuronQuantity){
			printf("\n!! Error !! - %i (%i) - %.6f , %.6f , %.6f\n", CurrentNeuronNum, PrimaryNetwork->NeuronQuantity, RandomPotential, TotalPotential, CurrentPotential);
			//char c= getchar();
		}
		//printf("%i(%i) ", CurrentNeuronNum, PrimaryNetwork->NeuronQuantity);
      // Уменьшаем суммарный потенциал на величину выбранного нейрона
      TotalPotential -= SummaryPotential[CurrentNeuronNum-1];

      SummaryPotential[CurrentNeuronNum - 1] = CheckEmpty; //!!!
      CurrentNeuronsQuantity++;
   }
   /*Детерминированный вариант
   for (int i=0; i<ActivationNeuronsQuantity; i++)
   {
      double CurrentMax=-999;
      int CurrentMaxNumber;
      for (int j=InputOuputNeuronsQuantity; j<PrimaryNetwork->NeuronsQuantity; j++)
         if (CurrentMax < SummaryPotential[j])
         {
            CurrentMax = SummaryPotential[j];
            CurrentMaxNumber = j;
         }
      SummaryPotential[j] = -1000;
   }*/

   //Изменяем информацию о нейронах (разделяем их на активные и молчащие)
   CurrentNeuron = PrimaryNetwork->NetworkStructure;
   while (CurrentNeuron!=NULL)
   {
      if (CurrentNeuron->Type == 1)
         if (SummaryPotential[CurrentNeuron->ID-1] == CheckEmpty)
            CurrentNeuron->Active = 1;
         else CurrentNeuron->Active = 0;
      else
         CurrentNeuron->Active=1;

      CurrentNeuron = CurrentNeuron->next;
   }

	delete []SummaryPotential;
}
// Построение ПОЛНОЙ (без отбора) первичной нейронной сети из генотипа (структуры пулов)
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;
}
// Процедура генерации стартовой популяции для модернизированного эвлюционного алгоритма
void InitFirstGeneration_ModernEvolution(TAgentGenomePopulation* AgentGenomePopulation, int EnvironmentResolution, int OutputResolution, int InitialPoolCapacity)
{
   for (int CurrentAgent=0; CurrentAgent<AgentGenomePopulation->PopulationAgentQuantity; CurrentAgent++) // Создаем популяцию
   {
      AgentGenomePopulation->AgentGenome[CurrentAgent] = CreatePoolNetwork();
      TNeuralPool* CurrentPool=NULL;
      int CurrentPoolNumber = 0;
      for (CurrentPoolNumber=0; CurrentPoolNumber < EnvironmentResolution; ++CurrentPoolNumber) // Создаем сенсорные пулы
         if (CurrentPool == NULL) // Если это первый пул
         {

            AgentGenomePopulation->AgentGenome[CurrentAgent]->PoolsStructure = CreateNeuralPool(CurrentPoolNumber + 1, 0, 1, UniformDistribution(-1,1), 0, 1, NULL, NULL, NULL);
            CurrentPool = AgentGenomePopulation->AgentGenome[CurrentAgent]->PoolsStructure;
         }
         else
         {
            CurrentPool->next = CreateNeuralPool(CurrentPoolNumber + 1, 0, 1, UniformDistribution(-1,1), 0, 1, NULL, NULL, NULL);
            CurrentPool = CurrentPool->next;
         }

      // Создаем выходные пулы
      for (CurrentPoolNumber=EnvironmentResolution; CurrentPoolNumber<EnvironmentResolution+OutputResolution; ++CurrentPoolNumber)
      {
         CurrentPool->next = CreateNeuralPool(CurrentPoolNumber + 1, 2, 1, UniformDistribution(-1,1), 0, 3, NULL, NULL, NULL);
         CurrentPool = CurrentPool->next;
      }

      // Создаем единственный вставочный пул
      CurrentPool->next = CreateNeuralPool(CurrentPoolNumber + 1, 1, InitialPoolCapacity, UniformDistribution(-1,1), 0, 2, NULL, NULL, NULL);
      CurrentPool = CurrentPool->next;

      TNeuralPool* CurrentPool_2 = AgentGenomePopulation->AgentGenome[CurrentAgent]->PoolsStructure;
      while (CurrentPool_2->Type != 2) // Находим первый вставочный нейрон
         CurrentPool_2 = CurrentPool_2->next;

      // Заполняем входящие связи выходных пулов от вставочного пула
      for (int CurrentConnectionNumber=0; CurrentConnectionNumber<OutputResolution; ++CurrentConnectionNumber)
      {
         CurrentPool_2->ConnectednessSet = CreatePoolConnection(CurrentConnectionNumber + 1, UniformDistribution(-1,1), 0, 1, static_cast<double>(CurrentConnectionNumber + 1), 0, CurrentPool, CurrentPool_2, NULL);
         CurrentPool_2 = CurrentPool_2->next;
      }

      CurrentPool_2 = AgentGenomePopulation->AgentGenome[CurrentAgent]->PoolsStructure; // Ссылка на первый сенсорный пул
      // Заполняем входящие связи вставочного пула от входных пулов
      TPoolConnection* CurrentConnection = NULL;
      for (int CurrentConnectionNumber=OutputResolution; CurrentConnectionNumber<OutputResolution+EnvironmentResolution; ++CurrentConnectionNumber)
         if (CurrentConnection == NULL) // Если это первая входящая связь у вставочного пула
         {
            CurrentPool->ConnectednessSet = CreatePoolConnection(CurrentConnectionNumber + 1, UniformDistribution(-1,1), 0, 1, static_cast<double>(CurrentConnectionNumber + 1), 0, CurrentPool_2, CurrentPool, NULL);
            CurrentConnection = CurrentPool->ConnectednessSet;
            CurrentPool_2 = CurrentPool_2->next; // Сдвигаемся на следующий сенсорный пул
         }
         else
         {
            CurrentConnection->next = CreatePoolConnection(CurrentConnectionNumber + 1, UniformDistribution(-1,1), 0, 1, static_cast<double>(CurrentConnectionNumber + 1), 0, CurrentPool_2, CurrentPool, NULL);
            CurrentConnection = CurrentConnection->next;
            CurrentPool_2 = CurrentPool_2->next; // Сдвигаемся на следующий сенсорный пул
         }
      AgentGenomePopulation->AgentGenome[CurrentAgent]->PoolQuantity = EnvironmentResolution + OutputResolution + 1;
      AgentGenomePopulation->AgentGenome[CurrentAgent]->ConnectionQuantity = EnvironmentResolution + OutputResolution;
      AgentGenomePopulation->AgentGenome[CurrentAgent]->PredConnectionQuantity = 0;
   }
}