OneParameterization.java Source code

Java tutorial

Introduction

Here is the source code for OneParameterization.java

Source

/* Copyright 2009-2012 David Hadka 
 * 2013 Matthew Woodruff
 * 
 * This file is based on part of the MOEA Framework.
 * 
 * The MOEA Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or (at your 
 * option) any later version.
 * 
 * The MOEA Framework 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 Lesser General Public 
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with the MOEA Framework.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.moeaframework.core.Algorithm;
import org.moeaframework.core.FrameworkException;
import org.moeaframework.core.NondominatedPopulation;
import org.moeaframework.core.PRNG;
import org.moeaframework.core.PopulationIO;
import org.moeaframework.core.Problem;
import org.moeaframework.core.indicator.QualityIndicator;
import org.moeaframework.core.spi.AlgorithmFactory;
import org.moeaframework.core.spi.ProblemFactory;
import org.moeaframework.problem.TimingProblem;
import org.moeaframework.util.CommandLineUtility;
import org.moeaframework.util.Localization;
import org.moeaframework.util.TypedProperties;
import org.moeaframework.analysis.sensitivity.*;

/**
 * Command line utility for evaluating an algorithm using many 
 * parameterizations.
 */
public class OneParameterization extends CommandLineUtility {

    /**
     * The problem being evaluated.
     */
    protected Problem problem;

    /**
     * The output writer where end-of-run results are stored.
     */
    protected OutputWriter output;

    /**
     * The sample reader from which input parameters are read.
     */
    protected SampleReader input;

    /**
     * Constructs the command line utility for evaluating an algorithm using
     * many parameterizations.
     */
    public OneParameterization() {
        super();
    }

    @Override
    public void start(String[] args) {
        // trim last argument because of an error with Windows newline                                                                                 
        // characters                                                                                                                                  
        if (args.length > 0) {
            args[args.length - 1] = args[args.length - 1].trim();
        }

        Options options = getOptions();
        CommandLineParser commandLineParser = new GnuParser();
        CommandLine commandLine = null;

        try {
            commandLine = commandLineParser.parse(options, args);
        } catch (ParseException e) {
            System.err.println(e.getMessage());
        }

        if ((commandLine == null) || commandLine.hasOption("help")) {
            // there's no helping you!
            System.exit(-1);
        }

        try {
            run(commandLine);
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(-1);
        }
    }

    @SuppressWarnings("static-access")
    @Override
    public Options getOptions() {
        Options options = super.getOptions();

        options.addOption(
                OptionBuilder.withLongOpt("parameterFile").hasArg().withArgName("file").isRequired().create('p'));
        options.addOption(OptionBuilder.withLongOpt("input").hasArg().withArgName("file").isRequired().create('i'));
        options.addOption(OptionBuilder.withLongOpt("inputnumber").hasArg().withArgName("input number").isRequired()
                .create('u'));
        options.addOption(
                OptionBuilder.withLongOpt("output").hasArg().withArgName("file").isRequired().create('o'));
        options.addOption(
                OptionBuilder.withLongOpt("problem").hasArg().withArgName("name").isRequired().create('b'));
        options.addOption(
                OptionBuilder.withLongOpt("algorithm").hasArg().withArgName("name").isRequired().create('a'));
        options.addOption(OptionBuilder.withLongOpt("properties").hasArgs().withArgName("p1=v1;p2=v2;...")
                .withValueSeparator(';').create('x'));
        options.addOption(OptionBuilder.withLongOpt("seed").hasArg().withArgName("value").create('s'));
        options.addOption(OptionBuilder.withLongOpt("epsilon").hasArg().withArgName("e1,e2,...").create('e'));
        options.addOption(OptionBuilder.withLongOpt("metrics").create('m'));
        options.addOption(OptionBuilder.withLongOpt("reference").hasArg().withArgName("file").create('r'));
        options.addOption(OptionBuilder.withLongOpt("novariables").create('n'));
        options.addOption(OptionBuilder.withLongOpt("force").create('f'));

        //fill in option descriptions
        for (Object obj : options.getOptions()) {
            Option option = (Option) obj;

            option.setDescription(option.getLongOpt());
        }

        return options;
    }

    @Override
    public String getDescription() {
        return Localization.getString(OneParameterization.class, "description");
    }

    @Override
    public void run(CommandLine commandLine) throws IOException {
        File outputFile = new File(commandLine.getOptionValue("output"));
        File inputFile = new File(commandLine.getOptionValue("input"));

        ParameterFile parameterFile = new ParameterFile(new File(commandLine.getOptionValue("parameterFile")));

        // sanity check to ensure input hasn't been modified after the output
        if (!commandLine.hasOption("force") && (outputFile.lastModified() > 0L)
                && (inputFile.lastModified() > outputFile.lastModified())) {
            throw new FrameworkException("input appears to be newer than output");
        }

        // open the resources and begin processing
        try {
            problem = ProblemFactory.getInstance().getProblem(commandLine.getOptionValue("problem"));

            try {
                input = new SampleReader(new FileReader(inputFile), parameterFile);

                try {
                    if (commandLine.hasOption("metrics")) {
                        NondominatedPopulation referenceSet = null;

                        // load reference set and create the quality indicator
                        if (commandLine.hasOption("reference")) {
                            referenceSet = new NondominatedPopulation(
                                    PopulationIO.readObjectives(new File(commandLine.getOptionValue("reference"))));
                        } else {
                            referenceSet = ProblemFactory.getInstance()
                                    .getReferenceSet(commandLine.getOptionValue("problem"));
                        }

                        if (referenceSet == null) {
                            throw new FrameworkException("no reference set available");
                        }

                        QualityIndicator indicator = new QualityIndicator(problem, referenceSet);

                        output = new MetricFileWriter(indicator, outputFile);
                    } else {
                        output = new ResultFileWriter(problem, outputFile, !commandLine.hasOption("novariables"));
                    }

                    // resume at the last good output
                    //               for (int i = 0; i < output.getNumberOfEntries(); i++) {
                    //                  if (input.hasNext()) {
                    //                     input.next();
                    //                  } else {
                    //                     throw new FrameworkException(
                    //                           "output has more entries than input");
                    //                  }
                    //               }
                    // only one input. scan forward to it
                    Properties properties = new Properties();
                    if (commandLine.hasOption("inputnumber")) {
                        long limit = Long.parseLong(commandLine.getOptionValue("inputnumber"));
                        for (long ii = 0; ii <= limit; ii++) {
                            if (input.hasNext()) {
                                properties = input.next();
                            } else {
                                throw new FrameworkException("input line does not exist");
                            }
                        }
                    }

                    // setup any default parameters
                    Properties defaultProperties = new Properties();

                    if (commandLine.hasOption("properties")) {
                        for (String property : commandLine.getOptionValues("properties")) {
                            String[] tokens = property.split("=");

                            if (tokens.length == 2) {
                                defaultProperties.setProperty(tokens[0], tokens[1]);
                            } else {
                                throw new FrameworkException("malformed property argument");
                            }
                        }
                    }

                    if (commandLine.hasOption("epsilon")) {
                        defaultProperties.setProperty("epsilon", commandLine.getOptionValue("epsilon"));
                    }

                    // seed the pseudo-random number generator
                    if (commandLine.hasOption("seed")) {
                        PRNG.setSeed(Long.parseLong(commandLine.getOptionValue("seed")));
                    }

                    // process the remaining runs
                    //               while (input.hasNext()) {
                    //                  Properties properties = input.next();
                    //                  properties.putAll(defaultProperties);
                    //
                    //                  process(commandLine.getOptionValue("algorithm"),
                    //                        properties);
                    //               }
                    properties.putAll(defaultProperties);
                    process(commandLine.getOptionValue("algorithm"), properties);
                } finally {
                    if (output != null) {
                        output.close();
                    }
                }
            } finally {
                if (input != null) {
                    input.close();
                }
            }
        } finally {
            if (problem != null) {
                problem.close();
            }
        }
    }

    /**
     * Performs a single run of the specified algorithm using the parameters.
     * 
     * @param algorithmName the algorithm name
     * @param properties the parameters stored in a properties object
     * @throws IOException if an I/O error occurred
     */
    protected void process(String algorithmName, Properties properties) throws IOException {
        // instrument the problem to record timing information
        TimingProblem timingProblem = new TimingProblem(problem);

        Algorithm algorithm = AlgorithmFactory.getInstance().getAlgorithm(algorithmName, properties, timingProblem);

        // find the maximum NFE to run
        if (!properties.containsKey("maxEvaluations")) {
            throw new FrameworkException("maxEvaluations not defined");
        }

        int maxEvaluations = (int) Double.parseDouble(properties.getProperty("maxEvaluations"));

        // run the algorithm
        long startTime = System.nanoTime();
        while (!algorithm.isTerminated() && (algorithm.getNumberOfEvaluations() < maxEvaluations)) {
            algorithm.step();
        }
        long endTime = System.nanoTime();

        // extract the result and free any resources
        NondominatedPopulation result = algorithm.getResult();
        algorithm.terminate();

        // apply epsilon-dominance if required
        if (properties.containsKey("epsilon")) {
            TypedProperties typedProperties = new TypedProperties(properties);
            double[] epsilon = typedProperties.getDoubleArray("epsilon", null);

            result = EpsilonHelper.convert(result, epsilon);
        }

        // record instrumented data
        Properties timingData = new Properties();
        timingData.setProperty("EvaluationTime", Double.toString(timingProblem.getTime()));
        timingData.setProperty("TotalTime", Double.toString((endTime - startTime) / 1e9));

        // write result to output
        output.append(new ResultEntry(result, timingData));
    }

    /**
     * Starts the command line utility for evaluating an algorithm using many
     * parameterizations.
     * 
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new OneParameterization().start(args);
    }

}