Skip to content

Instantly share code, notes, and snippets.

@vst
Created November 3, 2015 00:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vst/a2c6d4599ad0f965ef03 to your computer and use it in GitHub Desktop.
Save vst/a2c6d4599ad0f965ef03 to your computer and use it in GitHub Desktop.
import org.moeaframework.core.Algorithm;
import org.moeaframework.core.Solution;
import org.moeaframework.core.spi.AlgorithmFactory;
import org.moeaframework.core.variable.Grammar;
import org.moeaframework.problem.AbstractProblem;
import org.moeaframework.util.grammar.ContextFreeGrammar;
import org.moeaframework.util.grammar.Parser;
import org.renjin.sexp.SEXP;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;
/**
* Demonstrates how to use MOEA Framework and Renjin to evolve an R program.
*
* <p>
* This simple application requires MOEA and Renjin. These dependencies
* can be specified in the POM file as follows:
* </p>
*
* <pre>
* &lt;dependency&gt;
* &lt;groupId&gt;org.moeaframework&lt;/groupId&gt;
* &lt;artifactId&gt;moeaframework&lt;/artifactId&gt;
* &lt;version&gt;2.6&lt;/version&gt;
* &lt;/dependency&gt;
* &lt;dependency&gt;
* &lt;groupId&gt;org.renjin&lt;/groupId&gt;
* &lt;artifactId&gt;renjin-script-engine&lt;/artifactId&gt;
* &lt;version&gt;0.7.0-RC7&lt;/version&gt;
* &lt;/dependency&gt;
* </pre>
*/
public class SampleRenjinGRE extends AbstractProblem {
/**
* Defines the grammar of the problem.
*/
private final ContextFreeGrammar grammar;
/**
* Defines a Renjin-based scripting engine to be used for evaluating candidates.
*/
private final ScriptEngine engine = new ScriptEngineManager().getEngineByName("Renjin");
/**
* Prepares the evolution environment.
*/
public SampleRenjinGRE() throws IOException, ScriptException {
// Call the super with `number of variables = 1` and `number of objectives = 1`:
super(1, 1);
// Define a silly grammar:
this.grammar = Parser.load(new StringReader("<expr> ::= (<expr> <op> <expr>) | <value>\n" +
"<op> ::= + | * | - | /\n" +
"<value> ::= x"));
// Define some data:
this.engine.eval(String.format("mdata <- data.frame(x=1:10, y=(1:10)^5 + 1:10)"));
}
/**
* Consumes a candidate solution and evaluates the objective function score.
*
* @param solution The candidate solution.
*/
public void evaluate(Solution solution) {
// Get a string representation of the candidate solution:
final String program = this.grammar.build(((Grammar) solution.getVariable(0)).toArray());
// Is the program null? (Why would it be, right? But, there is a reason. Explanation on demand...)
if (program == null) {
// Penalize without mercy!
solution.setObjective(0, Double.POSITIVE_INFINITY);
// We are done here, move on:
return;
}
// Define the expression which will evaluate to the objective score:
final String expression = String.format("sum(abs((function (x) {%s})(mdata$x) - mdata$y))", program);
try {
// Evaluate the candidate program on the data and compute the distance to the actual values:
final SEXP exp = (SEXP) engine.eval(expression);
// Get the real number value:
final double result = exp.asReal();
// Is the number naughty?
if (!Double.isNaN(result)) {
// Set the objective score:
solution.setObjective(0, exp.asReal());
}
else {
// Oops!... Punish:
solution.setObjective(0, Double.POSITIVE_INFINITY);
}
}
catch (ScriptException e) {
// Something has gone wrong. Wrong must be punished:
solution.setObjective(0, Double.POSITIVE_INFINITY);
e.printStackTrace();
}
}
/**
* Defines the problem solution representation.
*
* @return A new solution for the problem.
*/
public Solution newSolution() {
final Solution solution = new Solution(1, 1);
solution.setVariable(0, new Grammar(20));
return solution;
}
/**
* Returns the grammar of the problem.
*
* @return The grammar of the problem.
*/
public ContextFreeGrammar getGrammar() {
return this.grammar;
}
/**
* Provides the entry point of the sample application.
*
* @param args Command line arguments.
* @throws IOException I/O Exception.
* @throws ScriptException Script engine exception.
*/
public static void main (String[] args) throws IOException, ScriptException {
// Define the maximum number of generations:
final int maxGenerations = 100;
// Declare algorithm properties:
final Properties properties = new Properties();
// Set the population size:
properties.setProperty("populationSize", "300");
// Initialize the problem:
final SampleRenjinGRE problem = new SampleRenjinGRE();
// Initialize the algorithm:
final Algorithm algorithm = AlgorithmFactory.getInstance().getAlgorithm("NSGAII", properties, problem);
// Define the iteration counter:
int generation = 1;
// Iterate over the generations:
while (generation <= maxGenerations) {
// Run a generation:
algorithm.step();
// Get the result as of now:
final Solution result = algorithm.getResult().get(0);
// Get the string representation:
final String repr = problem.getGrammar().build(((Grammar) result.getVariable(0)).toArray());
// Get the score:
final double score = result.getObjective(0);
// Calculate the percentage of done task:
final double completed = 100.0 * generation / maxGenerations;
// Increment the iteration counter:
generation++;
// Notify:
System.out.println(String.format("[%%%3.0f] %.2f %s", completed, score, repr));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment