// Settings.java
//
// Authors:
// Antonio J. Nebro <antonio@lcc.uma.es>
// Juan J. Durillo <durillo@lcc.uma.es>
//
// Copyright (c) 2011 Antonio J. Nebro, Juan J. Durillo
//
// This program 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.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
package jmetal.experiments;
import jmetal.core.Algorithm;
import jmetal.core.Operator;
import jmetal.core.Problem;
import jmetal.encodings.solutionType.ArrayRealSolutionType;
import jmetal.encodings.solutionType.BinaryRealSolutionType;
import jmetal.encodings.solutionType.BinarySolutionType;
import jmetal.encodings.solutionType.RealSolutionType;
import jmetal.operators.crossover.Crossover;
import jmetal.operators.crossover.CrossoverFactory;
import jmetal.operators.mutation.Mutation;
import jmetal.operators.mutation.MutationFactory;
import jmetal.util.JMException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Properties;
/**
* Class representing Settings objects.
*/
public abstract class Settings {
protected Problem problem_ ;
protected String problemName_ ;
protected String paretoFrontFile_ ;
/**
* Constructor
*/
public Settings() {
} // Constructor
/**
* Constructor
*/
public Settings (String problemName) {
problemName_ = problemName ;
} // Constructor
/**
* Default configure method
* @return An algorithm with the default configuration
* @throws jmetal.util.JMException
*/
abstract public Algorithm configure() throws JMException ;
/**
* Configure method based on reading a properties file
* @param configuration Properties file
* @return A algorithm with a the configuration contained in the properties file
*/
public Algorithm configure(Properties configuration) throws JMException {return null;} ;
/**
* Configure method. Change the default configuration
* @param settings
* @return A problem with the experiments.settings indicated as argument
* @throws jmetal.util.JMException
* @throws ClassNotFoundException
*/
public final Algorithm configure(HashMap settings) throws JMException, IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
if (settings != null) {
Field [] fields = this.getClass().getFields();
for (int i=0; i < fields.length; i++) {
if (fields[i].getName().endsWith("_")) { // it is a configuration field
// The configuration field is an integer
if (fields[i].getType().equals(int.class) ||
fields[i].getType().equals(Integer.class)) {
if (settings.containsKey(fields[i].getName())) {
Integer value = (Integer)settings.get(fields[i].getName());
fields[i].setInt(this, value.intValue());
}
}
else if (fields[i].getType().equals(double.class) ||
fields[i].getType().equals(Double.class)) {
// The configuration field is a double
//double value = Double.parseDouble(experiments.settings.getProperty(fields[i].getName(),""+fields[i].getDouble(this)));
Double value = (Double)settings.get(fields[i].getName());
if (settings.containsKey(fields[i].getName())) {
if (fields[i].getName().equals("mutationProbability_") &&
value == null) {
if ((problem_.getSolutionType().getClass() == RealSolutionType.class) ||
(problem_.getSolutionType().getClass() == ArrayRealSolutionType.class)) {
value = 1.0 / problem_.getNumberOfVariables();
} else if (problem_.getSolutionType().getClass() == BinarySolutionType.class ||
problem_.getSolutionType().getClass() == BinaryRealSolutionType.class) {
int length = problem_.getNumberOfBits();
value = 1.0 / length;
} else {
int length = 0;
for (int j = 0; j < problem_.getNumberOfVariables(); j++) {
length+= problem_.getLength(j);
}
value = 1.0 / length;
}
fields[i].setDouble(this, value);
} // if
else {
fields[i].setDouble(this, value);
}
}
} else {
//Object value = experiments.settings.getProperty(fields[i].getName(), null) ;
Object value = settings.get(fields[i].getName());
if (value!=null) {
if (fields[i].getType().equals(Crossover.class)) {
Object value2 = CrossoverFactory.getCrossoverOperator((String)value,settings);
value = value2;
}
if (fields[i].getType().equals(Mutation.class)) {
Object value2 = MutationFactory.getMutationOperator((String)value, settings);
value = value2;
}
fields[i].set(this, value);
}
}
}
} // for
// At this point all the fields have been read from the properties
// parameter. Those fields representing crossover and mutations should also
// be initialized. However, there is still mandatory to configure them
for (int i = 0; i < fields.length; i++) {
if (fields[i].getType().equals(Crossover.class) ||
fields[i].getType().equals(Mutation.class)) {
Operator operator = (Operator) fields[i].get(this);
// This field stores a crossover operator
String tmp = fields[i].getName();
String aux = fields[i].getName().substring(0, tmp.length()-1);
for (int j = 0; j < fields.length; j++) {
if (i != j) {
if (fields[j].getName().startsWith(aux)) {
// The field is a configuration parameter of the crossover
tmp = fields[j].getName().substring(aux.length(), fields[j].getName().length()-1);
if (
(fields[j].get(this)!=null)) {
if (fields[j].getType().equals(int.class) ||
fields[j].getType().equals(Integer.class)) {
operator.setParameter(tmp, fields[j].getInt(this));
} else if (fields[j].getType().equals(double.class) ||
fields[j].getType().equals(Double.class)) {
operator.setParameter(tmp, fields[j].getDouble(this));
}
}
}
}
}
}
}
//At this point, we should compare if the pareto front have been added
paretoFrontFile_ = (String)settings.get("paretoFrontFile_");
}
return configure();
} // configure
/**
* Changes the problem to solve
* @param problem
*/
void setProblem(Problem problem) {
problem_ = problem ;
} // setProblem
/**
* Returns the problem
*/
Problem getProblem() {
return problem_ ;
} // getProblem
} // Settings