Created
October 21, 2018 21:27
-
-
Save sgraaf/f82821d12f55f63a1e74b10d2946f19c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Comparator; | |
import java.util.Random; | |
import java.util.Properties; | |
import java.util.Arrays; | |
public class FitnessComparator implements Comparator<double[]>{ | |
@Override | |
public int compare(double[] entry1, double[] entry2) { | |
double field1 = entry1[20]; | |
double field2 = entry2[20]; | |
if (field1>field2) { | |
return 1; | |
} else if (field1==field2) { | |
return 0; | |
} else { | |
return -1; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.vu.contest.ContestSubmission; | |
import org.vu.contest.ContestEvaluation; | |
import java.util.Comparator; | |
import java.util.Random; | |
import java.util.Properties; | |
import java.util.Arrays; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Collections; | |
public class player8 implements ContestSubmission { | |
static final int ind_size = 10 + 10 + 1; //index 10-19 = sigmas, index 20 = fitness | |
static final double dev = 1/(Math.sqrt(20)); | |
static final double dev2 = 1/(Math.sqrt(2.0 * Math.sqrt(10))); | |
static final double eps0 = 0.001; | |
Random rnd_; | |
ContestEvaluation evaluation_; | |
private int evaluations_limit_; | |
public player8() { | |
rnd_ = new Random(); | |
} | |
public void setSeed(long seed) { | |
// Set seed of algortihms random process | |
rnd_.setSeed(seed); | |
} | |
public void setEvaluation(ContestEvaluation evaluation) { | |
// Set evaluation problem used in the run | |
evaluation_ = evaluation; | |
// Get evaluation properties | |
Properties props = evaluation.getProperties(); | |
// Get evaluation limit | |
evaluations_limit_ = Integer.parseInt(props.getProperty("Evaluations")); | |
// Property keys depend on specific evaluation | |
// E.g. double param = Double.parseDouble(props.getProperty("property_name")); | |
boolean isMultimodal = Boolean.parseBoolean(props.getProperty("Multimodal")); | |
boolean hasStructure = Boolean.parseBoolean(props.getProperty("Regular")); | |
boolean isSeparable = Boolean.parseBoolean(props.getProperty("Separable")); | |
// Do sth with property values, e.g. specify relevant settings of your algorithm | |
if(isMultimodal){ | |
// Do sth | |
} else { | |
// Do sth else | |
} | |
} | |
// Discrete recombination method | |
public double[][] discrete_recombination(double[] parent_1, double[] parent_2) { | |
double[][] children = new double[2][ind_size]; | |
// Genes + Sigmas | |
for (int j = 0; j < 20; j++) { | |
if (rnd_.nextDouble() <= 0.5) { | |
children[0][j] = parent_1[j]; | |
children[1][j] = parent_2[j]; | |
} else { | |
children[0][j] = parent_1[j]; | |
children[1][j] = parent_2[j]; | |
} | |
} | |
return children; | |
} | |
// Simple arithmic recombination method | |
public double[][] simple_arithmic_recombination(double[] parent_1, double[] parent_2, int k, double alpha) { | |
double[][] children = new double[2][ind_size]; | |
// Genes | |
for (int j = 0; j < k; j++) { | |
children[0][j] = parent_1[j]; | |
children[1][j] = parent_2[j]; | |
} | |
for (int j = k; j < 10; j++) { | |
children[0][j] = alpha * parent_1[j] + (1 - alpha) * parent_2[j]; | |
children[1][j] = alpha * parent_2[j] + (1 - alpha) * parent_1[j]; | |
} | |
// Sigmas | |
for (int j = 10; j < k + 10; j++) { | |
children[0][j] = parent_1[j]; | |
children[1][j] = parent_2[j]; | |
} | |
for (int j = k + 10; j < 20; j++) { | |
children[0][j] = alpha * parent_1[j] + (1 - alpha) * parent_2[j]; | |
children[1][j] = alpha * parent_2[j] + (1 - alpha) * parent_1[j]; | |
} | |
return children; | |
} | |
// Single arithmic recombination method | |
public double[][] single_arithmic_recombination(double[] parent_1, double[] parent_2, double alpha) { | |
double[][] children = new double[2][ind_size]; | |
int k = rnd_.nextInt(10); | |
children[0] = parent_1; | |
children[1] = parent_2; | |
// Genes | |
children[0][k] = alpha * parent_1[k] + (1 - alpha) * parent_2[k]; | |
children[1][k] = alpha * parent_2[k] + (1 - alpha) * parent_1[k]; | |
// Sigmas | |
children[0][k + 10] = alpha * parent_1[k + 10] + (1 - alpha) * parent_2[k + 10]; | |
children[1][k + 10] = alpha * parent_2[k + 10] + (1 - alpha) * parent_1[k + 10]; | |
return children; | |
} | |
// Whole arithmic recombination method | |
public double[][] whole_arithmic_recombination(double[] parent_1, double[] parent_2, double alpha) { | |
double[][] children = new double[2][ind_size]; | |
// Genes + Sigmas | |
for (int j = 0; j < 20; j++) { | |
children[0][j] = alpha * parent_1[j] + (1 - alpha) * parent_2[j]; | |
children[1][j] = alpha * parent_2[j] + (1 - alpha) * parent_1[j]; | |
} | |
return children; | |
} | |
// Blend crossover method | |
public double[][] blend_crossover(double[] parent_1, double[] parent_2, double gamma) { | |
double[][] children = new double[2][ind_size]; | |
// Genes | |
for (int j = 0; j < 10; j++) { | |
//Squeeze the values between [-5.0, 5.0] with the max-min | |
children[0][j] = Math.max(-5.0, Math.min((1 - gamma) * parent_1[j] + gamma * parent_2[j], 5.0)); | |
children[1][j] = Math.max(-5.0, Math.min((1 - gamma) * parent_2[j] + gamma * parent_1[j], 5.0)); | |
} | |
// Sigmas | |
for (int j = 10; j < 20; j++) { | |
children[0][j] = Math.max(eps0, (1 - gamma) * parent_1[j] + gamma * parent_2[j]); | |
children[1][j] = Math.max(eps0, (1 - gamma) * parent_2[j] + gamma * parent_1[j]); | |
} | |
return children; | |
} | |
// Mutation method | |
public double[] mutation(double[] individual) { | |
//double[] mutated = new double[ind_size]; | |
double oldFitness = individual[20]; | |
double N01 = rnd_.nextGaussian(); | |
double sigma; | |
double mut; | |
double oldSigma; | |
double newFitness; | |
double N2; | |
for (int j = 0; j < 10; j++) { | |
oldSigma = individual[10 + j]; | |
N2 = rnd_.nextGaussian(); | |
sigma = Math.max(eps0, oldSigma * (Math.exp(dev * N2 + dev2 * N01))); | |
individual[10 + j] = sigma; | |
mut = sigma * N2; | |
individual[j] = Math.max(-5.0, Math.min(individual[j] + mut, 5.0)); | |
} | |
// newFitness = (double) evaluation_.evaluate(Arrays.copyOfRange(individual, 0, 10)); | |
// individual[20] = newFitness; | |
// System.out.println("Change in fitness: " + oldFitness + " --> " + newFitness); | |
return individual; | |
} | |
public void run() { | |
int pop_size = 50; // mu | |
int children_size = 7 * pop_size; // lambda = 7 * pop_size is a good setting fur (mu, lambda)-selection | |
int crossover_type = Integer.parseInt(System.getProperty("crossover_type", "5")); // 1: discrete recombination, 2: simple arithmic recombination, 3: single arithmic recombination, 4: whole arithmic recombination, 5: blend crossover | |
// Run your algorithm here | |
// Set the seed to our system time | |
rnd_.setSeed(System.currentTimeMillis()); | |
// Initializaiton | |
int evals = 0; | |
double[][] population = new double[pop_size][ind_size]; | |
// Parameters | |
// Mutation | |
double sigma = 0.1; | |
// Crossover | |
// Arithmetic recombination | |
int k = 7; | |
double alpha_1 = 0.5; | |
// Blend crossover | |
double alpha_2 = 0.5; // The book reports that the creators of BLX found 0.5 to be the best value for alpha | |
// Create the population by filling the empty array of arrays of doubles | |
for (int i = 0; i < pop_size; i++) { | |
for (int j = 0; j < 10; j++) { | |
population[i][j] = 10 * rnd_.nextDouble() - 5; //Adapted this to get real values in the range of [-5,5] | |
population[i][10 + j] = sigma; | |
} | |
//System.out.println(Arrays.toString(population[i])); | |
} | |
// Evaluation of initial population | |
// System.out.println(); | |
// System.out.println("1. Evaluation of population"); | |
for (int i = 0; i < pop_size; i++) { | |
population[i][20] = (double) evaluation_.evaluate(Arrays.copyOfRange(population[i],0,10)); | |
} | |
while (evals < evaluations_limit_) { | |
// Parent selection | |
// System.out.println(); | |
// System.out.println("2. Parent selection"); | |
// Initialize the children array | |
int children_count = 0; | |
double[][] children = new double[children_size][ind_size]; | |
// Uniform selection of parents | |
while (children_count < children_size) { | |
int selected_parents_count = 0; | |
double[][] selected_parents = new double[2][ind_size]; // 2 parents are needed for children creation | |
while (selected_parents_count < 2) { | |
// Pick a member of the population with uniform probability to become a parent | |
int selected_parent = rnd_.nextInt(pop_size); | |
// Select this parent and update the counter | |
selected_parents[selected_parents_count] = population[selected_parent]; | |
selected_parents_count++; | |
} | |
// Apply crossover operators and create children | |
// System.out.println("4. Recombination (using " + crossover_types[crossover_type] + ")"); | |
double[][] tmp_children = new double[2][ind_size]; | |
// Use the selected crossover operator | |
switch (crossover_type) { | |
case 1: tmp_children = discrete_recombination(selected_parents[0], selected_parents[1]); | |
break; | |
case 2: tmp_children = simple_arithmic_recombination(selected_parents[0], selected_parents[1], k, alpha_1); | |
break; | |
case 3: tmp_children = single_arithmic_recombination(selected_parents[0], selected_parents[1], alpha_1); | |
break; | |
case 4: tmp_children = whole_arithmic_recombination(selected_parents[0], selected_parents[1], alpha_1); | |
break; | |
case 5: double u = rnd_.nextDouble(); | |
double gamma = (1 - 2 * alpha_2) * u - alpha_2; | |
tmp_children = blend_crossover(selected_parents[0], selected_parents[1], gamma); | |
break; | |
} | |
// Apply mutation operators | |
// System.out.println(); | |
// System.out.println("3. Mutation"); | |
// Mutate the selected parents | |
children[children_count] = mutation(tmp_children[0]); | |
children[children_count + 1] = mutation(tmp_children[1]); | |
// Evaluate of children | |
// System.out.println("5. Evaluation of children"); | |
children[children_count][20] = (double) evaluation_.evaluate(Arrays.copyOfRange(children[children_count], 0, 10)); | |
children[children_count + 1][20] = (double) evaluation_.evaluate(Arrays.copyOfRange(children[children_count + 1], 0, 10)); | |
// Increment our children counter | |
children_count += 2; | |
} | |
// Select survivors using (mu, lambda)-selection | |
// Sort the current children on their fitness | |
java.util.Arrays.sort(children, new FitnessComparator()); | |
// Set the new population to the best 5 parents + mu - 5 children | |
for (int i = 0; i < pop_size; i++) { | |
population[i] = children[children.length - (1 + i)]; | |
} | |
// System.out.println("Iteration: " + evals); | |
evals++; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment