diff --git a/README.md b/README.md index 8447df8..1346072 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Add the following dependency to your `pom.xml`: org.moeaframework gd - 1.1 + 1.2 ``` diff --git a/pom.xml b/pom.xml index 0c7a4c5..c66c8ad 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.moeaframework gd - 1.1 + 1.2 jar Generalized Decomposition diff --git a/src/main/java/org/moeaframework/gd/Example.java b/src/main/java/org/moeaframework/gd/Example.java index 5f50f03..08a86a0 100644 --- a/src/main/java/org/moeaframework/gd/Example.java +++ b/src/main/java/org/moeaframework/gd/Example.java @@ -28,7 +28,7 @@ public static void main(String[] args) { .withProperty("targets", "pf/DTLZ2.3D.pf") .runSeeds(50)); - analyzer.printAnalysis(); + analyzer.display(); } } diff --git a/src/main/java/org/moeaframework/gd/GDMOEAD.java b/src/main/java/org/moeaframework/gd/GDMOEAD.java new file mode 100644 index 0000000..e25e77a --- /dev/null +++ b/src/main/java/org/moeaframework/gd/GDMOEAD.java @@ -0,0 +1,84 @@ +package org.moeaframework.gd; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.moeaframework.algorithm.MOEAD; +import org.moeaframework.core.FrameworkException; +import org.moeaframework.core.Population; +import org.moeaframework.core.PopulationIO; +import org.moeaframework.core.Problem; +import org.moeaframework.core.Solution; +import org.moeaframework.core.operator.RandomInitialization; +import org.moeaframework.core.spi.OperatorFactory; +import org.moeaframework.core.variable.RealVariable; +import org.moeaframework.util.io.CommentedLineReader; +import org.moeaframework.util.weights.NormalBoundaryDivisions; +import org.moeaframework.util.weights.NormalBoundaryIntersectionGenerator; +import org.moeaframework.util.weights.WeightGenerator; + +public class GDMOEAD extends MOEAD { + + public GDMOEAD(Problem problem) { + this(problem, NormalBoundaryDivisions.forProblem(problem)); + } + + public GDMOEAD(Problem problem, String targets) { + this(problem, new GeneralizedDecomposition(loadTargets(targets))); + } + + public GDMOEAD(Problem problem, NormalBoundaryDivisions divisions) { + this(problem, + new GeneralizedDecomposition(new NormalBoundaryIntersectionGenerator( + problem.getNumberOfObjectives(), divisions))); + } + + public GDMOEAD(Problem problem, WeightGenerator weightGenerator) { + super(problem, + weightGenerator.size(), + 20, //neighborhoodSize + weightGenerator, + new RandomInitialization(problem), + OperatorFactory.getInstance().getVariation(problem.isType(RealVariable.class)? "de+pm": null, problem), + 0.9, //delta + 2, //eta + -1); //updateUtility + } + + private static List loadTargets(String resource) { + Population population = null; + + try { + File file = new File(resource); + + if (file.exists()) { + population = PopulationIO.readObjectives(file); + } else { + try (InputStream input = GDMOEAD.class.getResourceAsStream("/" + resource)) { + if (input != null) { + population = PopulationIO.readObjectives(new CommentedLineReader(new InputStreamReader(input))); + } + } + } + } catch (IOException e) { + throw new FrameworkException("failed to load " + resource, e); + } + + if (population == null) { + throw new FrameworkException("could not find " + resource); + } + + List targets = new ArrayList(); + + for (Solution solution : population) { + targets.add(solution.getObjectives()); + } + + return targets; + } + +} diff --git a/src/main/java/org/moeaframework/gd/GDMOEADProvider.java b/src/main/java/org/moeaframework/gd/GDMOEADProvider.java index 81840a5..c0f914f 100644 --- a/src/main/java/org/moeaframework/gd/GDMOEADProvider.java +++ b/src/main/java/org/moeaframework/gd/GDMOEADProvider.java @@ -1,31 +1,10 @@ package org.moeaframework.gd; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; - -import org.moeaframework.algorithm.MOEAD; import org.moeaframework.core.Algorithm; -import org.moeaframework.core.FrameworkException; -import org.moeaframework.core.Initialization; -import org.moeaframework.core.Population; -import org.moeaframework.core.PopulationIO; import org.moeaframework.core.Problem; -import org.moeaframework.core.Solution; -import org.moeaframework.core.Variable; -import org.moeaframework.core.Variation; -import org.moeaframework.core.operator.RandomInitialization; -import org.moeaframework.core.spi.OperatorFactory; import org.moeaframework.core.spi.RegisteredAlgorithmProvider; -import org.moeaframework.core.variable.RealVariable; import org.moeaframework.util.TypedProperties; -import org.moeaframework.util.io.CommentedLineReader; import org.moeaframework.util.weights.NormalBoundaryDivisions; -import org.moeaframework.util.weights.NormalBoundaryIntersectionGenerator; -import org.moeaframework.util.weights.WeightGenerator; public class GDMOEADProvider extends RegisteredAlgorithmProvider { @@ -36,106 +15,16 @@ public GDMOEADProvider() { } private Algorithm newGDMOEAD(TypedProperties properties, Problem problem) { - //provide weights - WeightGenerator weightGenerator = null; + GDMOEAD algorithm; if (properties.contains("targets")) { - weightGenerator = new GeneralizedDecomposition(loadTargets(properties.getString("targets", null))); + algorithm = new GDMOEAD(problem, properties.getString("targets")); } else { - NormalBoundaryDivisions divisions = NormalBoundaryDivisions.fromProperties(properties, problem); - - weightGenerator = new GeneralizedDecomposition(new NormalBoundaryIntersectionGenerator( - problem.getNumberOfObjectives(), divisions)); - } - - int populationSize = weightGenerator.size(); - - //enforce population size lower bound - if (populationSize < problem.getNumberOfObjectives()) { - System.err.println("increasing MOEA/D population size"); - populationSize = problem.getNumberOfObjectives(); - } - - Initialization initialization = new RandomInitialization(problem); - - //default to de+pm for real-encodings - String operator = properties.getString("operator", null); - - if ((operator == null) && checkType(RealVariable.class, problem)) { - operator = "de+pm"; - } - - Variation variation = OperatorFactory.getInstance().getVariation(operator, properties, problem); - - int neighborhoodSize = 20; - int eta = 2; - - if (properties.contains("neighborhoodSize")) { - neighborhoodSize = Math.max(2, - (int)(properties.getDouble("neighborhoodSize", 0.1) * populationSize)); - } - - if (neighborhoodSize > populationSize) { - neighborhoodSize = populationSize; - } - - if (properties.contains("eta")) { - eta = Math.max(2, (int)(properties.getDouble("eta", 0.01) * populationSize)); - } - - return new MOEAD( - problem, - populationSize, - neighborhoodSize, - weightGenerator, - initialization, - variation, - properties.getDouble("delta", 0.9), - eta, - (int)properties.getDouble("updateUtility", -1)); - } - - private List loadTargets(String resource) { - File file = new File(resource); - Population population = null; - - try { - if (file.exists()) { - population = PopulationIO.readObjectives(file); - } else { - try (InputStream input = getClass().getResourceAsStream("/" + resource)) { - if (input != null) { - population = PopulationIO.readObjectives(new CommentedLineReader(new InputStreamReader(input))); - } - } - } - } catch (IOException e) { - throw new FrameworkException("failed to load " + resource, e); - } - - if (population == null) { - throw new FrameworkException("could not find " + resource); - } - - List targets = new ArrayList(); - - for (Solution solution : population) { - targets.add(solution.getObjectives()); - } - - return targets; - } - - private boolean checkType(Class type, Problem problem) { - Solution solution = problem.newSolution(); - - for (int i=0; i