I am trying to build a little game "snake" playing by a neural network. I created 2 classes, one for the neural network and another one for the game. The game has an instance of the class neural network and I used an unique_ptr to avoid a basic pointer and to train with it.
The neural network class has 2 mains private variables that use the Eigen::MatrixXd and Eigen::VectorXd.
When all snakes are dead it's time to do a new generation, so I call a function that create this:
std::vector<std::pair<std::unique_ptr<NeuralNetwork>, int>> paired_vector;
(int for the points)
I push_back my values like this:
for (int i{ 0 }; i < m_number_player; i++)
{
// make_pair to create a pair and std::move to move the content of each unique_ptr to the paired_vector
paired_vector.push_back(std::make_pair(std::move(m_players[i]), m_points[i]));
}
after, I sort my vector with the points of each snake:
std::sort(paired_vector.begin(), paired_vector.end(), [](const auto& a, const auto& b) { return a.second > b.second; });
and here is the problem:
// crossOver the bests
for (int i{ 10 }; i < m_number_player; i++)
{
int random1{ rand() % 11 };
int random2{};
do {
random2 = rand() % 11;
} while (random2 == random1);
std::vector<Eigen::MatrixXd> value_returned = crossOverWeights(paired_vector[random2].first.get()->getWeigths(), paired_vector[random1].first.get()->getWeigths());
paired_vector[i].first.get()->setWeigths(value_returned);
This part has to choose 2 random "snake" in the top 10. Then the function has to "mix" the weights of 2 best snakes to a bad snake. So I call the member function setWeights() to send the new weights with a function that returns the value. This function take 2 parameters:
std::vector<Eigen::MatrixXd> Game::crossOverWeights(const std::vector<Eigen::MatrixXd>& second, const std::vector<Eigen::MatrixXd>& first)
I have 4 functions like that: crossOverWeights, crossOverBiases, mutationWeights and mutationBiases that works exactly the same.
Inside the function :
std::vector<Eigen::MatrixXd> Game::crossOverWeights(const std::vector<Eigen::MatrixXd>& second, const std::vector<Eigen::MatrixXd>& first)
{
std::vector<Eigen::MatrixXd> temp(second.size());
// loop through all the weights
for (int i{ 0 }; i < static_cast<int>(second.size()); i++)
{
// change the weights of the half first part
if (i <= static_cast<int>(second.size() / 2))
temp[i] = first[i];
else // stay unchanged
temp[i] = second[i];
}
return temp;
}
The problem is: when I have 50 snakes the program crash at the 2nd generation. When I have 11 snakes, the program could crash at the fifth generation or something like that.
The error is "HEAP CORRUPTION DETECTED: After normal block...CRT detected that the application wrote to memory after end of heap buffer" So I think I reach the end of the vector or the Eigen::MatrixXd but how is it possible? When I set up the new weights I do that:
m_weights.clear();
m_weights = new_weights;
Maybe someone knows the problem and can help me ? Thank you and don't hesitate to ask me for more details