762 lines
33 KiB
Java
762 lines
33 KiB
Java
package eva2.server.go.operators.migration;
|
|
|
|
|
|
import java.io.*;
|
|
import java.util.ArrayList;
|
|
|
|
import eva2.gui.GraphPointSet;
|
|
import eva2.gui.Plot;
|
|
import eva2.server.go.individuals.AbstractEAIndividual;
|
|
import eva2.server.go.operators.archiving.ArchivingAllDominating;
|
|
import eva2.server.go.operators.archiving.ArchivingNSGAII;
|
|
import eva2.server.go.operators.archiving.InterfaceArchiving;
|
|
import eva2.server.go.operators.cluster.ClusteringKMeans;
|
|
import eva2.server.go.operators.constraint.ConstObjectivesInEqualityBiggerThanLinear;
|
|
import eva2.server.go.operators.constraint.ConstObjectivesInEqualityBiggerThanSurface;
|
|
import eva2.server.go.operators.constraint.ConstObjectivesInEqualityLesserThanLinear;
|
|
import eva2.server.go.operators.constraint.ConstObjectivesInEqualitySmallerThanSurface;
|
|
import eva2.server.go.operators.selection.InterfaceSelection;
|
|
import eva2.server.go.operators.selection.SelectMOMaxiMin;
|
|
import eva2.server.go.operators.selection.SelectRandom;
|
|
import eva2.server.go.populations.Population;
|
|
import eva2.server.go.problems.AbstractMultiObjectiveOptimizationProblem;
|
|
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
|
import eva2.server.go.strategies.InterfaceOptimizer;
|
|
import eva2.server.go.strategies.MultiObjectiveEA;
|
|
import eva2.tools.chart2d.Chart2DDPointIconCircle;
|
|
import eva2.tools.chart2d.Chart2DDPointIconText;
|
|
import eva2.tools.chart2d.DPoint;
|
|
|
|
/** This method implements the cone separation subdivision
|
|
* scheme, this method rearanges the populations and may
|
|
* impose area constraints on the subpopulations.
|
|
* Created by IntelliJ IDEA.
|
|
* User: streiche
|
|
* Date: 15.09.2004
|
|
* Time: 17:39:26
|
|
* To change this template use File | Settings | File Templates.
|
|
*/
|
|
public class MOConeSeparation implements InterfaceMigration, java.io.Serializable {
|
|
|
|
public boolean m_Debug = false;
|
|
private boolean m_UseAllToDetermineR = false; // since i'm only interessted in the pareto-front this should be set to false!!
|
|
private boolean m_UseConstraints = true;
|
|
private InterfaceSelection m_Selection = new SelectRandom();
|
|
private double[][] m_3DBounds;
|
|
|
|
public MOConeSeparation() {
|
|
|
|
}
|
|
|
|
public MOConeSeparation(MOConeSeparation b) {
|
|
this.m_Debug = b.m_Debug;
|
|
this.m_UseConstraints = b.m_UseConstraints;
|
|
this.m_UseAllToDetermineR = b.m_UseAllToDetermineR;
|
|
if (b.m_Selection != null) {
|
|
this.m_Selection = (InterfaceSelection)b.m_Selection.clone();
|
|
}
|
|
}
|
|
|
|
/** The ever present clone method
|
|
*/
|
|
public Object clone() {
|
|
return new MOConeSeparation(this);
|
|
}
|
|
|
|
/** Typically i'll need some initialization method for
|
|
* every bit of code i write....
|
|
*/
|
|
public void initMigration(InterfaceOptimizer[] islands) {
|
|
// pff at a later stage i could initialize a topology here
|
|
}
|
|
|
|
/** The migrate method can be called asychnronously or
|
|
* sychronously. Basically it allows migration of individuals
|
|
* between multiple EA islands and since there are so many
|
|
* different possible strategies i've introduced this
|
|
* interface which is mostlikely subject to numerous changes..
|
|
* Note: Since i use the RMIRemoteThreadProxy everything done
|
|
* to the islands will use the serialization method, so if
|
|
* you call getPopulation() on an island it is not a reference
|
|
* to the population but a serialized copy of the population!!
|
|
*/
|
|
public void migrate(InterfaceOptimizer[] islands) {
|
|
Population[] oldIPOP = new Population[islands.length];
|
|
Population[] newIPOP = new Population[islands.length];
|
|
Population collector = new Population(), memory;
|
|
InterfaceArchiving allDom = new ArchivingAllDominating();
|
|
|
|
// collect the populations
|
|
for (int i = 0; i < islands.length; i++) {
|
|
oldIPOP[i] = islands[i].getPopulation();
|
|
if (this.m_Debug) System.out.println("Got population from "+i+" of size "+oldIPOP[i].size());
|
|
collector.addPopulation((Population)oldIPOP[i].clone());
|
|
newIPOP[i] = new Population();
|
|
}
|
|
memory = (Population)collector.clone();
|
|
|
|
if (((AbstractEAIndividual)collector.get(0)).getFitness().length == 2) {
|
|
this.coneSeparation2D(collector, newIPOP, islands);
|
|
} else {
|
|
if (((AbstractEAIndividual)collector.get(0)).getFitness().length == 3) {
|
|
this.coneSeparation3D(collector, newIPOP, islands);
|
|
} else {
|
|
if (((AbstractEAIndividual)collector.get(0)).getFitness().length >= 4) {
|
|
System.out.println("*Pff*");
|
|
}
|
|
}
|
|
}
|
|
// set the population back to the islands
|
|
for (int i = 0; i < islands.length; i++) {
|
|
oldIPOP[i].clear();
|
|
oldIPOP[i].addPopulation(newIPOP[i]);
|
|
// todo remove this for nice pictures
|
|
if (!oldIPOP[i].targetSizeReached()) {
|
|
oldIPOP[i].addPopulation(this.m_Selection.selectFrom(memory, oldIPOP[i].getTargetSize()-oldIPOP[i].size()));
|
|
}
|
|
if (this.m_Debug) System.out.println("Setting island "+i+" to population size " + oldIPOP[i].size());
|
|
allDom.addElementsToArchive(oldIPOP[i]);
|
|
islands[i].setPopulation(oldIPOP[i]);
|
|
}
|
|
}
|
|
|
|
/** This method performs cone separation in 2D
|
|
* @param collector This is a aggregated population;
|
|
* @param newIPOP The new population on the islands after separation
|
|
* @param islands The optimizer required to get the problem to set the constraints.
|
|
*/
|
|
private void coneSeparation2D(Population collector, Population[] newIPOP, InterfaceOptimizer[] islands) {
|
|
AbstractEAIndividual indy;
|
|
|
|
// if (this.m_Debug) {
|
|
// // let's see how they arrive here
|
|
// // This shows that the Drecksbeutels
|
|
// // indeed spread out, even within
|
|
// // two generations!!!
|
|
// Plot plot;
|
|
// double[] tmpD = new double[2];
|
|
// tmpD[0] = 0;
|
|
// tmpD[1] = 0;
|
|
// plot = new eva2.gui.Plot("Debugging Cone Separation", "Y1", "Y2", tmpD, tmpD);
|
|
// GraphPointSet mySet;
|
|
// DPoint myPoint;
|
|
// Chart2DDPointIconText tmp;
|
|
// for (int i = 0; i < oldIPOP.length; i++) {
|
|
// mySet = new GraphPointSet(10+1, plot.getFunctionArea());
|
|
// mySet.setConnectedMode(false);
|
|
// for (int j = 0; j < oldIPOP[i].size(); j++) {
|
|
// indy = (AbstractEAIndividual)oldIPOP[i].get(j);
|
|
// myPoint = new DPoint(indy.getFitness()[0], indy.getFitness()[1]);
|
|
// tmp = new Chart2DDPointIconText(""+i);
|
|
// if (indy.m_AreaConst4ParallelViolated) tmp.setIcon(new Chart2DDPointIconCircle());
|
|
// myPoint.setIcon(tmp);
|
|
// mySet.addDPoint(myPoint);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// now let's find the reference point first just in 2D
|
|
InterfaceArchiving allDom = new ArchivingAllDominating();
|
|
allDom.addElementsToArchive(collector);
|
|
int y1Big = 0, y2Big = 0;
|
|
Population archive = collector.getArchive();
|
|
Population ref;
|
|
|
|
if (this.m_UseAllToDetermineR) ref = collector;
|
|
else ref = archive;
|
|
|
|
for (int i = 1; i < ref.size(); i++) {
|
|
if (((AbstractEAIndividual)ref.get(i)).getFitness()[0] > ((AbstractEAIndividual)ref.get(y1Big)).getFitness()[0]) {
|
|
y1Big = i;
|
|
}
|
|
if (((AbstractEAIndividual)ref.get(i)).getFitness()[1] > ((AbstractEAIndividual)ref.get(y2Big)).getFitness()[1]) {
|
|
y2Big = i;
|
|
}
|
|
}
|
|
double[] r = new double[2];
|
|
double alpha = 90.0/(double)islands.length;
|
|
double[][] boundaries = new double[islands.length-1][2];
|
|
r[0] = ((AbstractEAIndividual)ref.get(y1Big)).getFitness()[0];
|
|
r[1] = ((AbstractEAIndividual)ref.get(y2Big)).getFitness()[1];
|
|
for (int i = 0; i < boundaries.length; i++) {
|
|
boundaries[i][0] = 1 / Math.tan(Math.toRadians(alpha*(i+1)));
|
|
boundaries[i][1] = r[1] - boundaries[i][0]*r[0];
|
|
// System.out.println("Boundary"+i+" f(x)="+boundaries[i][0]+"*x + "+ boundaries[i][1]);
|
|
}
|
|
|
|
collector.SetArchive(new Population());
|
|
|
|
// Now i got the cone's let's separate
|
|
for (int i = 0; i < boundaries.length; i++) {
|
|
for (int j = 0; j < collector.size(); j++) {
|
|
indy = (AbstractEAIndividual)collector.get(j);
|
|
if (indy.getFitness()[1] < boundaries[i][0]*indy.getFitness()[0]+boundaries[i][1]) {
|
|
// this guy belongs to cone i
|
|
newIPOP[i].add(indy);
|
|
collector.remove(j);
|
|
j--;
|
|
}
|
|
}
|
|
}
|
|
// the rest belongs to newIPOP.length-1
|
|
newIPOP[newIPOP.length-1].addPopulation(collector);
|
|
|
|
if (this.m_Debug) {
|
|
Plot plot;
|
|
double[] tmpD = new double[2];
|
|
tmpD[0] = 0;
|
|
tmpD[1] = 0;
|
|
plot = new eva2.gui.Plot("Debugging Cone Separation", "Y1", "Y2", tmpD, tmpD);
|
|
GraphPointSet mySet;
|
|
DPoint myPoint;
|
|
Chart2DDPointIconText tmp;
|
|
mySet = new GraphPointSet(9, plot.getFunctionArea());
|
|
mySet.setConnectedMode(false);
|
|
// now plot the region boundaries
|
|
for (int i = 0; i < 250; i++) {
|
|
myPoint = new DPoint(0, 0);
|
|
mySet.addDPoint(myPoint);
|
|
}
|
|
for (int i = 0; i < newIPOP.length; i++) {
|
|
mySet = new GraphPointSet(10+i, plot.getFunctionArea());
|
|
mySet.setConnectedMode(false);
|
|
for (int j = 0; j < newIPOP[i].size(); j++) {
|
|
indy = (AbstractEAIndividual)newIPOP[i].get(j);
|
|
myPoint = new DPoint(indy.getFitness()[0], indy.getFitness()[1]);
|
|
tmp = new Chart2DDPointIconText(""+i);
|
|
if (i % 2 == 0) tmp.setIcon(new Chart2DDPointIconCircle());
|
|
myPoint.setIcon(tmp);
|
|
mySet.addDPoint(myPoint);
|
|
}
|
|
}
|
|
mySet = new GraphPointSet(10, plot.getFunctionArea());
|
|
mySet.setConnectedMode(false);
|
|
// now plot the region boundaries
|
|
for (int i = 0; i < islands.length-1; i++) {
|
|
myPoint = new DPoint(r[0], r[1]);
|
|
mySet.addDPoint(myPoint);
|
|
myPoint = new DPoint(r[0], r[1]);
|
|
mySet.addDPoint(myPoint);
|
|
if (boundaries[i][1] > 0) {
|
|
myPoint = new DPoint(0.0, boundaries[i][1]);
|
|
mySet.addDPoint(myPoint);
|
|
myPoint = new DPoint(0.0, boundaries[i][1]);
|
|
mySet.addDPoint(myPoint);
|
|
} else {
|
|
myPoint = new DPoint(-boundaries[i][1]/boundaries[i][0], 0);
|
|
mySet.addDPoint(myPoint);
|
|
myPoint = new DPoint(-boundaries[i][1]/boundaries[i][0], 0);
|
|
mySet.addDPoint(myPoint);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.m_UseConstraints) {
|
|
// i should set the constraints to the optimizers
|
|
InterfaceOptimizationProblem prob;
|
|
for (int i = 0; i < islands.length; i++) {
|
|
prob = (InterfaceOptimizationProblem) islands[i].getProblem();
|
|
if (prob instanceof AbstractMultiObjectiveOptimizationProblem) {
|
|
// set the boundaries to perform the constrained
|
|
// domain principle introduced by Deb et al.
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.clear();
|
|
if (i > 0) {
|
|
// add the lower boundary
|
|
ConstObjectivesInEqualityBiggerThanLinear b = new ConstObjectivesInEqualityBiggerThanLinear(boundaries[i-1][0], boundaries[i-1][1]);
|
|
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(b);
|
|
}
|
|
if (i < islands.length-1) {
|
|
// add the upper boundary
|
|
ConstObjectivesInEqualityLesserThanLinear b = new ConstObjectivesInEqualityLesserThanLinear(boundaries[i][0], boundaries[i][1]);
|
|
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(b);
|
|
}
|
|
islands[i].SetProblem(prob);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** This method performs cone separation in 2D
|
|
* @param collector This is a aggregated population;
|
|
* @param newIPOP The new population on the islands after separation
|
|
* @param islands The optimizer required to get the problem to set the constraints.
|
|
*/
|
|
private void coneSeparation3D(Population collector, Population[] newIPOP, InterfaceOptimizer[] islands) {
|
|
AbstractEAIndividual indy;
|
|
|
|
// now let's find the reference point first just in 2D
|
|
InterfaceArchiving allDom = new ArchivingAllDominating();
|
|
allDom.addElementsToArchive(collector);
|
|
int y1Big = 0, y2Big = 0, y3Big = 0;
|
|
Population archive = collector.getArchive();
|
|
Population ref;
|
|
|
|
if (this.m_UseAllToDetermineR) ref = collector;
|
|
else ref = archive;
|
|
|
|
for (int i = 1; i < ref.size(); i++) {
|
|
if (((AbstractEAIndividual)ref.get(i)).getFitness()[0] > ((AbstractEAIndividual)ref.get(y1Big)).getFitness()[0]) {
|
|
y1Big = i;
|
|
}
|
|
if (((AbstractEAIndividual)ref.get(i)).getFitness()[1] > ((AbstractEAIndividual)ref.get(y2Big)).getFitness()[1]) {
|
|
y2Big = i;
|
|
}
|
|
if (((AbstractEAIndividual)ref.get(i)).getFitness()[2] > ((AbstractEAIndividual)ref.get(y3Big)).getFitness()[2]) {
|
|
y3Big = i;
|
|
}
|
|
}
|
|
// now build a 3D bounding rule
|
|
double[] distopian = new double[3], zE = new double[3];
|
|
double[][] normals = new double[islands.length][3];
|
|
double angIncr = 360.0 /(double)islands.length;
|
|
|
|
distopian[0] = ((AbstractEAIndividual)ref.get(y1Big)).getFitness()[0];
|
|
distopian[1] = ((AbstractEAIndividual)ref.get(y2Big)).getFitness()[1];
|
|
distopian[2] = ((AbstractEAIndividual)ref.get(y3Big)).getFitness()[2];
|
|
|
|
zE[0] = 0; zE[1] = 0; zE[2] = 1;
|
|
|
|
double[] firstVec = this.getCrossProduct(distopian, zE);
|
|
firstVec = this.getNormalized(firstVec);
|
|
double[] normDist = this.getNormalized(distopian);
|
|
|
|
this.m_3DBounds = new double[normals.length+2][3];
|
|
this.m_3DBounds[0] = distopian;
|
|
|
|
for (int i = 0; i < normals.length; i++) {
|
|
normals[i] = this.rotVector(firstVec, normDist, Math.toRadians(i*angIncr));
|
|
this.m_3DBounds[i+1] = normals[i];
|
|
}
|
|
|
|
// now i got the bounding planes
|
|
double[][] lastBoundingPlane = new double[2][3]; // first double[3] gives a point on the plane, the second gives the normal on the plane
|
|
double[][] curBoundingPlane = new double[2][3];
|
|
double[] fitness;
|
|
InterfaceOptimizationProblem prob;
|
|
lastBoundingPlane[0] = distopian;
|
|
lastBoundingPlane[1] = normals[normals.length-1];
|
|
curBoundingPlane[0] = distopian;
|
|
curBoundingPlane[1] = normals[0];
|
|
|
|
collector.SetArchive(new Population());
|
|
|
|
// Now i got the cone's let's separate
|
|
for (int i = 0; i < normals.length; i++) {
|
|
for (int j = 0; j < collector.size(); j++) {
|
|
indy = (AbstractEAIndividual)collector.get(j);
|
|
fitness = indy.getFitness();
|
|
if ((this.getScalarProduct(curBoundingPlane[1], this.getVectorSub(fitness, curBoundingPlane[0])) < 0) &&
|
|
(this.getScalarProduct(lastBoundingPlane[1], this.getVectorSub(fitness, lastBoundingPlane[0])) >= 0)) {
|
|
// this guy belongs to cone i
|
|
newIPOP[i].add(indy);
|
|
// collector.remove(j);
|
|
// j--;
|
|
}
|
|
}
|
|
if (this.m_UseConstraints) {
|
|
prob = (InterfaceOptimizationProblem) islands[i].getProblem();
|
|
if (prob instanceof AbstractMultiObjectiveOptimizationProblem) {
|
|
// set the boundaries to perform the constrained
|
|
// domain principle introduced by Deb et al.
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.clear();
|
|
ConstObjectivesInEqualitySmallerThanSurface sts = new ConstObjectivesInEqualitySmallerThanSurface(curBoundingPlane[0], curBoundingPlane[1]);
|
|
ConstObjectivesInEqualityBiggerThanSurface bts = new ConstObjectivesInEqualityBiggerThanSurface(lastBoundingPlane[0], lastBoundingPlane[1]);
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(sts);
|
|
((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(bts);
|
|
}
|
|
islands[i].SetProblem(prob);
|
|
// if (true) {
|
|
// prob.evaluate(newIPOP[i]);
|
|
// System.out.println("Invalid Individual in Island "+i+" ("+newIPOP[i].size()+"): ");
|
|
// for (int j = 0; j < newIPOP[i].size(); j++) {
|
|
// if(((AbstractEAIndividual)newIPOP[i].get(j)).m_AreaConst4ParallelViolated) {
|
|
// System.out.print(j+", ");
|
|
// ((AbstractEAIndividual)newIPOP[i].get(j)).checkAreaConst4Parallelization(((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization);
|
|
// }
|
|
// }
|
|
// System.out.println("");
|
|
// }
|
|
}
|
|
lastBoundingPlane[0] = curBoundingPlane[0];
|
|
lastBoundingPlane[1] = curBoundingPlane[1];
|
|
curBoundingPlane[0] = distopian;
|
|
if (i+1 < normals.length) curBoundingPlane[1] = normals[i+1];
|
|
// else curBoundingPlane[1] = normals[0];
|
|
}
|
|
// System.out.println("collector.size() "+ collector.size());
|
|
// // the rest belongs to newIPOP.length-1
|
|
// curBoundingPlane[0] = distopian;
|
|
// curBoundingPlane[1] = normals[normals.length-1];
|
|
// lastBoundingPlane[0] = distopian;
|
|
// lastBoundingPlane[1] = normals[0];
|
|
//
|
|
// int last = newIPOP.length-1;
|
|
// newIPOP[last].addPopulation(collector);
|
|
// if (this.m_UseConstraints) {
|
|
// prob = (InterfaceOptimizationProblem) islands[last].getProblem();
|
|
// if (prob instanceof AbstractMultiObjectiveOptimizationProblem) {
|
|
// // set the boundaries to perform the constrained
|
|
// // domain principle introduced by Deb et al.
|
|
// ((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.clear();
|
|
// ConstObjectivesInEqualitySmallerThanSurface sts = new ConstObjectivesInEqualitySmallerThanSurface(curBoundingPlane[0], curBoundingPlane[1]);
|
|
// ConstObjectivesInEqualityBiggerThanSurface bts = new ConstObjectivesInEqualityBiggerThanSurface(lastBoundingPlane[0], lastBoundingPlane[1]);
|
|
// ((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(sts);
|
|
// ((AbstractMultiObjectiveOptimizationProblem)prob).m_AreaConst4Parallelization.add(bts);
|
|
// }
|
|
// islands[last].SetProblem(prob);
|
|
// }
|
|
// System.out.println("collector.size() "+ collector.size());
|
|
// for (int i = 0; i < newIPOP.length; i++) {
|
|
// System.out.println("newIPOP["+i+ "]: "+ newIPOP[i].size());
|
|
// }
|
|
}
|
|
|
|
/** This method returns the scalar product of two vectors
|
|
* @param a The first vector
|
|
* @param b The second vector
|
|
* @return The scalar product of a and b
|
|
*/
|
|
private double getScalarProduct(double[] a, double[] b) {
|
|
return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
|
|
}
|
|
|
|
/** This method returns the cross product of two 3D vectors
|
|
* @param a The first vector
|
|
* @param b The second vector
|
|
* @return The cross product
|
|
*/
|
|
private double[] getCrossProduct(double[] a, double[] b) {
|
|
double[] result = new double[3];
|
|
|
|
result[0] = a[1]*b[2] - a[2]*b[1];
|
|
result[1] = a[2]*b[0] - a[0]*b[2];
|
|
result[2] = a[0]*b[1] - a[1]*b[0];
|
|
|
|
return result;
|
|
}
|
|
|
|
private double[] getVectorAdd(double[] a, double[] b) {
|
|
double[] result = new double[3];
|
|
|
|
result[0] = a[0]+b[0];
|
|
result[1] = a[1]+b[1];
|
|
result[2] = a[2]+b[2];
|
|
|
|
return result;
|
|
}
|
|
|
|
private double[] getVectorSub(double[] a, double[] b) {
|
|
double[] result = new double[3];
|
|
|
|
result[0] = a[0]-b[0];
|
|
result[1] = a[1]-b[1];
|
|
result[2] = a[2]-b[2];
|
|
|
|
return result;
|
|
}
|
|
|
|
private double[] getScalarMultiplication(double a, double[] b) {
|
|
double[] result = new double[3];
|
|
|
|
result[0] = a*b[0];
|
|
result[1] = a*b[1];
|
|
result[2] = a*b[2];
|
|
|
|
return result;
|
|
}
|
|
|
|
/** This method will return a normalized vector
|
|
* @param a The vector to normalize
|
|
* @return A normalized version of the input vector
|
|
*/
|
|
private double[] getNormalized(double[] a) {
|
|
double[] result = new double[a.length];
|
|
double sum = 0;
|
|
for (int i = 0; i < a.length; i++) {
|
|
sum += Math.pow(a[i], 2);
|
|
}
|
|
sum = Math.sqrt(sum);
|
|
for (int i = 0; i < a.length; i++) {
|
|
result[i] = a[i]/sum;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/** Quaternion rotation
|
|
* @param s The first quaternion
|
|
* @param v The second quaternion
|
|
* @return The resulting quaternion
|
|
*/
|
|
private double[] qMult(double[] s, double[] v) {
|
|
double[] r = new double[4];
|
|
r[0] = s[0]*v[0] - s[1]*v[1] - s[2]*v[2] - s[3]*v[3];
|
|
r[1] = s[0]*v[1] + s[1]*v[0] + s[2]*v[3] - s[3]*v[2];
|
|
r[2] = s[0]*v[2] - s[1]*v[3] + s[2]*v[0] + s[3]*v[1];
|
|
r[3] = s[0]*v[3] + s[1]*v[2] - s[2]*v[1] + s[3]*v[0];
|
|
return r;
|
|
}
|
|
|
|
/** This method will perform a quaterion rotation
|
|
* @param v The vector to rotate
|
|
* @param u The vector to rotate aroung
|
|
* @param alpha The rotation angle in RAD!
|
|
* @return The resulting rotated vector
|
|
*/
|
|
private double[] rotQuad(double[] v, double[] u, double alpha) {
|
|
double[] result = new double[3];
|
|
double[] q = new double[4];
|
|
double[] qt = new double[4];
|
|
double[] p = new double[4];
|
|
double s, f;
|
|
|
|
p[0] = 0;
|
|
p[1] = v[0];
|
|
p[2] = v[1];
|
|
p[3] = v[2];
|
|
s = Math.cos(alpha/2.0);
|
|
f = Math.sin(alpha/2.0);
|
|
q[0] = s;
|
|
q[1] = u[0]*f;
|
|
q[2] = u[1]*f;
|
|
q[3] = u[2]*f;
|
|
// ok bis hier hin
|
|
qt[0] = s;
|
|
qt[1] = -q[1];
|
|
qt[2] = -q[2];
|
|
qt[3] = -q[3];
|
|
p = this.qMult(q, p);
|
|
p = this.qMult(p, qt);
|
|
f = 1/(q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
|
|
result[0] = p[1];// * f;
|
|
result[1] = p[2]; // * f;
|
|
result[2] = p[3]; // * f;
|
|
result = this.getNormalized(result);
|
|
return result;
|
|
}
|
|
|
|
private double[] rotVector(double[] p, double[] w, double a) {
|
|
double[] result, tmp1, tmp2, tmp3;
|
|
|
|
tmp1 = this.getScalarMultiplication(Math.cos(a), p);
|
|
tmp2 = this.getScalarMultiplication(this.getScalarProduct(w, p), p);
|
|
tmp2 = this.getScalarMultiplication((1-Math.cos(a)), tmp2);
|
|
tmp3 = this.getScalarMultiplication(Math.sin(a), this.getCrossProduct(w, p));
|
|
result = this.getVectorAdd(tmp1, tmp2);
|
|
result = this.getVectorAdd(result, tmp3);
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// public static void main(String[] args) {
|
|
// MOConeSeparation cone = new MOConeSeparation();
|
|
// cone.setUseConstraints(true);
|
|
// BufferedWriter outfile = null, outfile1 = null, outfile2 = null;
|
|
//
|
|
///**
|
|
// double[] tmpDir = new double[3];
|
|
// double[] tmpVec = new double[3];
|
|
// double[] result;
|
|
// int n = 8;
|
|
// double alpha = 0;
|
|
// double incr = 360 /(double)n;
|
|
// incr = 10;
|
|
// tmpDir[0] = 0;
|
|
// tmpDir[1] = 0;
|
|
// tmpDir[2] = 1;
|
|
// tmpVec[0] = 0;
|
|
// tmpVec[1] = 1;
|
|
// tmpVec[2] = 0;
|
|
//
|
|
// // First the reference vector
|
|
// try {
|
|
// outfile1 = new BufferedWriter(new OutputStreamWriter (new FileOutputStream ("C://Programme//MATLAB6p5p1//work//MOTestSurfVec.txt")));
|
|
// outfile2 = new BufferedWriter(new OutputStreamWriter (new FileOutputStream ("C://Programme//MATLAB6p5p1//work//MOTestSurf.txt")));
|
|
// } catch (FileNotFoundException e) {
|
|
// System.out.println("Could not open output file! Filename: ");
|
|
// }
|
|
// cone.writeToFile(outfile1, "0\t 0\t 0");
|
|
// cone.writeToFile(outfile1, ""+tmpDir[0]+"\t"+tmpDir[1]+"\t"+tmpDir[2]);
|
|
//
|
|
// for (int i = 0; i < n; i++) {
|
|
// result = cone.rotQuad(tmpVec, tmpDir, Math.toRadians(i*incr));
|
|
// System.out.println("Alpha: " + alpha);
|
|
// System.out.println(result[0]+"\t"+result[1]+"\t"+result[2]);
|
|
// //cone.writeToFile(outfile2, ""+tmpDir[0]+"\t"+tmpDir[1]+"\t"+tmpDir[2]);
|
|
// cone.writeToFile(outfile2, "0\t 0\t 0");
|
|
// cone.writeToFile(outfile2, ""+(result[0])+"\t"+(result[1])+"\t"+(result[2]));
|
|
// alpha += incr;
|
|
// }
|
|
//
|
|
// try{
|
|
// outfile1.close();
|
|
// outfile2.close();
|
|
// } catch (IOException e) {
|
|
// System.out.println("Couldn't even close the stuff");
|
|
// }
|
|
// **/
|
|
//
|
|
// TFPortfolioSelectionProblem problem = new TFPortfolioSelectionProblem();
|
|
// problem.getOptimizationTargets().removeTarget(0);
|
|
// problem.getOptimizationTargets().removeTarget(0);
|
|
// OptTargetPortfolioReturn ret = new OptTargetPortfolioReturn();
|
|
// ret.setNormalizeTarget(true);
|
|
// problem.getOptimizationTargets().addTarget(ret);
|
|
// OptTargetPortfolioRisk ris = new OptTargetPortfolioRisk();
|
|
// ris.setNormalizeTarget(true);
|
|
// problem.getOptimizationTargets().addTarget(ris);
|
|
// OptTargetPortfolioDuration dur = new OptTargetPortfolioDuration();
|
|
// dur.setNormalizeTarget(true);
|
|
// problem.getOptimizationTargets().addTarget(dur);
|
|
//
|
|
// int n = 4;
|
|
// MultiObjectiveEA[] islands = new MultiObjectiveEA[n];
|
|
// for (int i = 0; i < islands.length; i++) {
|
|
// islands[i] = new MultiObjectiveEA();
|
|
// islands[i].SetProblem(problem);
|
|
// islands[i].init();
|
|
// }
|
|
//
|
|
// for (int i = 0; i < 20; i++) {
|
|
// for (int j = 0; j < islands.length; j++) {
|
|
// islands[j].optimize();
|
|
// }
|
|
// if (i % 4 == 0) cone.migrate(islands);
|
|
// }
|
|
//
|
|
// cone.migrate(islands);
|
|
//
|
|
// double[] fitness;
|
|
// ArchivingAllDominating arch = new ArchivingAllDominating();
|
|
//
|
|
// for (int i = 0; i < islands.length; i++) {
|
|
// try {
|
|
// outfile = new BufferedWriter(new OutputStreamWriter (new FileOutputStream ("C://Programme//MATLAB6p5p1//work//MOCone"+i+".txt")));
|
|
// } catch (FileNotFoundException e) {
|
|
// System.out.println("Could not open output file! Filename: ");
|
|
// }
|
|
// //cone.writeToFile(outfile, " x\t y\t z");
|
|
// islands[i].getPopulation().SetArchive(new Population());
|
|
// arch.addElementsToArchive(islands[i].getPopulation());
|
|
// for (int j = 0; j < islands[i].getPopulation().getArchive().size(); j++) {
|
|
// fitness = ((AbstractEAIndividual)islands[i].getPopulation().getArchive().get(j)).getFitness();
|
|
// cone.writeToFile(outfile, ""+fitness[0]+"\t"+fitness[1]+"\t"+fitness[2]);
|
|
// }
|
|
// try{
|
|
// outfile.close();
|
|
// } catch (IOException e) {
|
|
// System.out.println("Couldn'T even close the stuff");
|
|
// }
|
|
// }
|
|
//
|
|
// // First the reference vector
|
|
// try {
|
|
// outfile = new BufferedWriter(new OutputStreamWriter (new FileOutputStream ("C://Programme//MATLAB6p5p1//work//MOConeSurfVec.txt")));
|
|
// } catch (FileNotFoundException e) {
|
|
// System.out.println("Could not open output file! Filename: ");
|
|
// }
|
|
// double[][] surf = cone.m_3DBounds;
|
|
// cone.writeToFile(outfile, "0\t 0\t 0");
|
|
// cone.writeToFile(outfile, ""+surf[0][0]+"\t"+surf[0][1]+"\t"+surf[0][2]);
|
|
// cone.writeToFile(outfile, ""+surf[0][0]+"\t"+surf[0][1]+"\t"+surf[0][2]);
|
|
// cone.writeToFile(outfile, "0\t 0\t 0");
|
|
// try{
|
|
// outfile.close();
|
|
// } catch (IOException e) {
|
|
// System.out.println("Couldn't even close the stuff");
|
|
// }
|
|
//
|
|
// // now the surface normals
|
|
// try {
|
|
// outfile = new BufferedWriter(new OutputStreamWriter (new FileOutputStream ("C://Programme//MATLAB6p5p1//work//MOConeSurf.txt")));
|
|
// } catch (FileNotFoundException e) {
|
|
// System.out.println("Could not open output file! Filename: ");
|
|
// }
|
|
// for (int i = 1; i < surf.length; i++) {
|
|
// cone.writeToFile(outfile, ""+surf[0][0]+"\t"+surf[0][1]+"\t"+surf[0][2]);
|
|
// surf[i] = cone.getScalarMultiplication(0.02, surf[i]);
|
|
// cone.writeToFile(outfile, ""+(surf[i][0]+surf[0][0])+"\t"+(surf[i][1]+surf[0][1])+"\t"+(surf[i][2]+surf[0][2]));
|
|
// cone.writeToFile(outfile, ""+surf[0][0]+"\t"+surf[0][1]+"\t"+surf[0][2]);
|
|
// }
|
|
// try{
|
|
// outfile.close();
|
|
// } catch (IOException e) {
|
|
// System.out.println("Couldn't even close the stuff");
|
|
// }
|
|
//
|
|
// Population pop = new Population();
|
|
// for (int i = 0; i < islands.length; i++) {
|
|
// pop.addPopulation(islands[i].getPopulation());
|
|
// pop.addPopulation(islands[i].getPopulation().getArchive());
|
|
// }
|
|
// //System.out.println("S-Metric: "+problem.getMetric().calculateMetricOn(pop, problem));
|
|
//
|
|
// System.exit(0);
|
|
// }
|
|
|
|
/** This method writes Data to file.
|
|
* @param line The line that is to be added to the file
|
|
*/
|
|
private void writeToFile(BufferedWriter out, String line) {
|
|
String write = line + "\n";
|
|
write.replaceAll(",",".");
|
|
if (out == null) return;
|
|
try {
|
|
out.write(write, 0, write.length());
|
|
out.flush();
|
|
} catch (IOException e) {
|
|
System.out.println("Problems writing to output file!");
|
|
}
|
|
}
|
|
|
|
/**********************************************************************************************************************
|
|
* These are for GUI
|
|
*/
|
|
/** This method returns a global info string
|
|
* @return description
|
|
*/
|
|
public static String globalInfo() {
|
|
return "This is migration scheme, which implements a cone separation based partitioning.";
|
|
}
|
|
/** This method will return a naming String
|
|
* @return The name of the algorithm
|
|
*/
|
|
public String getName() {
|
|
return "MOConeSeparation";
|
|
}
|
|
|
|
/** This method allows you to toggle which elements are
|
|
* to be used to calculate the reference point. If false
|
|
* all individuals are used to calculate the reference point.
|
|
* This can cause the algorithm to build cone segments, which
|
|
* are actually all dominated.
|
|
* @return The modus to calculate the reference point.
|
|
*/
|
|
public boolean getUseAllToDetermineR() {
|
|
return this.m_UseAllToDetermineR;
|
|
}
|
|
public void setUseAllToDetermineR(boolean b){
|
|
this.m_UseAllToDetermineR = b;
|
|
}
|
|
public String useAllToDetermineRTipText() {
|
|
return "If true all individuals are used to calculate the reference point (may reduce efficiency).";
|
|
}
|
|
|
|
/** This method allows you to toogle the use of constraints,
|
|
* which enable the algorithm to limit each island to a
|
|
* specific area of the search space.
|
|
* @return The modus of constraints.
|
|
*/
|
|
public boolean getUseConstraints() {
|
|
return this.m_UseConstraints;
|
|
}
|
|
public void setUseConstraints(boolean b){
|
|
this.m_UseConstraints = b;
|
|
}
|
|
public String useConstraintsTipText() {
|
|
return "If activated constraints are used to limit each island to a local area.";
|
|
}
|
|
}
|