Skip to content

Commit

Permalink
Merge branch 'GPAnalyzer' into GPLoop-amanXSimon-CGPA
Browse files Browse the repository at this point in the history
  • Loading branch information
amantham20 committed Dec 6, 2023
2 parents 97b5ac2 + 4e1c13d commit 22b38af
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 7 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ if (${BUILD_MAIN})
string(REPLACE ".cpp" "" EXE_NAME ${EXE_SOURCE})
# Create list of source files (currently just the one .cpp file)
# Create executable and link to includes / libraries
add_executable(${EXE_NAME} ${CMAKE_SOURCE_DIR}/source/${EXE_SOURCE} ${CMAKE_SOURCE_DIR}/source/core/Entity.cpp)
add_executable(${EXE_NAME} ${CMAKE_SOURCE_DIR}/source/${EXE_SOURCE} ${CMAKE_SOURCE_DIR}/source/core/Entity.cpp
source/Agents/GP/GPAgentAnalyze.h)
target_include_directories(${EXE_NAME}
PRIVATE ${CMAKE_SOURCE_DIR}/source
)
Expand Down
104 changes: 104 additions & 0 deletions source/Agents/GP/GPAgentAnalyze.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
//
// A class that analyzes the data of the best agent in the GP algorithm
// and saves it to a csv file
//

#pragma once

#include <vector>
#include <iostream>
#include <string>
#include <fstream>

namespace cowboys {

class GPAgentAnalyzer {
private:
/// The average fitness of the best agent
std::vector<double> average_fitness;

/// The max fitness of the best agent
std::vector<double> max_fitness;

/// The weighted score of the best agent
std::vector<double> elite_score;

/// The average score of the best agent
std::vector<double> average_score;

/// The number of agents with the max fitness
std::vector<double> max_agents;

public:
/**
* @brief Construct a new GP Agent Analyzer object
*/
GPAgentAnalyzer() = default;

/**
* @brief Destroy the GP Agent Analyzer object
*/
~GPAgentAnalyzer() = default;

/**
* @brief Adds the average fitness of the best agent
* @param fitness
*/
void addAverageFitness(double fitness) {
average_fitness.push_back(fitness);
}

/**
* @brief Adds the max fitness of the best agent
* @param fitness
*/
void addMaxFitness(double fitness) {
max_fitness.push_back(fitness);
}

/**
* @brief Adds the weighted score of the best agent
* @param score
*/
void addEliteScore(double score) {
elite_score.push_back(score);
}

/**
* @brief Adds the average score of the best agent
* @param score
*/
void addAverageScore(double score) {
average_score.push_back(score);
}

/**
* @brief Adds the number of agents with the max fitness
* @param num_agents
*/
void addNumAgentsWithMaxFitness(double num_agents) {
max_agents.push_back(num_agents);
}

/**
* @brief Saves the data to a csv file
*/
void saveToFile() {
// create a new file
std::ofstream file("gp_agent_analyzer.csv");

// write the data to the file
file << "average_fitness,max_fitness,average_elite_score,best_agent_weighted_score,agents_with_max_fitness\n";

for (int i = 0; i < average_fitness.size(); i++) {
file << average_fitness[i] << "," << max_fitness[i] << "," << elite_score[i] << "," << average_score[i] << "," << max_agents[i] << "\n";
}
std::cout << "Saved GP Agent Analyzer data to gp_agent_analyzer.csv" << std::endl;

// close the file
file.close();
}
};

} // namespace cowboys

19 changes: 14 additions & 5 deletions source/Agents/GP/GPTrainingLoop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@


#include "tinyxml2.h"

#include "GPAgentAnalyze.h"


