Exemplo n.º 1
0
bool Population::init(const IndividualContainer &origin, unsigned int popSize) {

	if (!origin.areEvaluated()) {
		std::cout << "Trying to initialize population of n best Robots from "
				"IndividualContainer which is not evaluated!" << std::endl;
		return false;
	}

	for (unsigned int i = 0; i < origin.size(); i++) {
		this->push_back(origin[i]);
	}

	this->sort();

	// idea was to call this->resize(popSize);, but that requires a default
	// constructor to be present for RobotRepresentation, which is not the case
	// on purpose
	while (this->size() > popSize) {
		this->pop_back();
	}

	this->evaluated_ = true;

	return true;
}
Exemplo n.º 2
0
namespace robogen {
void init(unsigned int seed, std::string outputDirectory,
		std::string confFileName, bool overwrite, bool saveAll);

void printUsage(char *argv[]) {
	std::cout << std::endl << "USAGE: " << std::endl << "      "
			<< std::string(argv[0])
			<< " <SEED, INTEGER> <OUTPUT_DIRECTORY, STRING> "
			<< "<CONFIGURATION_FILE, STRING> [<OPTIONS>]" << std::endl
			<< std::endl << "WHERE: " << std::endl
			<< "      <SEED> is a number to seed "
			<< "the pseudorandom number generator." << std::endl << std::endl
			<< "      <OUTPUT_DIRECTORY> is the directory to write output "
			<< "files to." << std::endl << std::endl
			<< "      <CONFIGURATION_FILE> is the evolution"
			<< " configuration file to use." << std::endl << std::endl
			<< "OPTIONS: " << std::endl << "      --help" << std::endl
			<< "          Print all configuration options and exit."
			<< std::endl << std::endl << "      --overwrite" << std::endl
			<< "          Overwrite existing output file directory if it "
			<< "exists." << std::endl
			<< "          (Default is to keep creating new output "
			<< "directories with incrementing suffixes)." << std::endl
			<< std::endl << "      --save-all" << std::endl
			<< "          Save all individuals instead of just the generation"
			<< "best." << std::endl << std::endl;

}

void printHelp() {
	boost::shared_ptr<EvolverConfiguration> conf = boost::shared_ptr<
			EvolverConfiguration>(new EvolverConfiguration());
	conf->init("help");
	std::cout << std::endl;
	boost::shared_ptr<RobogenConfig> robotConf =
			ConfigurationReader::parseConfigurationFile("help");
}

boost::shared_ptr<Population> population;
IndividualContainer children;
boost::shared_ptr<NeatContainer> neatContainer;
boost::shared_ptr<RobogenConfig> robotConf;
boost::shared_ptr<EvolverConfiguration> conf;
boost::shared_ptr<EvolverLog> log;
bool neat;
boost::shared_ptr<Selector> selector;
boost::shared_ptr<Mutator> mutator;
unsigned int generation;
boost::random::mt19937 rng;

std::vector<Socket*> sockets;

void parseArgsThenInit(int argc, char* argv[]) {

	startRobogen();

	// ---------------------------------------
	// verify usage and load configuration
	// ---------------------------------------
	if (argc > 1 && std::string(argv[1]) == "--help") {
		printUsage(argv);
		printHelp();
		exitRobogen(EXIT_SUCCESS);
	}

	if ((argc < 4)) {
		printUsage(argv);
		std::cout << "RUN: " << std::endl << std::endl
				<< "      " << std::string(argv[0])
				<< " --help to see all configuration options."
				<< std::endl << std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	unsigned int seed = atoi(argv[1]);

	std::string outputDirectory = std::string(argv[2]);
	std::string confFileName = std::string(argv[3]);

	bool overwrite = false;
	bool saveAll = false;
	int currentArg = 4;
	for (; currentArg < argc; currentArg++) {
		if (std::string("--help").compare(argv[currentArg]) == 0) {
			printUsage(argv);
			printHelp();
			exitRobogen(EXIT_SUCCESS);
		} else if (std::string("--overwrite").compare(argv[currentArg]) == 0) {
			overwrite = true;
		} else if (std::string("--save-all").compare(argv[currentArg]) == 0) {
			saveAll = true;
		} else {
			std::cerr << std::endl << "Invalid option: " << argv[currentArg]
							 << std::endl << std::endl;
			printUsage(argv);
			exitRobogen(EXIT_FAILURE);
		}

	}

	init(seed, outputDirectory, confFileName, overwrite, saveAll);

}

void init(unsigned int seed, std::string outputDirectory,
		std::string confFileName, bool overwrite, bool saveAll) {

	// Seed random number generator

	rng.seed(seed);

	conf.reset(new EvolverConfiguration());
	if (!conf->init(confFileName)) {
		std::cerr << "Problems parsing the evolution configuration file. Quit."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	robotConf = ConfigurationReader::parseConfigurationFile(
			conf->simulatorConfFile);
	if (robotConf == NULL) {
		std::cerr << "Problems parsing the robot configuration file. Quit."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	// ---------------------------------------
	// Set up evolution
	// ---------------------------------------

	if (conf->selection == conf->DETERMINISTIC_TOURNAMENT) {
		selector.reset(new DeterministicTournament(conf->tournamentSize, rng));
	} else {
		std::cerr << "Selection type id " << conf->selection << " unknown."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	mutator.reset(new Mutator(conf, rng));
	log.reset(new EvolverLog());
	try {
		if (!log->init(conf, robotConf, outputDirectory, overwrite, saveAll)) {
			std::cerr << "Error creating evolver log. Aborting." << std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	} catch (std::exception& e) {
		std::cerr << e.what() << std::endl;
		exitRobogen(EXIT_FAILURE);
	} catch (...) {
		std::cerr << "non standard exception " << std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	// ---------------------------------------
	// parse robot from file & initialize population
	// ---------------------------------------

	boost::shared_ptr<RobotRepresentation> referenceBot(
			new RobotRepresentation());
	bool growBodies = false;
	if (conf->evolutionMode == EvolverConfiguration::BRAIN_EVOLVER
			&& conf->referenceRobotFile.compare("") == 0) {
		std::cerr << "Trying to evolve brain, but no robot file provided."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	} else if (conf->referenceRobotFile.compare("") != 0) {
		if (!referenceBot->init(conf->referenceRobotFile)) {
			std::cerr << "Failed interpreting robot from text file"
					<< std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	} else { //doing body evolution and don't have a reference robot
		if (referenceBot->init()) {
			growBodies = true;
		} else {
			std::cerr << "Failed creating base robot for body evolution"
					<< std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	}

	neat = (conf->evolutionaryAlgorithm == EvolverConfiguration::HYPER_NEAT);
	population.reset(new Population());
	if (!population->init(referenceBot, conf->mu, mutator, growBodies,
			(!(conf->useBrainSeed || neat)) ) ) {
		std::cerr << "Error when initializing population!" << std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	if (neat) {
		neatContainer.reset(new NeatContainer(conf, population, seed, rng));
	}

	// ---------------------------------------
	// open sockets for communication with simulator processes
	// ---------------------------------------
#ifndef EMSCRIPTEN
	sockets.resize(conf->sockets.size());
	for (unsigned int i = 0; i < conf->sockets.size(); i++) {
		sockets[i] = new TcpSocket;
#ifndef FAKEROBOTREPRESENTATION_H // do not bother with sockets when using
		// benchmark
		if (!sockets[i]->open(conf->sockets[i].first,
				conf->sockets[i].second)) {
			std::cerr << "Could not open connection to simulator" << std::endl;
			exitRobogen(EXIT_FAILURE);
		}
#endif
	}
#endif

	// ---------------------------------------
	// run evolution TODO stopping criterion
	// ---------------------------------------

	if(neat) {
		if(!neatContainer->fillPopulationWeights(population)) {
			std::cerr << "Filling weights from NEAT failed." << std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	}

	generation = 1;
	population->evaluate(robotConf, sockets);
}

void mainEvolutionLoop();

void postEvaluateNEAT() {
	population->sort(true);
	mainEvolutionLoop();
}

void postEvaluateStd() {

	// comma or plus?
	if (conf->replacement == conf->PLUS_REPLACEMENT) {
		children += *population.get();
	}

	// replace
	population.reset(new Population());
	if (!population->init(children, conf->mu)) {
		std::cout << "Error when initializing population!" << std::endl;
		exitRobogen(EXIT_FAILURE);
	}
	mainEvolutionLoop();
}

void triggerPostEvaluate() {
	if (generation == 1) {
		mainEvolutionLoop();
	} else {
		if (neat) {
			postEvaluateNEAT();
		} else {
			postEvaluateStd();
		}
	}
}

void mainEvolutionLoop() {
#ifdef EMSCRIPTEN
	std::stringstream ss;
	double best, average, stddev;
	population->getStat(best, average, stddev);
	ss << "{best : " << best << ", average : " << average << ", stddev : "
			<< stddev << ", generation : " << generation << "}";
	sendJSEvent("stats", ss.str());
#endif

	std::cout << "mainEvolutionLoop" << std::endl;
	if (!log->logGeneration(generation, *population.get())) {
		exitRobogen(EXIT_FAILURE);
	}

	generation++;


	if (generation <= conf->numGenerations) {
		std::cout << "Generation " << generation << std::endl;
		children.clear();

		// create children
		if (neat) {
			//neatPopulation->Epoch();
			if(!neatContainer->produceNextGeneration(population)) {
				std::cerr << "Producing next generation from NEAT failed."
						<< std::endl;
				exitRobogen(EXIT_FAILURE);
			}
			population->evaluate(robotConf, sockets);

		} else {
			selector->initPopulation(population);
			unsigned int numOffspring = 0;
			while (numOffspring < conf->lambda) {

				std::pair<boost::shared_ptr<RobotRepresentation>,
						boost::shared_ptr<RobotRepresentation> > selection;
				if (!selector->select(selection.first)) {
					std::cerr << "Selector::select() failed." << std::endl;
					exitRobogen(EXIT_FAILURE);
				}
				unsigned int tries = 0;
				do {
					if (tries > 10000) {
						std::cerr << "Selecting second parent failed after "
								"10000 tries, giving up.";
						exitRobogen(EXIT_FAILURE);
					}
					if (!selector->select(selection.second)) {
						std::cerr << "Selector::select() failed." << std::endl;
						exitRobogen(EXIT_FAILURE);
					}
					tries++;
				} while (selection.first == selection.second);

				std::vector<boost::shared_ptr<RobotRepresentation> > offspring
					= mutator->createOffspring(selection.first,
											   selection.second);

				// no crossover, or can fit both new individuals
				if ( (numOffspring + offspring.size()) <= conf->lambda ) {
					children.insert(children.end(), offspring.begin(),
													offspring.end() );
					numOffspring += offspring.size();
				} else { // crossover, but can only fit one
					children.push_back(offspring[0]);
					numOffspring++;
				}
			}
			children.evaluate(robotConf, sockets);
		}
#ifndef EMSCRIPTEN
		triggerPostEvaluate();
#endif
	} else {
#ifdef EMSCRIPTEN
		sendJSEvent("evolutionTerminated", "{}");
#endif

	}
}

#ifdef EMSCRIPTEN
void EMSCRIPTEN_KEEPALIVE evaluationResultAvailable(int ptr, double fitness) {
	RobotRepresentation* robot = (RobotRepresentation*) ptr;
	robot->asyncEvaluateResult(fitness);
}

void EMSCRIPTEN_KEEPALIVE evaluationIsDone() {
	triggerPostEvaluate();
}
#endif

}
Exemplo n.º 3
0
int main(int argc, char *argv[]) {

	startRobogen();

	// ---------------------------------------
	// verify usage and load configuration
	// ---------------------------------------
	if (argc > 1 && std::string(argv[1]) == "--help") {
		printUsage(argv);
		printHelp();
		exitRobogen(EXIT_SUCCESS);
	}

	if ((argc < 4)) {
		printUsage(argv);
		std::cout << "RUN: " << std::endl << std::endl
				<< "      " << std::string(argv[0])
				<< " --help to see all configuration options."
				<< std::endl << std::endl;
		exitRobogen(EXIT_FAILURE);
	}


	unsigned int seed = atoi(argv[1]);
	std::string outputDirectory = std::string(argv[2]);
	std::string confFileName = std::string(argv[3]);

	bool overwrite = false;
	bool saveAll = false;
	int currentArg = 4;
	for (; currentArg<argc; currentArg++) {
		if (std::string("--help").compare(argv[currentArg]) == 0) {
			printUsage(argv);
			printHelp();
			return EXIT_SUCCESS;
		} else if (std::string("--overwrite").compare(argv[currentArg]) == 0) {
			overwrite = true;
		} else if (std::string("--save-all").compare(argv[currentArg]) == 0) {
			saveAll = true;
		} else {
			std::cerr << std::endl << "Invalid option: " << argv[currentArg]
							 << std::endl << std::endl;
			printUsage(argv);
			exitRobogen(EXIT_FAILURE);
		}


	}


	// Create random number generator
	boost::random::mt19937 rng;
	rng.seed(seed);

	boost::shared_ptr<EvolverConfiguration> conf =
			boost::shared_ptr<EvolverConfiguration>(new EvolverConfiguration());
	if (!conf->init(confFileName)) {
		std::cerr << "Problems parsing the evolution configuration file. Quit."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	boost::shared_ptr<RobogenConfig> robotConf =
			ConfigurationReader::parseConfigurationFile(
					conf->simulatorConfFile);
	if (robotConf == NULL) {
		std::cerr << "Problems parsing the robot configuration file. Quit."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	// ---------------------------------------
	// Set up evolution
	// ---------------------------------------

	boost::shared_ptr<Selector> selector;
	if (conf->selection == conf->DETERMINISTIC_TOURNAMENT) {
		selector.reset(new DeterministicTournament(conf->tournamentSize, rng));
	} else {
		std::cerr << "Selection type id " << conf->selection << " unknown."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	}
	boost::shared_ptr<Mutator> mutator = boost::shared_ptr<Mutator>(
			new Mutator(conf, rng));
	boost::shared_ptr<EvolverLog> log(new EvolverLog());
	if (!log->init(conf, robotConf, outputDirectory, overwrite, saveAll)) {
		std::cout << "Error creating evolver log. Aborting." << std::endl;
		return EXIT_FAILURE;
	}

	// ---------------------------------------
	// parse robot from file & initialize population
	// ---------------------------------------

	boost::shared_ptr<RobotRepresentation> referenceBot(
			new RobotRepresentation());
	bool growBodies = false;
	if (conf->evolutionMode == EvolverConfiguration::BRAIN_EVOLVER
			&& conf->referenceRobotFile.compare("") == 0) {
		std::cerr << "Trying to evolve brain, but no robot file provided."
				<< std::endl;
		exitRobogen(EXIT_FAILURE);
	} else if (conf->referenceRobotFile.compare("") != 0) {
		if (!referenceBot->init(conf->referenceRobotFile)) {
			std::cerr << "Failed interpreting robot from text file"
					<< std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	} else { //doing body evolution and don't have a reference robot
		if (referenceBot->init()) {
			growBodies = true;
		} else {
			std::cerr << "Failed creating base robot for body evolution"
					<< std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	}
	

	boost::shared_ptr<Population> population(new Population());
	boost::shared_ptr<NeatContainer> neatContainer;

	bool neat = (conf->evolutionaryAlgorithm ==
			EvolverConfiguration::HYPER_NEAT);

	if (!population->init(referenceBot, conf->mu, mutator, growBodies,
			(!(conf->useBrainSeed || neat)) ) ) {
		std::cerr << "Error when initializing population!" << std::endl;
		exitRobogen(EXIT_FAILURE);
	}

	if (neat) {
		neatContainer.reset(new NeatContainer(conf, population, seed, rng));

	}




	// ---------------------------------------
	// open sockets for communication with simulator processes
	// ---------------------------------------

	std::vector<TcpSocket*> sockets(conf->sockets.size());
	for (unsigned int i = 0; i < conf->sockets.size(); i++) {
		sockets[i] = new TcpSocket;
#ifndef FAKEROBOTREPRESENTATION_H // do not bother with sockets when using
		// benchmark
		if (!sockets[i]->open(conf->sockets[i].first,
				conf->sockets[i].second)) {
			std::cerr << "Could not open connection to simulator" << std::endl;
			exitRobogen(EXIT_FAILURE);
		}
#endif
	}

	// ---------------------------------------
	// run evolution TODO stopping criterion
	// ---------------------------------------

	if(neat) {
		if(!neatContainer->fillPopulationWeights(population)) {
			std::cerr << "Filling weights from NEAT failed." << std::endl;
			exitRobogen(EXIT_FAILURE);
		}
	}

	population->evaluate(robotConf, sockets);
	if (!log->logGeneration(1, *population.get())) {
		exitRobogen(EXIT_FAILURE);
	}

	for (unsigned int generation = 2; generation <= conf->numGenerations;
			++generation) {
		// create children
		IndividualContainer children;
		if (neat) {
			//neatPopulation->Epoch();
			if(!neatContainer->produceNextGeneration(population)) {
				std::cerr << "Producing next generation from NEAT failed."
						<< std::endl;
				exitRobogen(EXIT_FAILURE);
			}
			population->evaluate(robotConf, sockets);
			population->sort(true);
		} else {
			selector->initPopulation(population);
			for (unsigned int i = 0; i < conf->lambda; i++) {
				std::pair<boost::shared_ptr<RobotRepresentation>,
						boost::shared_ptr<RobotRepresentation> > selection;
				if (!selector->select(selection)) {
					std::cerr << "Selector::select() failed." << std::endl;
					exitRobogen(EXIT_FAILURE);
				}
				children.push_back(
						mutator->mutate(selection.first, selection.second));
			}

			// evaluate children
			children.evaluate(robotConf, sockets);

			// comma or plus?
			if (conf->replacement == conf->PLUS_REPLACEMENT) {
				children += *population.get();
			}

			// replace
			population.reset(new Population());
			if (!population->init(children, conf->mu)) {
				std::cerr << "Error when initializing population!" << std::endl;
				exitRobogen(EXIT_FAILURE);
			}
		}


		if (!log->logGeneration(generation, *population.get())) {
			exitRobogen(EXIT_FAILURE);
		}
	}

	// Clean up sockets
	for (unsigned int i = 0; i < conf->sockets.size(); i++) {
		delete sockets[i];
	}

	exitRobogen(EXIT_SUCCESS);
}
Exemplo n.º 4
0
void mainEvolutionLoop() {
#ifdef EMSCRIPTEN
	std::stringstream ss;
	double best, average, stddev;
	population->getStat(best, average, stddev);
	ss << "{best : " << best << ", average : " << average << ", stddev : "
			<< stddev << ", generation : " << generation << "}";
	sendJSEvent("stats", ss.str());
#endif

	std::cout << "mainEvolutionLoop" << std::endl;
	if (!log->logGeneration(generation, *population.get())) {
		exitRobogen(EXIT_FAILURE);
	}

	generation++;


	if (generation <= conf->numGenerations) {
		std::cout << "Generation " << generation << std::endl;
		children.clear();

		// create children
		if (neat) {
			//neatPopulation->Epoch();
			if(!neatContainer->produceNextGeneration(population)) {
				std::cerr << "Producing next generation from NEAT failed."
						<< std::endl;
				exitRobogen(EXIT_FAILURE);
			}
			population->evaluate(robotConf, sockets);

		} else {
			selector->initPopulation(population);
			unsigned int numOffspring = 0;
			while (numOffspring < conf->lambda) {

				std::pair<boost::shared_ptr<RobotRepresentation>,
						boost::shared_ptr<RobotRepresentation> > selection;
				if (!selector->select(selection.first)) {
					std::cerr << "Selector::select() failed." << std::endl;
					exitRobogen(EXIT_FAILURE);
				}
				unsigned int tries = 0;
				do {
					if (tries > 10000) {
						std::cerr << "Selecting second parent failed after "
								"10000 tries, giving up.";
						exitRobogen(EXIT_FAILURE);
					}
					if (!selector->select(selection.second)) {
						std::cerr << "Selector::select() failed." << std::endl;
						exitRobogen(EXIT_FAILURE);
					}
					tries++;
				} while (selection.first == selection.second);

				std::vector<boost::shared_ptr<RobotRepresentation> > offspring
					= mutator->createOffspring(selection.first,
											   selection.second);

				// no crossover, or can fit both new individuals
				if ( (numOffspring + offspring.size()) <= conf->lambda ) {
					children.insert(children.end(), offspring.begin(),
													offspring.end() );
					numOffspring += offspring.size();
				} else { // crossover, but can only fit one
					children.push_back(offspring[0]);
					numOffspring++;
				}
			}
			children.evaluate(robotConf, sockets);
		}
#ifndef EMSCRIPTEN
		triggerPostEvaluate();
#endif
	} else {
#ifdef EMSCRIPTEN
		sendJSEvent("evolutionTerminated", "{}");
#endif

	}
}