Česky
Kamil Dudka

Non-Uniform CA Designer (C++, GAlib, Boost)

File detail

Name:Downloadnucad.cpp [Download]
Location: nucad > src
Size:5.8 KB
Last modification:2009-07-12 01:46

Source code

/*
 * 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;
}