namespace cowboys {

constexpr unsigned int TRAINING_SEED = 10; ///< If this is 0, then a random seed will be used
constexpr unsigned int TRAINING_SEED = 0; ///< If this is 0, then a random seed will be used

template<class AgentType, class EnvironmentType>
class GPTrainingLoop {
Expand All @@ -36,6 +36,7 @@ namespace cowboys {
std::vector<std::vector<cowboys::GPAgentBase *>> agents;
std::vector<std::vector<double>> TEMPAgentFitness;

GPAgentAnalyzer analyzer;

tinyxml2::XMLDocument topAgentsDoc;
tinyxml2::XMLDocument lastGenerationsTopAgentsDoc; // <- Saves the last 5 generations
Expand Down Expand Up @@ -487,6 +488,7 @@ namespace cowboys {
saveDataParams.countMaxAgents = countMaxAgents;
SaveDataCheckPoint(saveDataParams);


GpLoopMutateHelper();
resetEnvironments();

Expand All @@ -495,6 +497,7 @@ namespace cowboys {
generationEndTime - generationStartTime);
std::cout << "Generation " << generation << " took " << generationDuration.count() / 1000000.0 << " seconds"
<< std::endl;
analyzer.saveToFile();

}

Expand Down Expand Up @@ -597,6 +600,7 @@ namespace cowboys {

std::cout << "@@@@@@@@@@@@@@@@@@@@@@ " << "DataSaved" << " @@@@@@@@@@@@@@@@@@@@@@" << std::endl;

// analyzer.saveToFile(getSystemPath() / "fitness.csv");
lastGenerationsTopAgentsDoc.Clear();
ResetMainTagLastGenerations();
}
Expand Down Expand Up @@ -663,7 +667,11 @@ namespace cowboys {

std::cout << "Generation " << generation << " complete" << std::endl;
std::cout << "Average fitness: " << averageFitness << " ";
analyzer.addAverageFitness(averageFitness);

std::cout << "Max fitness: " << maxFitness << std::endl;
analyzer.addMaxFitness(maxFitness);



std::string tagName = "generation_" + std::to_string(generation);
Expand Down Expand Up @@ -723,12 +731,13 @@ namespace cowboys {
std::cout << std::endl;
}

std::cout << "with an average score of " << TEMPAgentFitness[bestAgent.first][bestAgent.second] << std::endl;
std::cout << "with best agent weighted score of " << TEMPAgentFitness[bestAgent.first][bestAgent.second] << std::endl;
std::cout << std::endl;

analyzer.addAverageScore(TEMPAgentFitness[bestAgent.first][bestAgent.second]);

std::cout << "Number of agents with max fitness: " << countMaxAgents << std::endl;
std::cout << "------------------------------------------------------------------" << std::endl;
analyzer.addNumAgentsWithMaxFitness(countMaxAgents);
return countMaxAgents;
}

Expand Down Expand Up @@ -867,7 +876,7 @@ namespace cowboys {
averageEliteFitness /= ELITE_POPULATION_SIZE;

std::cout << " --- average elite score " << averageEliteFitness << "------ " << std::endl;

analyzer.addEliteScore(averageEliteFitness);

const int MIDDLE_MUTATE_ENDBOUND = int(sortedAgents.size() * (1 - UNFIT_POPULATION_PERCENT));
const int MIDDLE_MUTATE_STARTBOUND = int(ELITE_POPULATION_PERCENT * sortedAgents.size());
Expand Down
2 changes: 2 additions & 0 deletions source/Worlds/MazeWorld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ class MazeWorld : public WorldBase {

MazeWorld(unsigned int seed = 0) : WorldBase(seed) {
// Create cell types

floor_id =
AddCellType("floor", "Floor that you can easily walk over.", ' ');
wall_id = AddCellType(
"wall", "Impenetrable wall that you must find a way around.", '#');


// Set cell type properties
type_options.at(floor_id).SetProperty(CellType::CELL_WALL);
// Load map
Expand Down
1 change: 0 additions & 1 deletion source/gp_train_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ int main() {

cowboys::GPTrainingLoop <cowboys::CGPAgent, cse491::MazeWorld> loop(false);


loop.Initialize(13, 200);
loop.Run(6, 50, num_threads, true);

Expand Down

0 comments on commit 22b38af

Please sign in to comment.