Česky
Kamil Dudka

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

File detail

Name:Downloadcheck.cpp [Download]
Location: nucad > src
Size:7.4 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 check.cpp
 * Command-line utility which can work with (partial or complete) solutions
 * found by nucad.
 */
 
#include "CaDesigner.h"
#include "CaFactory.h"
#include "Color.h"
 
#ifndef BUILDING_DOX
#   include <iostream>
#   include <string>
#endif
 
#include <getopt.h>
 
using std::string;
 
// cmd-line option list
static struct option const long_opts[] = {
    { "echo",       no_argument,        0, 'e' },
    { "input",      required_argument,  0, 'i' },
    { "list",       no_argument,        0, 'l' },
    { "quiet",      no_argument,        0, 'q' },
    { "rules",      no_argument,        0, 'r' },
    { "simulate",   no_argument,        0, 's' },
    { "help",       no_argument,        0, 'h' },
 
    // this line avoids SIGSEGV if an invalid long option is given
    { NULL, 0, NULL, 0}
};
 
namespace {
    /**
     * Print usage for executable.
     * @param name Name of the executable (usually argv[0]).
     * @param status Expected status code ought to be returned.
     */
    void usage(const char *name, int status)
    {
        if (status != EXIT_SUCCESS)
            std::cerr << "Try `" << name
                << " --help' for more information." << std::endl;
        else
            std::cout << "Usage: " << name << " [OPTIONS] CIRCUIT_NAME\n\
  -e, --echo                   diagnostic echo for rules\n\
  -i, --input=INPUT            simulation for given input\n\
  -l, --list                   print circuit list\n\
  -q, --quiet                  suppress statistics\n\
  -r, --rules                  dump rules in human readable form\n\
  -s, --simulate               simulation for all inputs\n\
      --help                   print this help to stdout"
                << std::endl;
    }
 
    /**
     * Write CA's rules to stream in human-readable format.
     * @param rules The CA's rules to write.
     * @param str Standard output stream to write to.
     */
    void writeRules(GaCaRules *rules, size_t caSize, std::ostream &str)
    {
        for (unsigned row = 0; row < caSize; ++row) {
            for (unsigned col = 0; col < caSize; ++col) {
                str << Color(C_LIGHT_PURPLE) << "--- cell ["
                    << row << "," << col << "]"
                    << Color(C_NO_COLOR) << std::endl;
                TRule5N rule;
                rules->getRuleAtPos(Pos(row, col), rule);
                writeRule(str, rule);
            }
        }
    }
 
}
 
int main(int argc, char *argv[]) {
    // name of executable which is printed on user interaction
    static const char *szAppName = argv[0];
 
    // enable colorized output only if stdout/stderr are connected to terminal
    Color::enable(isatty(STDOUT_FILENO) && isatty(STDERR_FILENO));
 
    // state variables necessary to always delete an existing (if any) evaluator
    int ec = 0;
    CaEvaluator *evaluator = 0;
 
    try {
        // parameters to be read from cmd-line by getopt_long
        bool echo = false;
        bool printList = false;
        bool quiet = false;
        bool dumpRules = false;
        bool simOne = false;
        bool simAll = false;
        TBus in = 0;
 
        // parse cmd-line arguments
        int c;
        while ((c = getopt_long (argc, argv, "ei:lqrs", long_opts, 0)) != -1) {
            switch (c) {
                case 'e':
                    echo = true;
                    break;
 
                case 'i':
                    simOne = true;
                    // FIXME: check if the string is really a number
                    if (!optarg)
                        throw std::runtime_error(
                                "invalid --input (-i) argument");
                    // FIXME: avoid using atoi()
                    in = atoi(optarg);
                    break;
 
                case 'l':
                    printList = true;
                    break;
 
                case 'q':
                    quiet = true;
                    break;
 
                case 'r':
                    dumpRules = true;
                    break;
 
                case 's':
                    simAll = true;
                    break;
 
                case 'h':
                    // print usage and exit successfully
                    usage(argv[0], EXIT_SUCCESS);
                    return EXIT_SUCCESS;
            }
        }
 
        // check for possible cmd-line arguments conflicts
        if (simOne && simAll)
            throw std::runtime_error(
                    "options -i and -s are mutually exclusive");
 
        // create factory on stack (to avoid possible memory leak)
        CaEvaluatorFactory factory;
 
        if (printList) {
            // print circuit list and exit
            factory.printList(std::cout);
            return 0;
        }
 
        // read circuit name from cmd-line
        argc -= optind;
        argv += optind;
        if (argc != 1)
            throw std::runtime_error("invalid count of arguments");
 
        // try to create evaluator for desired circuit
        // this might fail if circuit name is not valid
        evaluator = factory.create(argv[0]);
 
        // parse data from stdin line after line
        string line;
        while (getline(std::cin, line)) {
            // deserialize non-uniform CA's rules
            GaCaRules rules(line);
 
            // check size of the deserialized CA's
            if (rules.size() !=
                    evaluator->caSize() * evaluator->caSize() * RULE_WIDTH)
                throw std::runtime_error(
                        "GaCaRules size mismatch (not implemented)");
 
            if (echo)
                // print echo if requested by cmd-line parameter
                std::cout << rules << std::endl;
 
            if (!quiet) {
                // simulate given CA's rules and print statistics
                unsigned min, max;
                if (evaluator->cntSteps(&rules, min, max)) {
                    std::cout << "--- nSteps: <" << min << ", " << max << ">"
                        << std::endl;
                } else {
                    std::cout << "--- fitness = " << evaluator->eval(&rules)
                        << std::endl;
                }
            }
 
            if (dumpRules)
                // write CA's rules in human-readable format
                writeRules(&rules, evaluator->caSize(), std::cout);
 
            if (simOne)
                // simulate CA for given input value
                evaluator->simulate(&rules, std::cout, in);
 
            if (simAll)
                // simulate CA for all possible input values
                evaluator->simulate(&rules, std::cout);
        }
    }
    catch (std::runtime_error &e) {
        std::cerr << szAppName << ": "
            << Color(C_LIGHT_RED) << "error: " << Color(C_NO_COLOR)
            << e.what() << std::endl;
        ec = 1;
    }
 
    delete evaluator;
 
    return ec;
}