Non-Uniform CA Designer (C++, GAlib, Boost)
Detail souboru
Zdrojový kód
/*
* Copyright (C) 2009 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
*
* This file is part of nucad (Non-Uniform CA Designer).
*
* nucad is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* nucad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with nucad. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file nucad.cpp
* Implementation of nucad binary used to run the (r)evolution.
*/
#include "config.h"
#include "CaDesigner.h"
#include "CaFactory.h"
#include "Color.h"
#ifndef BUILDING_DOX
# include <iostream>
# include <iomanip>
# include <stdexcept>
# include <string>
#endif
#include <ga/GAStatistics.h>
using std::string;
/**
* Create observer observer and attach it to subject.
* @param OBSERVER Observer's class to create and attach.
* @param subject ISubject object ought to be observed.
* @param arg Object, pointer or reference given to observer as a second
* parameter.
* @return Return newly created observer which is already attached to subject.
*/
template <typename OBSERVER, typename SUBJECT, typename ARG>
inline OBSERVER* createAttached(SUBJECT *subject, ARG &arg) {
OBSERVER *observer = new OBSERVER(subject, arg);
subject->addObserver(observer);
return observer;
}
int main(int argc, char *argv[]) {
// colorize stderr output if stderr is connected to terminal
// no matter if stdout is or is not connected to terminal
Color::enable(isatty(STDERR_FILENO));
// TODO: use getopt_long instead of hard-wired src/config.h options
static const int minSlns = GA_MIN_SLNS;
static const int maxSlns = GA_MAX_SLNS;
static const int maxRuns = GA_MAX_RUNS;
static const int maxTime = GA_MAX_TIME_PER_RUN;
// create factory on stack (it helps to avoid memory leaks)
CaEvaluatorFactory factory;
const char *circuit = "\"\"";
// TODO: use getopt_long and full-featured --help output
if (1 < argc) {
if (2 < argc || string("--help")==string(argv[1])) {
std::cerr << "Usage: " << argv[0] << " CIRCUIT_NAME" << std::endl;
return 1;
}
circuit = argv[1];
}
// Used for final clean-up on exit
int ec = 0;
CaEvaluator *evaluator = 0;
CaDesigner *designer = 0;
SolutionsCountStop *slnsCountStop = 0;
TimedStop *timedStop = 0;
FitnessWatch *fitnessWatch = 0;
ResultsWatch *resultsWatch = 0;
try {
// try to create evaluator for desired circuit
// this might fail if circuit name is not valid
evaluator = factory.create(circuit);
// create GAlib-powered CA designer
designer = CaDesigner::create(evaluator);
// display message if maxFitness is increased
fitnessWatch = createAttached<FitnessWatch>(designer, std::cerr);
// display message if solution is discovered
resultsWatch = createAttached<ResultsWatch>(designer, std::cerr);
// stop progress after maxSlns solutions are found
slnsCountStop = createAttached<SolutionsCountStop>(designer, maxSlns);
if (maxTime)
// nun will be stopped if its time exceeds
timedStop = createAttached<TimedStop>(designer, maxTime);
// grand total
int totalSolutions = 0;
float totalTime = 0.0;
// for each run...
for (int i = 0; i < maxRuns && totalSolutions < minSlns; i++) {
std::cerr << Color(C_LIGHT_GREEN)
<< ">>> Run " << std::setw(6) << i+1
<< " of " << std::setw(6) << maxRuns
<< Color(C_NO_COLOR) << std::endl;
// initialization
designer->reset();
fitnessWatch->reset();
// run designer
designer->start();
// update solutions count
const int runSolutions= designer->getSolutionsCount() - totalSolutions;
totalSolutions+= runSolutions;
// update elapsed time
const float timeElapsed= designer->getTimeElapsed()/1000.0;
totalTime+= timeElapsed;
// print partial statistics
std::cerr << Color(C_LIGHT_GREEN)
<< "--- Found " << std::setw(6) << runSolutions << " solutions"
<< " in " << FixedFloat(6,2) << timeElapsed << " s"
<< Color(C_NO_COLOR) << std::endl;
// print up-to-now total statistics
if (1 < maxRuns)
std::cerr << Color(C_LIGHT_RED)
<< "--- Total " << std::setw(6) << totalSolutions
<< " solutions in " << FixedFloat(6,2) << totalTime << " s"
<< Color(C_NO_COLOR) << std::endl << std::endl;
// end of run
}
#if GA_VERBOSE_MODE
// print GAlib statistics in verbose mode
// TODO: turn on this by cmd-line argument
GAStatistics stats = designer->getStatistics();
std::cerr << std::endl << Color(C_YELLOW) << stats << Color() << std::endl;
#endif
}
catch (std::runtime_error &e) {
std::cerr << argv[0] << ": "
<< Color(C_LIGHT_RED) << "error: " << Color(C_NO_COLOR)
<< e.what() << std::endl;
ec = 1;
}
// destroy objects in reverse order
delete resultsWatch;
delete fitnessWatch;
delete timedStop;
delete slnsCountStop;
delete designer;
delete evaluator;
return ec;
}