Adding Binary Scatter Search and the Bayesian Optimization Algorithm from the branch of Alex Seitz (rev. 926)
This commit is contained in:
parent
0e54cf526b
commit
73efcca17b
@ -0,0 +1,104 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.operators.mutation.InterfaceAdaptOperatorGenerational;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
|
||||
/**
|
||||
* A modified version of the CrossoverEAMixer that adapts the weights with which the crossover-methods are chosen
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class AdaptiveCrossoverEAMixer extends CrossoverEAMixer implements InterfaceAdaptOperatorGenerational {
|
||||
|
||||
private Population pop = new Population();
|
||||
private boolean initialized = false;
|
||||
private double lastFitness = Double.MAX_VALUE;
|
||||
private int[] used;
|
||||
private InterfaceOptimizationProblem opt;
|
||||
|
||||
public AdaptiveCrossoverEAMixer(){
|
||||
super();
|
||||
}
|
||||
|
||||
public AdaptiveCrossoverEAMixer(AdaptiveCrossoverEAMixer mutator) {
|
||||
super(mutator);
|
||||
this.pop = (Population) mutator.pop.clone(); // TODO !Make a deep copy!?
|
||||
this.initialized = mutator.initialized;
|
||||
this.lastFitness = mutator.lastFitness;
|
||||
this.used = mutator.used;
|
||||
this.opt = mutator.opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mutation mixer with equal weights of the given mutation operators.
|
||||
* @param mutators
|
||||
*/
|
||||
public AdaptiveCrossoverEAMixer(InterfaceCrossover ... crossovers) {
|
||||
this.m_Crossers = new PropertyCrossoverMixer(crossovers);
|
||||
this.m_Crossers.m_SelectedTargets = m_Crossers.m_AvailableTargets.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void maybeAdaptWeights(AbstractEAIndividual[] indies) {
|
||||
if(initialized){
|
||||
AbstractEAIndividual indy = indies[0];
|
||||
this.opt.evaluate(indy);
|
||||
this.pop.incrFunctionCalls();
|
||||
if(indy.getFitness(0)<this.lastFitness){
|
||||
this.lastFitness = indy.getFitness(0);
|
||||
this.used[lastOperatorIndex] = this.used[lastOperatorIndex] + 1;
|
||||
int sum = 0;
|
||||
for(int i=0; i<this.used.length; i++){
|
||||
sum = sum + used[i];
|
||||
}
|
||||
double[] weights = new double[used.length];
|
||||
for(int i=0; i<weights.length; i++){
|
||||
weights[i] = ((double) used[i])/sum;
|
||||
}
|
||||
getCrossovers().setWeights(weights);
|
||||
}
|
||||
}else{
|
||||
System.err.println("not yet initialized");
|
||||
}
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual, InterfaceOptimizationProblem opt, Population pop, double fit){
|
||||
InterfaceCrossover[] mutators = this.m_Crossers.getSelectedCrossers();
|
||||
for (int i = 0; i < mutators.length; i++) mutators[i].init(individual, opt);
|
||||
this.pop = pop;
|
||||
this.lastFitness = fit;
|
||||
this.used = new int[getCrossovers().getWeights().length];
|
||||
for(int i=0; i<this.used.length; i++){
|
||||
this.used[i]=1;
|
||||
}
|
||||
this.opt = opt;
|
||||
this.initialized = true;
|
||||
}
|
||||
|
||||
public void update(AbstractEAIndividual individual, InterfaceOptimizationProblem opt, Population pop, double fit){
|
||||
InterfaceCrossover[] mutators = this.m_Crossers.getSelectedCrossers();
|
||||
for (int i = 0; i < mutators.length; i++) mutators[i].init(individual, opt);
|
||||
this.pop = pop;
|
||||
this.lastFitness = fit;
|
||||
this.opt = opt;
|
||||
}
|
||||
|
||||
public boolean isInitialized(){
|
||||
return this.initialized;
|
||||
}
|
||||
|
||||
public void adaptAfterSelection(Population oldPop, Population selectedPop) {
|
||||
// Nothing to to here
|
||||
|
||||
}
|
||||
|
||||
public void adaptGenerational(Population oldPop, Population selectedPop,
|
||||
Population newPop, boolean updateSelected) {
|
||||
// TODO Perform adaption here by checking how often individuals in newPop have used which operator
|
||||
// look at CrossoverEAMixer.CROSSOVER_EA_MIXER_OPERATOR_KEY or AbstractOptimizationProblem.OLD_FITNESS_KEY using AbstractEAIndividual.getData(KEY);
|
||||
System.out.println("In adaptGenerational");
|
||||
}
|
||||
}
|
78
src/eva2/server/go/operators/crossover/CM1.java
Normal file
78
src/eva2/server/go/operators/crossover/CM1.java
Normal file
@ -0,0 +1,78 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.server.go.strategies.BinaryScatterSearch;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* This crossover-Method performs a \"union\" of the selected Individuals
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM1 implements InterfaceCrossover, java.io.Serializable {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM1(){
|
||||
}
|
||||
|
||||
public CM1(CM1 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM1(this);
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getIndividual(0)).getBinaryData();
|
||||
for(int j=0; j<data2.size(); j++){
|
||||
if(data2.get(j)){
|
||||
data.set(j, true);
|
||||
}
|
||||
}
|
||||
partners.remove(0);
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(RNG.flipCoin(Math.max(0, 1-BinaryScatterSearch.score(i, partners)))&&data.get(i)){
|
||||
data.set(i, false);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0]=indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 1";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "This is a Crossover Method for Binary Individuals which just forms the \"union\" of the individuals";
|
||||
}
|
||||
|
||||
}
|
78
src/eva2/server/go/operators/crossover/CM2.java
Normal file
78
src/eva2/server/go/operators/crossover/CM2.java
Normal file
@ -0,0 +1,78 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.server.go.strategies.BinaryScatterSearch;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* This crossover-Method performs an \"intersection\" of the selected Individuals
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM2 implements InterfaceCrossover, java.io.Serializable {
|
||||
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM2(){
|
||||
|
||||
}
|
||||
|
||||
public CM2(CM2 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM2(this);
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getIndividual(0)).getBinaryData();
|
||||
for(int j=0; j<data2.length(); j++){
|
||||
if(data2.get(j)){
|
||||
data.set(j, true);
|
||||
}
|
||||
}
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(RNG.flipCoin(0.5)){
|
||||
data.set(i, false);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0]=indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 2";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "This is a Crossover Method for Binary Individuals which just forms the \"intersection\" of the individuals";
|
||||
}
|
||||
}
|
89
src/eva2/server/go/operators/crossover/CM3.java
Normal file
89
src/eva2/server/go/operators/crossover/CM3.java
Normal file
@ -0,0 +1,89 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* calculates a weight based on the fitnessValues and the configuration of each bit from the two individuals and use it as a probability to set the bit
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM3 implements InterfaceCrossover, java.io.Serializable {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM3(){
|
||||
|
||||
}
|
||||
|
||||
public CM3(CM3 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM3(this);
|
||||
}
|
||||
|
||||
private int convertBoolean(boolean b){
|
||||
if(b){
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private double weight(double valX, boolean xi, double valY, boolean yi){
|
||||
double result = valX*convertBoolean(xi)+valY*convertBoolean(yi);
|
||||
result = result / (valX + valY);
|
||||
return result;
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getEAIndividual(0)).getBinaryData();
|
||||
for(int j=0; j<data.size(); j++){
|
||||
double w = weight(indy1.getFitness(0), data.get(j), partners.getEAIndividual(0).getFitness(0), data2.get(j));
|
||||
if(RNG.flipCoin(w)){
|
||||
data.set(j, true);
|
||||
}else{
|
||||
data.set(j, false);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0] = indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 3";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "Weight driven crossover method";
|
||||
}
|
||||
|
||||
}
|
91
src/eva2/server/go/operators/crossover/CM4.java
Normal file
91
src/eva2/server/go/operators/crossover/CM4.java
Normal file
@ -0,0 +1,91 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* This crossover-Method performs an \"intersection\" of the selected Individuals and then tries to improve it through score (like in CM3)
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM4 implements InterfaceCrossover, java.io.Serializable {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM4(){
|
||||
|
||||
}
|
||||
|
||||
public CM4(CM4 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM4(this);
|
||||
}
|
||||
|
||||
private int convertBoolean(boolean b){
|
||||
if(b){
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private double weight(double valX, boolean xi, double valY, boolean yi){
|
||||
double result = valX*convertBoolean(xi)+valY*convertBoolean(yi);
|
||||
result = result / (valX + valY);
|
||||
return result;
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getEAIndividual(0)).getBinaryData();
|
||||
for(int i=0; i<data.size(); i++){
|
||||
boolean setBit = data.get(i);
|
||||
setBit = setBit && data2.get(i);
|
||||
double val = partners.getEAIndividual(0).getFitness(0);
|
||||
double w = weight(indy1.getFitness(0), data.get(i), val, setBit);
|
||||
data.set(i, setBit);
|
||||
if(!setBit && RNG.flipCoin(w)){
|
||||
data.set(i, true);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0] = indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 4";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "Intersection with weight driven improvement";
|
||||
}
|
||||
|
||||
}
|
74
src/eva2/server/go/operators/crossover/CM5.java
Normal file
74
src/eva2/server/go/operators/crossover/CM5.java
Normal file
@ -0,0 +1,74 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* This crossover-Method performs an \"intersection\" of the selected Individuals and then tries to improve it by randomly setting Bits to 1
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM5 implements InterfaceCrossover, java.io.Serializable {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM5(){
|
||||
|
||||
}
|
||||
|
||||
public CM5(CM5 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM5(this);
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getEAIndividual(0)).getBinaryData();
|
||||
for(int i=0; i<data.size(); i++){
|
||||
boolean setBit = data2.get(i);
|
||||
data.set(i, setBit);
|
||||
if(!setBit && RNG.flipCoin(0.5)){
|
||||
data.set(i, true);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0] = indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return this.getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 5";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "Intersection with random change";
|
||||
}
|
||||
|
||||
}
|
80
src/eva2/server/go/operators/crossover/CM6.java
Normal file
80
src/eva2/server/go/operators/crossover/CM6.java
Normal file
@ -0,0 +1,80 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.server.go.strategies.BinaryScatterSearch;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* Score driven Crossover-Method. It uses the same score as the BinaryScatterSearch.
|
||||
* Only the first individual of the given Population in the mate method is used. the rest is only for calculating the score
|
||||
* It only mates 2 Individuals, not more
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM6 implements InterfaceCrossover, java.io.Serializable {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
|
||||
public CM6(){
|
||||
|
||||
}
|
||||
|
||||
public CM6(CM6 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM6(this);
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getIndividual(0)).getBinaryData();
|
||||
for(int j=0; j<data2.size(); j++){
|
||||
if(data2.get(j)){
|
||||
data.set(j, true);
|
||||
}
|
||||
}
|
||||
partners.remove(0);
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(!(data.get(i) && RNG.flipCoin(Math.min(0.1+BinaryScatterSearch.score(i, partners),1)))){
|
||||
data.set(i, false);
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0]=indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 6";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "score driven crossover method";
|
||||
}
|
||||
|
||||
}
|
104
src/eva2/server/go/operators/crossover/CM7.java
Normal file
104
src/eva2/server/go/operators/crossover/CM7.java
Normal file
@ -0,0 +1,104 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
|
||||
/**
|
||||
* This crossover-Method tries to convert the first individual into the second. If a better Individual is found on the way, this individual is chosen.
|
||||
* If no better individual is found, one with the greatest distance from the both is chosen
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
*/
|
||||
public class CM7 implements InterfaceCrossover, java.io.Serializable, InterfaceEvaluatingCrossoverOperator {
|
||||
private InterfaceOptimizationProblem m_OptimizationProblem;
|
||||
private int evaluations = 0;
|
||||
|
||||
public CM7(){
|
||||
|
||||
}
|
||||
|
||||
public CM7(CM7 c){
|
||||
this.m_OptimizationProblem = c.m_OptimizationProblem;
|
||||
this.evaluations = c.evaluations;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new CM7(this);
|
||||
}
|
||||
|
||||
public AbstractEAIndividual[] mate(AbstractEAIndividual indy1,
|
||||
Population partners) {
|
||||
AbstractEAIndividual[] result = null;
|
||||
result = new AbstractEAIndividual[1];
|
||||
if(partners.size()>0);
|
||||
if(indy1 instanceof InterfaceDataTypeBinary && partners.getEAIndividual(0) instanceof InterfaceDataTypeBinary){
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy1).getBinaryData();
|
||||
BitSet dataSave = (BitSet) data.clone();
|
||||
BitSet data2 = ((InterfaceDataTypeBinary) partners.getEAIndividual(0)).getBinaryData();
|
||||
double f1 = indy1.getFitness(0);
|
||||
double f2 = partners.getEAIndividual(0).getFitness(0);
|
||||
double min = Math.min(f1, f2);
|
||||
int different = 0;
|
||||
boolean foundBetter = false;
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(data.get(i) != data2.get(i)){
|
||||
different++;
|
||||
data.flip(i);
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
this.m_OptimizationProblem.evaluate(indy1);
|
||||
this.evaluations++;
|
||||
if(indy1.getFitness(0) < min){
|
||||
foundBetter = true;
|
||||
i=data.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!foundBetter){
|
||||
for(int i=0; i<dataSave.size(); i++){
|
||||
if(dataSave.get(i) != data2.get(i) && different > 0){
|
||||
dataSave.flip(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy1).SetBinaryGenotype(data);
|
||||
}
|
||||
result[0] = indy1;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void init(AbstractEAIndividual individual,
|
||||
InterfaceOptimizationProblem opt) {
|
||||
this.m_OptimizationProblem = opt;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public int getEvaluations(){
|
||||
return this.evaluations;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* GUI
|
||||
*/
|
||||
|
||||
public String getName(){
|
||||
return "Combination Method 7";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
//TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
public void resetEvaluations() {
|
||||
this.evaluations = 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package eva2.server.go.operators.crossover;
|
||||
|
||||
|
||||
public interface InterfaceEvaluatingCrossoverOperator extends InterfaceCrossover {
|
||||
/**
|
||||
* Retrieve the number of evaluations performed during crossover.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getEvaluations();
|
||||
|
||||
public void resetEvaluations();
|
||||
}
|
522
src/eva2/server/go/strategies/BOA.java
Normal file
522
src/eva2/server/go/strategies/BOA.java
Normal file
@ -0,0 +1,522 @@
|
||||
package eva2.server.go.strategies;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import eva2.gui.BeanInspector;
|
||||
import eva2.gui.GenericObjectEditor;
|
||||
import eva2.server.go.InterfacePopulationChangedEventListener;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.GAIndividualBinaryData;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.individuals.InterfaceGAIndividual;
|
||||
import eva2.server.go.populations.InterfaceSolutionSet;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.populations.SolutionSet;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.BKnapsackProblem;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.Pair;
|
||||
import eva2.tools.math.BayNet;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* Basic implementation of the Bayesian Optimization Algorithm
|
||||
*
|
||||
* Martin Pelikan, David E. Goldberg and Erick Cantu-Paz: 'BOA: The Bayesian Optimization Algorithm'
|
||||
* the works by Martin Pelikan and David E. Goldberg.
|
||||
*
|
||||
* @author seitz
|
||||
*
|
||||
*/
|
||||
public class BOA implements InterfaceOptimizer, java.io.Serializable {
|
||||
|
||||
private static boolean TRACE = true;
|
||||
transient private InterfacePopulationChangedEventListener m_Listener = null;
|
||||
private String m_Identifier = "BOA";
|
||||
|
||||
private int probDim = 3;
|
||||
private int fitCrit = -1;
|
||||
private int PopSize = 50;
|
||||
private int numberOfParents = 3;
|
||||
private boolean replaceNetwork = true;
|
||||
private transient BayNet network = null;
|
||||
private Population population = new Population();
|
||||
private AbstractOptimizationProblem problem = new BKnapsackProblem();
|
||||
private AbstractEAIndividual template = null;
|
||||
private double learningSetRatio = 0.5;
|
||||
private double resampleRatio = 0.5;
|
||||
private double upperProbLimit = 0.9;
|
||||
private double lowerProbLimit = 0.1;
|
||||
|
||||
// private networkGenerationMethod netGenMethod = networkGenerationMethod.GREEDY;
|
||||
// public enum networkGenerationMethod { GREEDY, K2 };
|
||||
|
||||
public BOA(){
|
||||
|
||||
}
|
||||
|
||||
public BOA(int numberOfParents, int popSize, boolean replaceNetwork, double learningSetRatio, double resampleRatio){
|
||||
this.numberOfParents = numberOfParents;
|
||||
this.PopSize = popSize;
|
||||
this.replaceNetwork = replaceNetwork;
|
||||
this.learningSetRatio = learningSetRatio;
|
||||
this.resampleRatio = resampleRatio;
|
||||
}
|
||||
|
||||
public BOA(BOA b){
|
||||
this.m_Listener = b.m_Listener;
|
||||
this.m_Identifier = b.m_Identifier;
|
||||
this.probDim = b.probDim;
|
||||
this.fitCrit = b.fitCrit;
|
||||
this.PopSize = b.PopSize;
|
||||
this.numberOfParents = b.numberOfParents;
|
||||
this.replaceNetwork = b.replaceNetwork;
|
||||
this.network = (BayNet) b.network.clone();
|
||||
this.population = (Population) b.population.clone();
|
||||
this.problem = (AbstractOptimizationProblem) b.problem.clone();
|
||||
this.template = (AbstractEAIndividual) b.template.clone();
|
||||
this.learningSetRatio = b.learningSetRatio;
|
||||
this.resampleRatio = b.resampleRatio;
|
||||
this.upperProbLimit = b.upperProbLimit;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new BOA(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "Bayesian Optimization Algorithm";
|
||||
}
|
||||
|
||||
public static String globalInfo() {
|
||||
return "Basic implementation of the Bayesian Optimization Algorithm based on the works by Martin Pelikan and David E. Goldberg.";
|
||||
}
|
||||
|
||||
public void hideHideable() {
|
||||
GenericObjectEditor.setHideProperty(this.getClass(), "population", true);
|
||||
}
|
||||
|
||||
public void addPopulationChangedEventListener(
|
||||
InterfacePopulationChangedEventListener ea) {
|
||||
this.m_Listener = ea;
|
||||
}
|
||||
|
||||
public boolean removePopulationChangedEventListener(
|
||||
InterfacePopulationChangedEventListener ea) {
|
||||
if (m_Listener==ea) {
|
||||
m_Listener=null;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
private static BitSet getBinaryData(AbstractEAIndividual indy) {
|
||||
if (indy instanceof InterfaceGAIndividual) return ((InterfaceGAIndividual)indy).getBGenotype();
|
||||
else if (indy instanceof InterfaceDataTypeBinary) return ((InterfaceDataTypeBinary)indy).getBinaryData();
|
||||
else {
|
||||
throw new RuntimeException("Unable to get binary representation for " + indy.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* evaluate the given Individual and increments the counter. if the individual is null, only the counter is incremented
|
||||
* @param indy the individual you want to evaluate
|
||||
*/
|
||||
private void evaluate(AbstractEAIndividual indy){
|
||||
// evaluate the given individual if it is not null
|
||||
if(indy != null){
|
||||
this.problem.evaluate(indy);
|
||||
}
|
||||
// increment the number of evaluations
|
||||
this.population.incrFunctionCalls();
|
||||
}
|
||||
|
||||
/**
|
||||
* the default initialization
|
||||
*/
|
||||
private void defaultInit(){
|
||||
if (population==null) {
|
||||
this.population = new Population(this.PopSize);
|
||||
} else {
|
||||
this.population.setTargetPopSize(this.PopSize);
|
||||
}
|
||||
this.template = this.problem.getIndividualTemplate();
|
||||
if (!(template instanceof InterfaceDataTypeBinary)){
|
||||
System.err.println("Requiring binary data!");
|
||||
}else{
|
||||
Object dim = BeanInspector.callIfAvailable(problem, "getProblemDimension", null);
|
||||
if (dim==null) System.err.println("Couldnt get problem dimension!");
|
||||
probDim = (Integer)dim;
|
||||
((InterfaceDataTypeBinary)this.template).SetBinaryGenotype(new BitSet(probDim));
|
||||
}
|
||||
this.network = new BayNet(this.probDim, upperProbLimit, lowerProbLimit);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
defaultInit();
|
||||
this.problem.initPopulation(this.population);
|
||||
this.evaluatePopulation(this.population);
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
|
||||
private void evaluatePopulation(Population pop) {
|
||||
for (int i=0; i<pop.size(); i++) {
|
||||
evaluate(pop.getEAIndividual(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void initByPopulation(Population pop, boolean reset) {
|
||||
if(reset){
|
||||
init();
|
||||
}else{
|
||||
defaultInit();
|
||||
this.population = (pop);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateGreedy(Population pop){
|
||||
this.network = new BayNet(this.probDim, upperProbLimit, lowerProbLimit);
|
||||
// BayNet net = (BayNet) this.network.clone();
|
||||
// BayNet best = (BayNet) this.network.clone();
|
||||
|
||||
boolean improvement = true;
|
||||
double score = this.network.bayesianDirichletMetric(pop);
|
||||
score = 0;
|
||||
// Date time = new Date();
|
||||
// System.out.println("Start: "+time.getHours()+":"+time.getMinutes()+":"+time.getSeconds());
|
||||
List<Pair<Integer, Integer>> bestNetworks = new LinkedList<Pair<Integer, Integer>>();
|
||||
while(improvement){
|
||||
improvement = false;
|
||||
// System.out.println("score:"+score);
|
||||
for(int i=0; i<this.probDim; i++){
|
||||
for(int j=0; j<this.probDim; j++){
|
||||
if((!this.network.hasEdge(i, j)) && (i != j) && (this.network.getNode(j).getNumberOfParents() < this.numberOfParents)){
|
||||
BayNet tmp = this.network;
|
||||
tmp.addEdge(i, j);
|
||||
if(tmp.isACyclic(i, j)){
|
||||
double tmpScore = tmp.bayesianDirichletMetric(pop);
|
||||
if(tmpScore >= score){
|
||||
if(tmpScore == score){
|
||||
bestNetworks.add(new Pair<Integer, Integer>(i, j));
|
||||
}else{
|
||||
bestNetworks.clear();
|
||||
bestNetworks.add(new Pair<Integer, Integer>(i, j));
|
||||
score = tmpScore;
|
||||
improvement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.network.removeEdge(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bestNetworks.size() > 0){
|
||||
int val = RNG.randomInt(bestNetworks.size());
|
||||
Pair<Integer, Integer> pair = bestNetworks.get(val);
|
||||
this.network.addEdge(pair.getHead(), pair.getTail());
|
||||
}
|
||||
bestNetworks.clear();
|
||||
}
|
||||
// time = new Date();
|
||||
// System.out.println("Stop: "+time.getHours()+":"+time.getMinutes()+":"+time.getSeconds());
|
||||
}
|
||||
|
||||
private boolean expandGreedy(Population pop){
|
||||
BayNet net = (BayNet) this.network.clone();
|
||||
BayNet best = (BayNet) this.network.clone();
|
||||
boolean improv = false;
|
||||
boolean improvement = true;
|
||||
double score = net.bayesianDirichletMetric(pop);
|
||||
Date time = new Date();
|
||||
// System.out.println("Start: "+time.getHours()+":"+time.getMinutes()+":"+time.getSeconds());
|
||||
while(improvement){
|
||||
improvement = false;
|
||||
// System.out.println("score:"+score);
|
||||
for(int i=0; i<this.probDim; i++){
|
||||
for(int j=0; j<this.probDim; j++){
|
||||
if((!net.hasEdge(i, j)) && (i != j) && (net.getNode(j).getNumberOfParents() < this.numberOfParents)){
|
||||
BayNet tmp = (BayNet) net.clone();
|
||||
tmp.addEdge(i, j);
|
||||
if(tmp.isACyclic()){
|
||||
double tmpScore = tmp.bayesianDirichletMetric(pop);
|
||||
if(tmpScore > score){
|
||||
best = (BayNet) tmp.clone();
|
||||
score = tmpScore;
|
||||
improvement = true;
|
||||
improv = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
net = (BayNet) best.clone();;
|
||||
}
|
||||
time = new Date();
|
||||
// System.out.println("Stop: "+time.getHours()+":"+time.getMinutes()+":"+time.getSeconds());
|
||||
this.network = (BayNet) best.clone();
|
||||
return improv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a Bayesian network with the individuals of the population as a reference Point
|
||||
* @param pop the individuals the network is based on
|
||||
*/
|
||||
private void constructNetwork(Population pop){
|
||||
if(this.replaceNetwork){
|
||||
generateGreedy(pop);
|
||||
}else{
|
||||
boolean improve = expandGreedy(pop);
|
||||
if(!improve){
|
||||
generateGreedy(pop);
|
||||
}
|
||||
}
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* generate new individuals based on the bayesian network
|
||||
* @return the new individuals
|
||||
*/
|
||||
private Population generateNewIndys(int sampleSetSize){
|
||||
Population pop = new Population(sampleSetSize);
|
||||
if (TRACE) System.out.println("Resampling " + sampleSetSize + " indies...");
|
||||
while(pop.size() < sampleSetSize){
|
||||
AbstractEAIndividual indy = (AbstractEAIndividual) this.template.clone();
|
||||
BitSet data = this.network.sample(getBinaryData(indy));
|
||||
((InterfaceDataTypeBinary) indy).SetBinaryGenotype(data);
|
||||
evaluate(indy);
|
||||
pop.add(indy);
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a plausible number of individuals to be resampled per iteration.
|
||||
* @return
|
||||
*/
|
||||
private int calcResampleSetSize() {
|
||||
int result = (int)Math.min(PopSize, Math.max(1.0, ((double)PopSize)*resampleRatio));
|
||||
// System.out.println(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate a plausible number of individuals from which the BayNet is learned.
|
||||
* In principle this can be independent of the resampling set size.
|
||||
* @return
|
||||
*/
|
||||
private int calcLearningSetSize() {
|
||||
return (int)Math.min(PopSize, Math.max(1.0, ((double)PopSize)*learningSetRatio));
|
||||
}
|
||||
|
||||
public void remove(Population pop){
|
||||
for(Object indy: pop){
|
||||
this.population.remove(indy);
|
||||
}
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
Population best = this.population.getBestNIndividuals(calcLearningSetSize(), this.fitCrit);
|
||||
constructNetwork(best);
|
||||
Population newlyGenerated = generateNewIndys(calcResampleSetSize());
|
||||
Population toRemove = this.population.getWorstNIndividuals(calcResampleSetSize(), this.fitCrit);
|
||||
remove(toRemove);
|
||||
this.population.addAll(newlyGenerated);
|
||||
// print();
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
|
||||
|
||||
/** Something has changed
|
||||
*/
|
||||
protected void firePropertyChangedEvent (String name) {
|
||||
if (this.m_Listener != null) this.m_Listener.registerPopulationStateChanged(this, name);
|
||||
}
|
||||
|
||||
public Population getPopulation() {
|
||||
return this.population;
|
||||
}
|
||||
|
||||
public void setPopulation(Population pop) {
|
||||
this.population = pop;
|
||||
}
|
||||
|
||||
public InterfaceSolutionSet getAllSolutions() {
|
||||
return new SolutionSet(this.population);
|
||||
}
|
||||
|
||||
public void SetIdentifier(String name) {
|
||||
this.m_Identifier = name;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return this.m_Identifier;
|
||||
}
|
||||
|
||||
public void SetProblem(InterfaceOptimizationProblem problem) {
|
||||
this.problem = (AbstractOptimizationProblem) problem;
|
||||
}
|
||||
|
||||
public InterfaceOptimizationProblem getProblem() {
|
||||
return this.problem;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return "Bayesian Network";
|
||||
}
|
||||
|
||||
public void freeWilly() {
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------
|
||||
//-------------GUI---------------
|
||||
//-------------------------------
|
||||
|
||||
public int getNumberOfParents(){
|
||||
return this.numberOfParents;
|
||||
}
|
||||
|
||||
public void setNumberOfParents(int i){
|
||||
this.numberOfParents = i;
|
||||
}
|
||||
|
||||
public String numberOfParentsTipText(){
|
||||
return "The maximum number of parents a node in the Bayesian Network can have";
|
||||
}
|
||||
|
||||
public boolean getReplaceNetwork(){
|
||||
return this.replaceNetwork;
|
||||
}
|
||||
|
||||
public void setReplaceNetwork(boolean b){
|
||||
this.replaceNetwork = b;
|
||||
}
|
||||
|
||||
public String replaceNetworkTipText(){
|
||||
return "if set, the network will be completely replaced. If not, it will be tried to improve the last network, if that is not possible, it will be replaced";
|
||||
}
|
||||
|
||||
// public networkGenerationMethod getNetworkGenerationMethod(){
|
||||
// return this.netGenMethod;
|
||||
// }
|
||||
//
|
||||
// public void setNetworkGenerationMethod(networkGenerationMethod n){
|
||||
// this.netGenMethod = n;
|
||||
// }
|
||||
//
|
||||
// public String networkGenerationMethodTipText(){
|
||||
// return "The Method with which the Bayesian Network will be gererated";
|
||||
// }
|
||||
|
||||
public void print(){
|
||||
this.network.print();
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
Population pop = new Population();
|
||||
GAIndividualBinaryData indy1 = new GAIndividualBinaryData();
|
||||
indy1.setBinaryDataLength(3);
|
||||
GAIndividualBinaryData indy2 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy3 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy4 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy5 = (GAIndividualBinaryData) indy1.clone();
|
||||
BitSet data1 = indy1.getBinaryData();
|
||||
BitSet data2 = indy2.getBinaryData();
|
||||
BitSet data3 = indy3.getBinaryData();
|
||||
BitSet data4 = indy4.getBinaryData();
|
||||
BitSet data5 = indy5.getBinaryData();
|
||||
data1.set(0, true);
|
||||
data1.set(1, true);
|
||||
data1.set(2, false);
|
||||
data2.set(0, true);
|
||||
data2.set(1, true);
|
||||
data2.set(2, true);
|
||||
data3.set(0, false);
|
||||
data3.set(1, true);
|
||||
data3.set(2, false);
|
||||
data4.set(0, false);
|
||||
data4.set(1, true);
|
||||
data4.set(2, true);
|
||||
data5.set(0, true);
|
||||
data5.set(1, false);
|
||||
data5.set(2, false);
|
||||
indy1.SetBinaryGenotype(data1);
|
||||
indy2.SetBinaryGenotype(data2);
|
||||
indy3.SetBinaryGenotype(data3);
|
||||
indy4.SetBinaryGenotype(data4);
|
||||
indy5.SetBinaryGenotype(data5);
|
||||
pop.add(indy1);
|
||||
pop.add(indy2);
|
||||
AbstractEAIndividual ind = (AbstractEAIndividual) indy2.clone();
|
||||
pop.add(ind);
|
||||
// pop.add(indy3);
|
||||
// pop.add(indy4);
|
||||
// pop.add(indy5);
|
||||
BOA b = new BOA();
|
||||
b.generateGreedy(pop);
|
||||
System.out.println(pop.getStringRepresentation());
|
||||
b.print();
|
||||
}
|
||||
|
||||
public int getPopulationSize() {
|
||||
return PopSize;
|
||||
}
|
||||
public void setPopulationSize(int popSize) {
|
||||
PopSize = popSize;
|
||||
}
|
||||
public String populationSizeTipText() {
|
||||
return "Define the pool size used by BOA";
|
||||
}
|
||||
|
||||
public double getResamplingRatio() {
|
||||
return resampleRatio;
|
||||
}
|
||||
public void setResamplingRatio(double resampleRat) {
|
||||
this.resampleRatio = resampleRat;
|
||||
}
|
||||
public String resamplingRatioTipText() {
|
||||
return "Ratio of individuals to be resampled from the Bayesian network per iteration";
|
||||
}
|
||||
|
||||
public double getLearningRatio() {
|
||||
return learningSetRatio;
|
||||
}
|
||||
public void setLearningRatio(double rat) {
|
||||
this.learningSetRatio = rat;
|
||||
}
|
||||
public String learningRatioTipText() {
|
||||
return "Ratio of individuals to be used to learn the Bayesian network";
|
||||
}
|
||||
|
||||
public double getProbLimitHigh() {
|
||||
return upperProbLimit;
|
||||
}
|
||||
|
||||
public void setProbLimitHigh(double upperProbLimit) {
|
||||
this.upperProbLimit = upperProbLimit;
|
||||
}
|
||||
|
||||
public String probLimitHighTipText(){
|
||||
return "the upper limit of the probability to set one Bit to 1";
|
||||
}
|
||||
|
||||
public double getProbLimitLow() {
|
||||
return lowerProbLimit;
|
||||
}
|
||||
|
||||
public void setProbLimitLow(double lowerProbLimit) {
|
||||
this.lowerProbLimit = lowerProbLimit;
|
||||
}
|
||||
|
||||
public String probLimitLowTipText(){
|
||||
return "the lower limit of the probability to set one Bit to 1";
|
||||
}
|
||||
|
||||
public String[] customPropertyOrder() {
|
||||
return new String[] {"learningRatio", "resamplingRatio"};
|
||||
}
|
||||
|
||||
}
|
844
src/eva2/server/go/strategies/BinaryScatterSearch.java
Normal file
844
src/eva2/server/go/strategies/BinaryScatterSearch.java
Normal file
@ -0,0 +1,844 @@
|
||||
package eva2.server.go.strategies;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
|
||||
import eva2.gui.BeanInspector;
|
||||
import eva2.server.go.InterfacePopulationChangedEventListener;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.individuals.InterfaceGAIndividual;
|
||||
import eva2.server.go.operators.crossover.AdaptiveCrossoverEAMixer;
|
||||
import eva2.server.go.operators.crossover.CM1;
|
||||
import eva2.server.go.operators.crossover.CM2;
|
||||
import eva2.server.go.operators.crossover.CM3;
|
||||
import eva2.server.go.operators.crossover.CM4;
|
||||
import eva2.server.go.operators.crossover.CM5;
|
||||
import eva2.server.go.operators.crossover.CM6;
|
||||
import eva2.server.go.operators.crossover.CM7;
|
||||
import eva2.server.go.operators.distancemetric.GenotypeMetricBitSet;
|
||||
import eva2.server.go.populations.InterfaceSolutionSet;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.server.go.populations.SolutionSet;
|
||||
import eva2.server.go.problems.AbstractOptimizationProblem;
|
||||
import eva2.server.go.problems.B1Problem;
|
||||
import eva2.server.go.problems.InterfaceOptimizationProblem;
|
||||
import eva2.tools.Pair;
|
||||
import eva2.tools.math.RNG;
|
||||
|
||||
/**
|
||||
* A BinaryScatterSearch implementation taken mainly from [i].
|
||||
*
|
||||
* @author Alex
|
||||
*
|
||||
* F. Gortazar, A. Duarte, M. Laguna and R. Marti: Black Box Scatter Search for General Classes of Binary Optimization Problems
|
||||
* Computers and Operations research, vol. 37, no. 11, pp. 1977-1986 (2010)
|
||||
*/
|
||||
public class BinaryScatterSearch implements InterfaceOptimizer, java.io.Serializable, InterfacePopulationChangedEventListener {
|
||||
private static boolean TRACE = false;
|
||||
transient private InterfacePopulationChangedEventListener m_Listener = null;
|
||||
private String m_Identifier = "BinaryScatterSearch";
|
||||
|
||||
|
||||
private int MaxImpIter = 5;
|
||||
private int poolSize = 100;
|
||||
private int refSetSize = 10;
|
||||
private int fitCrit = -1;
|
||||
private int probDim = -1;
|
||||
private int generationCycle = 500;
|
||||
private double th1 = 0.5;
|
||||
private double th2 = 0.5;
|
||||
private double g1 = 1.0/3.0;
|
||||
private double g2 = 1.0/3.0;
|
||||
private boolean firstTime = true;
|
||||
private AbstractEAIndividual template = null;
|
||||
private AbstractOptimizationProblem problem = new B1Problem();
|
||||
private Population pool = new Population();
|
||||
private Population refSet = new Population(10);
|
||||
private AdaptiveCrossoverEAMixer cross = new AdaptiveCrossoverEAMixer(new CM1(), new CM2(), new CM3(), new CM4(), new CM5(), new CM6(), new CM7());
|
||||
|
||||
/**
|
||||
* Create a new BinaryScatterSearch with default values
|
||||
*/
|
||||
public BinaryScatterSearch(){
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BinaryScatterSearch with the same parameters as the given BinaryScatterSearch
|
||||
* @param b
|
||||
*/
|
||||
public BinaryScatterSearch(BinaryScatterSearch b){
|
||||
this.m_Listener = b.m_Listener;
|
||||
this.m_Identifier = b.m_Identifier;
|
||||
this.MaxImpIter = b.MaxImpIter;
|
||||
this.poolSize = b.poolSize;
|
||||
this.refSetSize = b.refSetSize;
|
||||
this.fitCrit = b.fitCrit;
|
||||
this.probDim = b.probDim;
|
||||
this.generationCycle= b.generationCycle;
|
||||
this.th1 = b.th1;
|
||||
this.th2 = b.th2;
|
||||
this.g1 = b.g1;
|
||||
this.g2 = b.g2;
|
||||
this.firstTime = b.firstTime;
|
||||
this.template = b.template;
|
||||
this.problem = b.problem;
|
||||
this.pool = b.pool;
|
||||
this.refSet = b.refSet;
|
||||
this.cross = b.cross;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BinaryScatterSearch with the given Parameters
|
||||
* @param refSetS the refSetSize
|
||||
* @param poolS the poolSize
|
||||
* @param lowerThreshold the lower Boundary for the local Search
|
||||
* @param upperThreshold the upper Boundary for the local Search
|
||||
* @param perCentFirstIndGenerator how many individuals (in prospect of the poolSize) are generated through the first Generator
|
||||
* @param perCentSecondIndGenerator how many individuals (in prospect of the poolSize) are generated through the second Generator
|
||||
* @param prob the Problem
|
||||
*/
|
||||
public BinaryScatterSearch(
|
||||
int refSetS, int poolS, double lowerThreshold, double upperThreshold,
|
||||
double perCentFirstIndGenerator, double perCentSecondIndGenerator, AbstractOptimizationProblem prob) {
|
||||
this.refSetSize = refSetS;
|
||||
this.poolSize= poolS;
|
||||
this.th1 = lowerThreshold;
|
||||
this.th2 = upperThreshold;
|
||||
this.g1 = perCentFirstIndGenerator;
|
||||
this.g2 = perCentSecondIndGenerator;
|
||||
this.problem = prob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BinaryScatterSearch with the given Parameters
|
||||
* @param refSetS the refSetSize
|
||||
* @param poolS the poolSize
|
||||
* @param lowerThreshold the lower Boundary for the local Search
|
||||
* @param upperThreshold the upper Boundary for the local Search
|
||||
* @param perCentFirstIndGenerator how many individuals (in prospect of the poolSize) are generated through the first Generator
|
||||
* @param perCentSecondIndGenerator how many individuals (in prospect of the poolSize) are generated through the second Generator
|
||||
* @param prob the Problem
|
||||
* @param cross the Crossover-Operators
|
||||
*/
|
||||
public BinaryScatterSearch(
|
||||
int refSetS, int poolS, double lowerThreshold, double upperThreshold,
|
||||
double perCentFirstIndGenerator, double perCentSecondIndGenerator,
|
||||
AbstractOptimizationProblem prob, AdaptiveCrossoverEAMixer cross) {
|
||||
this.refSetSize = refSetS;
|
||||
this.poolSize= poolS;
|
||||
this.th1 = lowerThreshold;
|
||||
this.th2 = upperThreshold;
|
||||
this.g1 = perCentFirstIndGenerator;
|
||||
this.g2 = perCentSecondIndGenerator;
|
||||
this.problem = prob;
|
||||
this.cross = cross;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a copy of the current BinaryScatterSearch
|
||||
*/
|
||||
public Object clone(){
|
||||
return new BinaryScatterSearch(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "BSS";
|
||||
}
|
||||
|
||||
public void addPopulationChangedEventListener(
|
||||
InterfacePopulationChangedEventListener ea) {
|
||||
this.m_Listener = ea;
|
||||
}
|
||||
|
||||
public boolean removePopulationChangedEventListener(
|
||||
InterfacePopulationChangedEventListener ea) {
|
||||
if (m_Listener==ea) {
|
||||
m_Listener=null;
|
||||
return true;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* evaluate the given Individual and increments the counter. if the individual is null, only the counter is incremented
|
||||
* @param indy the individual you want to evaluate
|
||||
*/
|
||||
private void evaluate(AbstractEAIndividual indy){
|
||||
// evaluate the given individual if it is not null
|
||||
if(indy != null){
|
||||
this.problem.evaluate(indy);
|
||||
}
|
||||
// increment the number of evaluations
|
||||
this.refSet.incrFunctionCalls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default initialization
|
||||
*/
|
||||
private void defaultInit(){
|
||||
this.refSet = new Population();
|
||||
this.template = this.problem.getIndividualTemplate();
|
||||
if (!(template instanceof InterfaceDataTypeBinary)){
|
||||
System.err.println("Requiring binary data!");
|
||||
}else{
|
||||
Object dim = BeanInspector.callIfAvailable(problem, "getProblemDimension", null);
|
||||
if (dim==null) System.err.println("Couldnt get problem dimension!");
|
||||
probDim = (Integer)dim;
|
||||
((InterfaceDataTypeBinary)this.template).SetBinaryGenotype(new BitSet(probDim));
|
||||
}
|
||||
this.firstTime = true;
|
||||
this.cross.init(this.template, problem, refSet, Double.MAX_VALUE);
|
||||
refSet.addPopulationChangedEventListener(this);
|
||||
this.refSet.setNotifyEvalInterval(this.generationCycle);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
defaultInit();
|
||||
initRefSet(diversify());
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
|
||||
public void initByPopulation(Population pop, boolean reset) {
|
||||
defaultInit();
|
||||
initRefSet(diversify(pop));
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a new diversified Population
|
||||
*/
|
||||
private Population diversify(){
|
||||
return diversify(new Population());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pop the initial Population
|
||||
* @return a diversified Population with all the Individuals in the initial Population
|
||||
*/
|
||||
private Population diversify(Population pop){
|
||||
pop = generateG1(pop);
|
||||
pop = generateG2(pop);
|
||||
pop = generateG3(pop);
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a new Population with diverse Individuals starting with 000...000, then 010101...01, 101010...10, 001001001...001, 110110110...110 and so on
|
||||
* @param pop the initial Population
|
||||
* @return the new Population
|
||||
*/
|
||||
private Population generateG1(Population pop){
|
||||
boolean method1 = true;
|
||||
int i=1;
|
||||
while(pop.size() < ((double) this.poolSize) * this.g1){
|
||||
AbstractEAIndividual indy = (AbstractEAIndividual) this.template.clone();
|
||||
BitSet data = getBinaryData(indy);
|
||||
if(method1){
|
||||
method1 = !method1;
|
||||
data.set(0, data.size(), true);
|
||||
for(int j=0; j<data.size(); j=j+i){
|
||||
data.flip(j);
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy).SetBinaryGenotype(data);
|
||||
if(i==1){
|
||||
i++;
|
||||
method1 = !method1;
|
||||
}
|
||||
}else{
|
||||
method1 = !method1;
|
||||
if(i!=1){
|
||||
data.set(0, data.size(), false);
|
||||
for(int j=0; j<data.size(); j=j+i){
|
||||
data.flip(j);
|
||||
}
|
||||
((InterfaceDataTypeBinary) indy).SetBinaryGenotype(data);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
pop.add(indy);
|
||||
evaluate((AbstractEAIndividual) indy);
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new Individuals that have the individuals of the given Population as a base
|
||||
* @param pop the population
|
||||
* @return the new Population
|
||||
*/
|
||||
private Population generateG2(Population pop){
|
||||
while(pop.size() < ((double) this.poolSize) * (this.g1 + this.g2)){
|
||||
AbstractEAIndividual indy = (AbstractEAIndividual)template.clone();
|
||||
InterfaceDataTypeBinary dblIndy = (InterfaceDataTypeBinary) indy;
|
||||
BitSet data = dblIndy.getBinaryData();
|
||||
data.set(0, data.size(), false);
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(RNG.flipCoin(Math.min(0.1+score(i, pop),1))){
|
||||
data.set(i, true);
|
||||
}
|
||||
}
|
||||
dblIndy.SetBinaryGenotype(data);
|
||||
if(!contains(dblIndy, pop)){
|
||||
pop.add(dblIndy);
|
||||
evaluate(indy);
|
||||
}
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new Individuals that have the individuals of the given Population as a base
|
||||
* @param pop the population
|
||||
* @return the new Population
|
||||
*/
|
||||
private Population generateG3(Population pop){
|
||||
while(pop.size() <= this.poolSize){
|
||||
AbstractEAIndividual indy = (AbstractEAIndividual)template.clone();
|
||||
InterfaceDataTypeBinary dblIndy = (InterfaceDataTypeBinary)indy;
|
||||
BitSet data = dblIndy.getBinaryData();
|
||||
data.set(0, data.size(), true);
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(RNG.flipCoin(Math.max(0, 1-score(i, pop)))){//???
|
||||
data.set(i, false);
|
||||
}
|
||||
}
|
||||
dblIndy.SetBinaryGenotype(data);
|
||||
if(!contains(dblIndy, pop)){
|
||||
pop.add(dblIndy);
|
||||
evaluate(indy);
|
||||
}
|
||||
}
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the number of individuals in the given Population that have a 1 at the i-th position
|
||||
* @param i the position
|
||||
* @param pop the population
|
||||
* @return The number of individuals that have a '1' on the i-th position
|
||||
*/
|
||||
private static double calculateNumberOFPI1(int i, Population pop){
|
||||
int result = 0;
|
||||
for(int j=0; j<pop.size(); j++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(j);
|
||||
BitSet binData = getBinaryData(indy);
|
||||
if(binData.get(i)){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the number of individuals in the given Population that have a 0 at the i-th position
|
||||
* @param i the position
|
||||
* @param pop the population
|
||||
* @return The number of individuals that have a '0' on the i-th position
|
||||
*/
|
||||
private static double calculateNumberOFPI0(int i, Population pop){
|
||||
int result = 0;
|
||||
for(int j=0; j<pop.size(); j++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(j);
|
||||
BitSet binData = getBinaryData(indy);
|
||||
if(!binData.get(i)){
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BitSet getBinaryData(AbstractEAIndividual indy) {
|
||||
if (indy instanceof InterfaceGAIndividual) return ((InterfaceGAIndividual)indy).getBGenotype();
|
||||
else if (indy instanceof InterfaceDataTypeBinary) return ((InterfaceDataTypeBinary)indy).getBinaryData();
|
||||
else {
|
||||
throw new RuntimeException("Unable to get binary representation for " + indy.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the sum of all the FitnessValues of the individuals that have a '0' at the i-th position
|
||||
* @param i the position
|
||||
* @param pop the population
|
||||
* @return the sum
|
||||
*/
|
||||
private static double calculateSumPI0(int i, Population pop){
|
||||
double result = 0;
|
||||
for(int j=0; j<pop.size(); j++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(j);
|
||||
BitSet binData = getBinaryData(indy);
|
||||
if(binData.get(i)){
|
||||
result += indy.getFitness(0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the sum of all the FitnessValues of the individuals that have a '0' at the i-th position
|
||||
* @param i the position
|
||||
* @param pop the population
|
||||
* @return the sum
|
||||
*/
|
||||
private static double calculateSumPI1(int i, Population pop){
|
||||
double result = 0;
|
||||
for(int j=0; j<pop.size(); j++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(j);
|
||||
BitSet binData = getBinaryData(indy);
|
||||
if(binData.get(i)){
|
||||
result += indy.getFitness(0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates a score that gives a reference Point if the Bit on the i-th position is right.
|
||||
* If the bit is set to '1' and you get a high score then the Bit is probably set correct.
|
||||
* If the bit is set to '0' and you get a low score then the Bit is probably set correct.
|
||||
* @param i the position
|
||||
* @param pop the population
|
||||
* @return the score
|
||||
*/
|
||||
public static double score(int i, Population pop){
|
||||
double sumPI1 = calculateSumPI1(i, pop);
|
||||
double sumPI0 = calculateSumPI0(i, pop);
|
||||
double numberOfPI1 = calculateNumberOFPI1(i, pop);
|
||||
double numberOfPI0 = calculateNumberOFPI0(i, pop);
|
||||
double v= (sumPI1/numberOfPI1)/((sumPI1/numberOfPI1)+(sumPI0/numberOfPI0));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* calculate the first RefSet with the given Population as a reference Point
|
||||
* @param pop the generated Pool
|
||||
*/
|
||||
private void initRefSet(Population pop){
|
||||
this.problem.evaluatePopulationStart(this.refSet);
|
||||
this.pool = pop;
|
||||
refSetUpdate(true);
|
||||
Population best = this.refSet.getBestNIndividuals(this.refSetSize/2, fitCrit);
|
||||
for(int i=0; i<best.size(); i++){
|
||||
//improve(best.getEAIndividual(i));
|
||||
AbstractEAIndividual indy = best.getEAIndividual(i);
|
||||
AbstractEAIndividual x = improve((AbstractEAIndividual)indy.clone());
|
||||
if(x.getFitness(0)<indy.getFitness(0) && !contains((InterfaceDataTypeBinary)x, this.refSet)){
|
||||
this.refSet.remove(indy);
|
||||
this.refSet.add(x);
|
||||
}
|
||||
}
|
||||
this.problem.evaluatePopulationEnd(this.refSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the reference Set
|
||||
* @param replaceWorstHalf replaces the worst half of the RefSet if set
|
||||
* @return has the Population changed
|
||||
*/
|
||||
private boolean refSetUpdate(boolean replaceWorstHalf){
|
||||
boolean refSetChanged = false;
|
||||
Population rest = (Population) this.pool.clone();
|
||||
if(this.firstTime){
|
||||
Population tmp = this.pool.getBestNIndividuals(this.pool.size(), this.fitCrit);
|
||||
int i=0;
|
||||
while(this.refSet.size() < this.refSetSize){
|
||||
this.refSet.add(tmp.get(i));
|
||||
i++;
|
||||
}
|
||||
rest = this.pool.getWorstNIndividuals(this.poolSize-i, this.fitCrit);
|
||||
refSetChanged = true;
|
||||
}
|
||||
if(replaceWorstHalf){
|
||||
refSetChanged = true;
|
||||
// delete the worst half of refSet
|
||||
this.refSet.removeMembers(this.refSet.getWorstNIndividuals(this.refSet.size()-this.refSetSize/2, this.fitCrit), false);
|
||||
while(this.refSet.size()<this.refSetSize){
|
||||
ArrayList<Pair<Integer,Double>> list = new ArrayList<Pair<Integer,Double>>();
|
||||
for(int i=0; i< this.refSet.size(); i++){
|
||||
AbstractEAIndividual indy = this.refSet.getEAIndividual(i);
|
||||
list.add(Population.getClosestFarthestIndy(indy, rest, new GenotypeMetricBitSet(), false));
|
||||
}
|
||||
Pair<Integer,Double> pair = list.get(0);
|
||||
for(Pair<Integer,Double> p: list){
|
||||
if(p.getTail()<pair.getTail()){
|
||||
pair=p;
|
||||
}
|
||||
}
|
||||
this.refSet.add(rest.getEAIndividual(pair.getHead()));
|
||||
rest.remove(pair.getHead());
|
||||
}
|
||||
}else{
|
||||
Population best = this.pool.getBestNIndividuals(this.refSetSize, this.fitCrit);
|
||||
while(best.size()>0 && best.getBestEAIndividual().getFitness(0)<this.refSet.getWorstEAIndividual().getFitness(0)){
|
||||
if(!contains((InterfaceDataTypeBinary)best.getBestIndividual(), this.refSet)){
|
||||
refSetChanged = true;
|
||||
this.refSet.remove(this.refSet.getWorstEAIndividual());
|
||||
this.refSet.add(best.getBestIndividual());
|
||||
}
|
||||
best.remove(best.getBestEAIndividual());
|
||||
}
|
||||
}
|
||||
this.firstTime = false;
|
||||
return refSetChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the given List according to the score of the given values
|
||||
* @param list the initial List
|
||||
* @return the ordered List
|
||||
*/
|
||||
private ArrayList<Integer> order(ArrayList<Integer> list){
|
||||
ArrayList<Integer> result = new ArrayList<Integer>();
|
||||
for(Integer s: list){
|
||||
boolean done = false;
|
||||
if(result.isEmpty()){
|
||||
result.add(s);
|
||||
}else{
|
||||
for(int i=0; i<result.size(); i++){
|
||||
if(score(s, this.refSet)>score(result.get(i), this.refSet)&&!done){
|
||||
result.add(i,s);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
if(!done){
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a local search
|
||||
* @param indy the individual that will be improved
|
||||
* @return the new improved individual
|
||||
*/
|
||||
private AbstractEAIndividual improve(AbstractEAIndividual indy){
|
||||
AbstractEAIndividual tmpIndy = (AbstractEAIndividual) indy.clone();
|
||||
BitSet data = ((InterfaceDataTypeBinary)tmpIndy).getBinaryData();
|
||||
ArrayList<Integer> cl = new ArrayList<Integer>();
|
||||
int localIter = 0;
|
||||
for(int i=0; i<data.size(); i++){
|
||||
if(data.get(i)){
|
||||
if(score(i, this.refSet)<=this.th2){
|
||||
cl.add(i);
|
||||
}
|
||||
}else{
|
||||
if(score(i, this.refSet)>=this.th1){
|
||||
cl.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
cl = order(cl);
|
||||
boolean improvement = true;
|
||||
while(improvement && localIter < this.MaxImpIter){
|
||||
improvement = false;
|
||||
for(int i:cl){
|
||||
data.flip(i);
|
||||
((InterfaceDataTypeBinary) tmpIndy).SetBinaryGenotype(data);
|
||||
evaluate(tmpIndy);
|
||||
if(tmpIndy.getFitness(0)<indy.getFitness(0)){
|
||||
improvement = true;
|
||||
indy = (AbstractEAIndividual) tmpIndy.clone();
|
||||
data = ((InterfaceDataTypeBinary)tmpIndy).getBinaryData();
|
||||
}else{
|
||||
tmpIndy = (AbstractEAIndividual) indy.clone();
|
||||
}
|
||||
}
|
||||
cl = order(cl);
|
||||
for(int i=0; i<cl.size()-1; i++){
|
||||
boolean valI = ((InterfaceDataTypeBinary) tmpIndy).getBinaryData().get(i);
|
||||
for(int j=i+1; j<cl.size(); j++){
|
||||
boolean valJ = ((InterfaceDataTypeBinary) tmpIndy).getBinaryData().get(i);
|
||||
if(valJ != valI){
|
||||
data.set(i, valJ);
|
||||
data.set(j, valI);
|
||||
((InterfaceDataTypeBinary) tmpIndy).SetBinaryGenotype(data);
|
||||
evaluate(tmpIndy);
|
||||
if(tmpIndy.getFitness(0)<indy.getFitness(0)){
|
||||
improvement = true;
|
||||
indy = (AbstractEAIndividual) tmpIndy.clone();
|
||||
data = ((InterfaceDataTypeBinary)tmpIndy).getBinaryData();
|
||||
i=cl.size();
|
||||
j=cl.size();
|
||||
}else{
|
||||
tmpIndy = (AbstractEAIndividual) indy.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
localIter++;
|
||||
}
|
||||
return indy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine all the individuals in the reference Set (always 2)
|
||||
* @return the List with all the combinations
|
||||
*/
|
||||
public ArrayList<Population> generateSubsets(){
|
||||
ArrayList<Population> result = new ArrayList<Population>();
|
||||
for(int i=0; i<this.refSet.size(); i++){
|
||||
for(int j=i+1; j<this.refSet.size(); j++){
|
||||
Population tmp = new Population();
|
||||
tmp.add(this.refSet.getIndividual(i));
|
||||
tmp.add(this.refSet.getIndividual(j));
|
||||
result.add((Population) tmp.clone());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* combine the first individual with the second one
|
||||
* @param pop the Population
|
||||
* @return the new Individual
|
||||
*/
|
||||
public AbstractEAIndividual combineSolution(Population pop){
|
||||
AbstractEAIndividual result = (AbstractEAIndividual) template.clone();
|
||||
if(pop.size()>=2){
|
||||
AbstractEAIndividual indy1 = pop.getEAIndividual(0);
|
||||
pop.remove(0);
|
||||
// Because some Crossover-Methods need the score, we need to give them the RefSet
|
||||
for(int i=0; i<this.refSet.size(); i++){
|
||||
pop.add(this.refSet.getEAIndividual(i));
|
||||
}
|
||||
this.cross.update(indy1, problem, refSet, indy1.getFitness(0));
|
||||
result = this.cross.mate(indy1, pop)[0];
|
||||
evaluate(null);
|
||||
//result = indy1.mateWith(s)[0];
|
||||
}else if(pop.size()>0){
|
||||
result = pop.getBestEAIndividual();
|
||||
}else{
|
||||
System.err.println("Population empty");
|
||||
//return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* look if the individual is already in the population
|
||||
* @param indy the Individual to be tested
|
||||
* @param pop the population in where to search
|
||||
* @return is the individual already in the Population
|
||||
*/
|
||||
private boolean contains(InterfaceDataTypeBinary indy, Population pop){
|
||||
if(pop.size()<=0){
|
||||
return false;
|
||||
}else{
|
||||
BitSet data = indy.getBinaryData();
|
||||
for(int i=0; i<pop.size(); i++){
|
||||
BitSet tmpData = ((InterfaceDataTypeBinary) pop.getEAIndividual(i)).getBinaryData();
|
||||
if(tmpData.equals(data)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
problem.evaluatePopulationStart(refSet);
|
||||
int funCallsStart = this.refSet.getFunctionCalls();
|
||||
do {
|
||||
// generate a new Pool
|
||||
this.pool = new Population();
|
||||
ArrayList<Population> newSubsets = generateSubsets();
|
||||
for(int i=0; i<newSubsets.size(); i++){
|
||||
Population s = newSubsets.get(i);
|
||||
AbstractEAIndividual x = combineSolution(s);
|
||||
if(!contains((InterfaceDataTypeBinary)x,this.pool)&&this.pool.size()<=this.poolSize){
|
||||
this.pool.add(x);
|
||||
}
|
||||
}
|
||||
this.refSet.incrFunctionCallsBy(this.pool.size());
|
||||
// increase the number of evaluations by the number of evaluations that are performed in the crossover-step
|
||||
for(int i=0; i<this.cross.getEvaluations(); i++){
|
||||
evaluate(null);
|
||||
}
|
||||
// reset the extra evaluations
|
||||
this.cross.resetEvaluations();
|
||||
// get the best half of the Populations
|
||||
Population best = this.refSet.getBestNIndividuals(this.refSetSize/2, fitCrit);
|
||||
// do a local search on the better half of the reference Set
|
||||
for(int i=0; i<best.size(); i++){
|
||||
AbstractEAIndividual indy = best.getEAIndividual(i);
|
||||
AbstractEAIndividual x = improve((AbstractEAIndividual)indy.clone());
|
||||
if(x.getFitness(0)<indy.getFitness(0) && !contains((InterfaceDataTypeBinary)x, this.refSet)){
|
||||
this.refSet.remove(indy);
|
||||
this.refSet.add(x);
|
||||
}
|
||||
}
|
||||
// update the referenceSet
|
||||
boolean changed = refSetUpdate(false);
|
||||
// if no change occurred, replace the worst half of the referenceSet
|
||||
if(!changed){
|
||||
refSetUpdate(true);
|
||||
}
|
||||
} while (refSet.getFunctionCalls()-funCallsStart < generationCycle);
|
||||
problem.evaluatePopulationEnd(refSet);
|
||||
}
|
||||
|
||||
public Population getPopulation() {
|
||||
return this.refSet;
|
||||
}
|
||||
|
||||
public void setPopulation(Population pop) {
|
||||
this.refSet = pop;
|
||||
this.refSetSize = pop.getTargetSize();
|
||||
}
|
||||
|
||||
public String populationTipText(){
|
||||
return "The Population";
|
||||
}
|
||||
|
||||
public InterfaceSolutionSet getAllSolutions() {
|
||||
return new SolutionSet(this.refSet);
|
||||
}
|
||||
|
||||
public void SetIdentifier(String name) {
|
||||
this.m_Identifier = name;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return this.m_Identifier;
|
||||
}
|
||||
|
||||
public void SetProblem(InterfaceOptimizationProblem problem) {
|
||||
this.problem = (AbstractOptimizationProblem) problem;
|
||||
}
|
||||
|
||||
public InterfaceOptimizationProblem getProblem() {
|
||||
return this.problem;
|
||||
}
|
||||
|
||||
public String getStringRepresentation() {
|
||||
return "BinaryScatterSearch";
|
||||
}
|
||||
|
||||
public void freeWilly() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
protected void firePropertyChangedEvent (String name) {
|
||||
if (this.m_Listener != null) this.m_Listener.registerPopulationStateChanged(this, name);
|
||||
}
|
||||
|
||||
public void registerPopulationStateChanged(Object source, String name) {
|
||||
// The events of the interim hill climbing population will be caught here
|
||||
if (name.compareTo(Population.funCallIntervalReached) == 0) {
|
||||
// set funcalls to real value
|
||||
refSet.SetFunctionCalls(((Population)source).getFunctionCalls());
|
||||
|
||||
// System.out.println("FunCallIntervalReached at " + (((Population)source).getFunctionCalls()));
|
||||
|
||||
this.firePropertyChangedEvent(Population.nextGenerationPerformed);
|
||||
}
|
||||
}
|
||||
|
||||
//----------GUI----------
|
||||
|
||||
public int getPoolSize(){
|
||||
return this.poolSize;
|
||||
}
|
||||
|
||||
public void setPoolSize(int i){
|
||||
this.poolSize = i;
|
||||
}
|
||||
|
||||
public String poolSizeTipText(){
|
||||
return "The number of individuals created in the diversification step";
|
||||
}
|
||||
|
||||
public double getThresholdHigh(){
|
||||
return th2;
|
||||
}
|
||||
|
||||
public void setThresholdHigh(double t){
|
||||
this.th2 = t;
|
||||
}
|
||||
|
||||
public String thresholdHighTipText(){
|
||||
return "Only scores set to 0 with a value below this value will be improved";
|
||||
}
|
||||
|
||||
public double getThresholdLow(){
|
||||
return th1;
|
||||
}
|
||||
|
||||
public void setThresholdLow(double t){
|
||||
this.th1 = t;
|
||||
}
|
||||
|
||||
public String thresholdLowTipText(){
|
||||
return "Only scores set to 1 with a value above this value will be improved";
|
||||
}
|
||||
|
||||
public int getLocalSearchSteps(){
|
||||
return this.MaxImpIter;
|
||||
}
|
||||
|
||||
public void setLocalSearchSteps(int i){
|
||||
this.MaxImpIter = i;
|
||||
}
|
||||
|
||||
public String localSearchStepsTipText(){
|
||||
return "Maximum number of local search iterations";
|
||||
}
|
||||
|
||||
public AdaptiveCrossoverEAMixer getCrossoverMethods(){
|
||||
return this.cross;
|
||||
}
|
||||
|
||||
|
||||
public void setCrossoverMethods(AdaptiveCrossoverEAMixer c){
|
||||
this.cross = c;
|
||||
}
|
||||
|
||||
public String crossoverMethodsTipText(){
|
||||
return "The crossover Methods used to create the pool";
|
||||
}
|
||||
|
||||
public int getGenerationCycle(){
|
||||
return this.generationCycle;
|
||||
}
|
||||
|
||||
public void setGenerationCycle(int i){
|
||||
this.generationCycle = i;
|
||||
}
|
||||
|
||||
public String generationCycleTipText(){
|
||||
return "The number of evaluations done in every generation Cycle";
|
||||
}
|
||||
|
||||
public double getPerCentFirstGenMethod(){
|
||||
return this.g1;
|
||||
}
|
||||
|
||||
public void setPerCentFirstGenMethod(double d){
|
||||
this.g1 = d;
|
||||
}
|
||||
|
||||
public String perCentFirstGenMethodTipText(){
|
||||
return "The number of individuals generated with the first Generation Method. The percentage, that is not covered with the first and the second method will be covered with a third method";
|
||||
}
|
||||
|
||||
public double getPerCentSecondGenMethod(){
|
||||
return this.g2;
|
||||
}
|
||||
|
||||
public void setPerCentSecondGenMethod(double d){
|
||||
this.g2 = d;
|
||||
}
|
||||
|
||||
public String perCentSecondGenMethodTipText(){
|
||||
return "The number of individuals generated with the second Generation Method. The percentage, that is not covered with the first and the second method will be covered with a third method";
|
||||
}
|
||||
|
||||
public static String globalInfo(){
|
||||
return "A basic implementation of a Binary ScatterSearch";
|
||||
}
|
||||
}
|
639
src/eva2/tools/math/BayNet.java
Normal file
639
src/eva2/tools/math/BayNet.java
Normal file
@ -0,0 +1,639 @@
|
||||
package eva2.tools.math;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import eva2.gui.BeanInspector;
|
||||
import eva2.server.go.individuals.AbstractEAIndividual;
|
||||
import eva2.server.go.individuals.GAIndividualBinaryData;
|
||||
import eva2.server.go.individuals.InterfaceDataTypeBinary;
|
||||
import eva2.server.go.individuals.InterfaceGAIndividual;
|
||||
import eva2.server.go.populations.Population;
|
||||
import eva2.tools.Pair;
|
||||
|
||||
public class BayNet {
|
||||
|
||||
private boolean[][] network = null;
|
||||
private int dimension = 5;
|
||||
private BayNode[] nodes = null;
|
||||
private List<BayNode> rootNodes = new LinkedList<BayNode>();
|
||||
private double upperProbLimit = 0.9;
|
||||
private double lowerProbLimit = 0.1;
|
||||
|
||||
public BayNet(int dimension, double upperLimit, double lowerLimit){
|
||||
this.dimension = dimension;
|
||||
this.upperProbLimit = upperLimit;
|
||||
this.lowerProbLimit = lowerLimit;
|
||||
init();
|
||||
}
|
||||
|
||||
public BayNet(BayNet b){
|
||||
this.network = cloneNetwork(b.network);
|
||||
this.dimension = b.dimension;
|
||||
this.nodes = new BayNode[b.dimension];
|
||||
for(int i=0; i<this.nodes.length; i++){
|
||||
this.nodes[i] = (BayNode) b.nodes[i].clone();
|
||||
}
|
||||
this.rootNodes = new LinkedList<BayNode>();
|
||||
for(BayNode node: b.rootNodes){
|
||||
this.rootNodes.add(this.nodes[node.getId()]);
|
||||
}
|
||||
this.upperProbLimit = b.upperProbLimit;
|
||||
this.lowerProbLimit = b.lowerProbLimit;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new BayNet(this);
|
||||
}
|
||||
|
||||
private boolean[][] cloneNetwork(boolean[][] b){
|
||||
boolean[][] result = new boolean[b.length][b.length];
|
||||
for(int i=0; i<b.length; i++){
|
||||
for(int j=0; j<b.length; j++){
|
||||
if(b[i][j]){
|
||||
result[i][j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the Network
|
||||
*/
|
||||
public void init(){
|
||||
this.network = new boolean[this.dimension][this.dimension];
|
||||
this.nodes = new BayNode[this.dimension];
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
this.nodes[i] = new BayNode(i);
|
||||
this.rootNodes.add(this.nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static BitSet getBinaryData(AbstractEAIndividual indy) {
|
||||
if (indy instanceof InterfaceGAIndividual) return ((InterfaceGAIndividual)indy).getBGenotype();
|
||||
else if (indy instanceof InterfaceDataTypeBinary) return ((InterfaceDataTypeBinary)indy).getBinaryData();
|
||||
else {
|
||||
throw new RuntimeException("Unable to get binary representation for " + indy.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a list of the root nodes
|
||||
*/
|
||||
public List<BayNode> getRootNodes(){
|
||||
// ArrayList<BayNode> result = new ArrayList<BayNode>();
|
||||
// for (int i=0; i<this.dimension; i++){
|
||||
// // when the column is empty, we have no incoming edges and the node is a root-node
|
||||
// boolean root = true;
|
||||
// for(int j=0; j<this.dimension; j++){
|
||||
// if(this.network[j][i]){
|
||||
// root = false;
|
||||
// j=this.dimension;
|
||||
// }
|
||||
// }
|
||||
// if(root){
|
||||
// result.add(getNode(i));
|
||||
// }
|
||||
// }
|
||||
// return result;
|
||||
return this.rootNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the i-th node
|
||||
* @param i the node to be returned
|
||||
* @return the requested node
|
||||
*/
|
||||
public BayNode getNode(int i){
|
||||
return this.nodes[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* return the children for a given node
|
||||
* @param n the node
|
||||
* @return the children of the node
|
||||
*/
|
||||
public List<BayNode> getChildren(BayNode n){
|
||||
// ArrayList<BayNode> result = new ArrayList<BayNode>();
|
||||
// int i = n.getId();
|
||||
// for(int j=0; j<this.dimension; j++){
|
||||
// if(this.network[i][j]){
|
||||
// result.add(this.nodes[j]);
|
||||
// }
|
||||
// }
|
||||
// return result;
|
||||
List<Integer> ids = n.getChildren();
|
||||
List<BayNode> result = new ArrayList<BayNode>();
|
||||
for(int i: ids){
|
||||
result.add(this.nodes[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the parents for a given node
|
||||
* @param n the node
|
||||
* @return the parents of the node
|
||||
*/
|
||||
public List<BayNode> getParents(BayNode n){
|
||||
// ArrayList<BayNode> result = new ArrayList<BayNode>();
|
||||
// int i = n.getId();
|
||||
// for(int j=0; j<this.dimension; j++){
|
||||
// if(this.network[j][i]){
|
||||
// result.add(this.nodes[j]);
|
||||
// }
|
||||
// }
|
||||
// if (result.size()!=n.getNumberOfParents()) {
|
||||
// System.err.println("Error in getParents!");
|
||||
// }
|
||||
// return result;
|
||||
List<Integer> ids = n.getParents();
|
||||
List<BayNode> result = new LinkedList<BayNode>();
|
||||
for(int i: ids){
|
||||
result.add(this.nodes[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the children of a list of nodes
|
||||
* @param n the list of nodes
|
||||
* @return the children of the nodes
|
||||
*/
|
||||
public List<BayNode> getChildren(List<BayNode> n){
|
||||
ArrayList<BayNode> result = new ArrayList<BayNode>();
|
||||
for(BayNode node: n){
|
||||
List<BayNode> children = getChildren(node);
|
||||
for(BayNode nod: children){
|
||||
if(!result.contains(nod)){
|
||||
result.add(nod);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the edge from node i to node j
|
||||
* @param i the node from which the edge comes
|
||||
* @param j the node to which the edge points
|
||||
*/
|
||||
public void removeEdge(int i, int j){
|
||||
if(this.network[i][j]){
|
||||
this.network[i][j] = false;
|
||||
this.nodes[j].decrNumberOfParents();
|
||||
this.nodes[i].removeChild(j);
|
||||
this.nodes[j].removeParent(i);
|
||||
this.nodes[j].generateNewPTable();
|
||||
if(this.nodes[j].getNumberOfParents() == 0){
|
||||
this.rootNodes.add(nodes[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add an edge from the node i to the node j
|
||||
* @param i edge from this node
|
||||
* @param j edge to this node
|
||||
*/
|
||||
public void addEdge(int i, int j){
|
||||
if(!this.network[i][j]){
|
||||
this.network[i][j] = true;
|
||||
this.nodes[j].incrNumberOfParents();
|
||||
this.nodes[j].generateNewPTable();
|
||||
this.rootNodes.remove(this.nodes[j]);
|
||||
this.nodes[i].addChild(j);
|
||||
this.nodes[j].addParent(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find the next value where all the parents are already set
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
private int findNext(double[] probabilities, List<BayNode> nodes){
|
||||
for(BayNode node: nodes){
|
||||
List<BayNode> parents = getParents(node);
|
||||
boolean possible = false;
|
||||
for(BayNode p: parents){
|
||||
if(probabilities[p.getId()] != -1){
|
||||
possible = true;
|
||||
}else{
|
||||
possible = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(possible){
|
||||
return node.getId();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate a new BitSet according to the network
|
||||
* @param data the BitSet that will be calculated
|
||||
* @return the new BitSet
|
||||
*/
|
||||
public BitSet sample(BitSet data){
|
||||
// generate a new probabilities-vector
|
||||
double[] probabilities = new double[this.network.length];
|
||||
for(int i=0; i<probabilities.length; i++){
|
||||
probabilities[i] = -1;
|
||||
}
|
||||
// get the root-nodes (the non dependent nodes)
|
||||
List<BayNode> nodes = getRootNodes();
|
||||
// calculate the BitSet-Value for these nodes
|
||||
for(BayNode node: nodes){
|
||||
int id = node.getId();
|
||||
probabilities[id] = node.getProbability(0);
|
||||
data.set(id, RNG.flipCoin(probabilities[id]));
|
||||
}
|
||||
// find the next node that can be evaluated
|
||||
List<BayNode> toCalculate = getChildren(nodes);
|
||||
int next = findNext(probabilities, toCalculate);
|
||||
while(next != -1){
|
||||
toCalculate.remove(this.nodes[next]);
|
||||
probabilities[next] = calculateNextProbability(data, toCalculate, next);
|
||||
data.set(next, RNG.flipCoin(probabilities[next]));
|
||||
next = findNext(probabilities, toCalculate);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the next probability
|
||||
* @param data the already calculated data
|
||||
* @param probabilities the already calculated probabilities
|
||||
* @param toCalculate the Nodes that have yet to be calculated
|
||||
* @param next the node for which to calculate the probability
|
||||
* @return the new probabilities array
|
||||
*/
|
||||
private double calculateNextProbability(BitSet data, List<BayNode> toCalculate, int next) {
|
||||
toCalculate.addAll(getChildren(this.nodes[next]));
|
||||
int[] parId = calculateSortedParentIds(next);
|
||||
int prob = 0;
|
||||
int cnt = 0;
|
||||
for(int j=parId.length-1; j>=0; j--){
|
||||
if(data.get(parId[j])){
|
||||
prob += (int) Math.pow(2, j);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
return this.nodes[next].getProbability(prob);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an array of the parents, sorted by there id
|
||||
* @param id the id of the node
|
||||
* @return the sorted parent-ids
|
||||
*/
|
||||
private int[] calculateSortedParentIds(int id) {
|
||||
List<BayNode> parents = getParents(this.nodes[id]);
|
||||
int[] parId = new int[parents.size()];
|
||||
int i=0;
|
||||
for(BayNode nod: parents){
|
||||
parId[i] = nod.getId();
|
||||
i++;
|
||||
}
|
||||
Arrays.sort(parId);
|
||||
return parId;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate an array of the parents plus the given node, sorted by there id
|
||||
* @param id the id of the node
|
||||
* @return the sorted parent-ids
|
||||
*/
|
||||
private int[] calculateSortedParentPlusNodeIds(int id) {
|
||||
List<BayNode> nodes = getParents(this.nodes[id]);
|
||||
nodes.add(this.nodes[id]);
|
||||
int[] sortedIds = new int[nodes.size()];
|
||||
int i=0;
|
||||
for(BayNode nod: nodes){
|
||||
sortedIds[i] = nod.getId();
|
||||
i++;
|
||||
}
|
||||
Arrays.sort(sortedIds);
|
||||
return sortedIds;
|
||||
}
|
||||
|
||||
private void resetCalculated(){
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
this.nodes[i].setCalculated(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* see if the network is still acyclic after inserting the edge
|
||||
* @param from the node from which the edge comes from
|
||||
* @param to the node to which the edgte points
|
||||
* @return is the network still acyclic
|
||||
*/
|
||||
public boolean isACyclic(int from, int to){
|
||||
int cnt1 = 0;
|
||||
int cnt2 = 0;
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
if(this.network[i][from]){
|
||||
cnt1++;
|
||||
}
|
||||
if(this.network[to][i]){
|
||||
cnt2++;
|
||||
}
|
||||
}
|
||||
// if the from node has no incoming edges or the to node has no outgoing edges the network is still acyclic
|
||||
if(cnt1==0 || cnt2==0){
|
||||
return true;
|
||||
}
|
||||
// look at all the children and see if we can get to the from-node from the to-node
|
||||
List<BayNode> toCalculate = getChildren(this.nodes[to]);
|
||||
while(!toCalculate.isEmpty()){
|
||||
BayNode node = toCalculate.get(0);
|
||||
toCalculate.remove(node);
|
||||
if(!node.getCalculated()){
|
||||
node.setCalculated(true);
|
||||
if(from == node.getId()){
|
||||
resetCalculated();
|
||||
return false;
|
||||
}
|
||||
List<BayNode> children = getChildren(node);
|
||||
toCalculate.addAll(children);
|
||||
}
|
||||
}
|
||||
resetCalculated();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the given Network is acyclic
|
||||
* @param net the Network
|
||||
* @return is the net acyclic
|
||||
*/
|
||||
public boolean isACyclic(){
|
||||
List<Pair<Integer,Integer>> deletedEdges = new LinkedList<Pair<Integer,Integer>>();
|
||||
List<BayNode> nodes = getRootNodes();
|
||||
boolean res=false;
|
||||
for(int i=0; i<=this.dimension; i++){
|
||||
for(BayNode node: nodes){
|
||||
int id = node.getId();
|
||||
for(int j=0; j<this.dimension; j++){
|
||||
if (this.network[id][j]) {
|
||||
this.network[id][j] = false;
|
||||
deletedEdges.add(new Pair<Integer,Integer>(id,j));
|
||||
}
|
||||
}
|
||||
}
|
||||
nodes = getRootNodes();
|
||||
// if we only have root nodes, we have an acyclic graph
|
||||
if(nodes.size() == this.nodes.length){
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// System.out.println("Deleted edges: " + BeanInspector.toString(deletedEdges));
|
||||
for (Pair<Integer,Integer> edge : deletedEdges) {
|
||||
this.network[edge.head][edge.tail] = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private double getPrior(List<BayNode> parents, Population pop){
|
||||
return (double) pop.size() / Math.pow(2.0, (double) parents.size());
|
||||
}
|
||||
|
||||
private double getPrior(List<BayNode> parents, BayNode current, Population pop){
|
||||
return getPrior(parents, pop) / 2.0;
|
||||
}
|
||||
|
||||
private void setRootPTables(Population pop){
|
||||
List<BayNode> rootNodes = getRootNodes();
|
||||
for(BayNode node: rootNodes){
|
||||
int id = node.getId();
|
||||
double count = 0;
|
||||
for(int i=0; i<pop.size(); i++){
|
||||
BitSet data = getBinaryData(pop.getEAIndividual(i));
|
||||
if(data.get(id)){
|
||||
count++;
|
||||
}
|
||||
}
|
||||
double prob = count / (double) pop.size();
|
||||
setProbability(node, 0, prob);
|
||||
// node.setPTable(0, count / (double) pop.size());
|
||||
}
|
||||
}
|
||||
|
||||
public void setUpperProbLimit(double upperProbLimit) {
|
||||
this.upperProbLimit = upperProbLimit;
|
||||
}
|
||||
|
||||
public void setLowerProbLimit(double lowerProbLimit) {
|
||||
this.lowerProbLimit = lowerProbLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate the bayesian Dirichlet Metric
|
||||
* @param pop the population on which the metric is based on
|
||||
* @return the metric
|
||||
*/
|
||||
public double bayesianDirichletMetric(Population pop){
|
||||
double result = 1.0;
|
||||
//for every node
|
||||
setRootPTables(pop);
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
BayNode currentNode = this.nodes[i];
|
||||
//get the parents
|
||||
List<BayNode> parents = getParents(currentNode);
|
||||
// System.out.println("parents: "+parents.size());
|
||||
// get the parentIds sorted (for the lookup)
|
||||
if(!parents.isEmpty()){
|
||||
int[] parId = calculateSortedParentIds(i);
|
||||
// the parentIds plus the id of the current node sorted (for the lookup
|
||||
int[] nodeIds = calculateSortedParentPlusNodeIds(i);
|
||||
double[] pTable = currentNode.getPTable();
|
||||
for(int j=0; j<pTable.length; j++){
|
||||
Population pop2 = numberSetCorrectly(pop, j, parId);
|
||||
double count = (double) pop2.size();
|
||||
double numeratorFirstFraction = SpecialFunction.gamma(getPrior(parents, pop));
|
||||
double denominatorFirstFraction = SpecialFunction.gamma(getPrior(parents, pop)+count);
|
||||
double firstFraction = numeratorFirstFraction / denominatorFirstFraction;
|
||||
result = result * firstFraction;
|
||||
// currentNode.setPTable(j, count / (double) pop.size());
|
||||
count = 0;
|
||||
for(int k=0; k<2; k++){
|
||||
double cnt = numberSetCorrectly(pop2, j, k, nodeIds, parId);
|
||||
double numeratorSecondFraction = SpecialFunction.gamma(getPrior(parents, currentNode, pop) + cnt);
|
||||
double denumeratorSecondFraction = SpecialFunction.gamma(getPrior(parents, currentNode, pop));
|
||||
double secondFraction = numeratorSecondFraction / denumeratorSecondFraction;
|
||||
result = result * secondFraction;
|
||||
double prob = cnt / (double) pop2.size();
|
||||
setProbability(currentNode, j, prob);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setProbability(BayNode n, int j, double prob){
|
||||
n.setPTable(j, Math.min(upperProbLimit, Math.max(lowerProbLimit, prob)));
|
||||
}
|
||||
|
||||
private double numberSetCorrectly(Population pop, int j, int k, int[] Ids, int[] parIds){
|
||||
double result = 0.0;
|
||||
String binaryString = Integer.toBinaryString(j);
|
||||
while(binaryString.length() < parIds.length){
|
||||
binaryString = "0"+binaryString;
|
||||
}
|
||||
boolean found = false;
|
||||
boolean end = false;
|
||||
int different = 0;
|
||||
for(int i=0; i<parIds.length; i++){
|
||||
if(parIds[i] != Ids[i]){
|
||||
different = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
different = Ids.length;
|
||||
end = true;
|
||||
}
|
||||
if(end){
|
||||
binaryString = binaryString+k;
|
||||
}else{
|
||||
binaryString = binaryString.substring(0, different)+k+binaryString.substring(different);
|
||||
}
|
||||
int l = Integer.parseInt(binaryString);
|
||||
// binary = getBinaryArray(Ids, binaryString);
|
||||
for(int i=0; i<pop.size(); i++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(i);
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy).getBinaryData();
|
||||
boolean setCorrectly = isSetCorrectly(Ids, data, l);
|
||||
if(setCorrectly){
|
||||
result ++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Population numberSetCorrectly(Population pop, int j, int[] Ids){
|
||||
Population result = new Population();
|
||||
// String binaryString = Integer.toBinaryString(j);
|
||||
// append zeroes to the front
|
||||
// boolean[] binary = getBinaryArray(Ids, binaryString);
|
||||
for(int i=0; i<pop.size(); i++){
|
||||
AbstractEAIndividual indy = pop.getEAIndividual(i);
|
||||
BitSet data = ((InterfaceDataTypeBinary) indy).getBinaryData();
|
||||
boolean setCorrectly = isSetCorrectly(Ids, data, j);
|
||||
if(setCorrectly){
|
||||
// result ++;
|
||||
result.add(indy);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* is the BitSet of the individual set correctly corresponding to the binary String and the parId
|
||||
* @param ids the Ids of the parents sorted
|
||||
* @param data the data of the individual to be checked
|
||||
* @param j how the Bits have to be set (as Integer)
|
||||
* @return is the data set correctly
|
||||
*/
|
||||
private boolean isSetCorrectly(int[] ids, BitSet data, int j) {
|
||||
boolean setCorrectly = false;
|
||||
for(int m=0; m<ids.length; m++){
|
||||
if(((j & (1<<m))>0) && (data.get(ids[m]))){
|
||||
setCorrectly = true;
|
||||
}else if(!((j & (1<<m))>0) && (!data.get(ids[m]))){
|
||||
setCorrectly = true;
|
||||
}else{
|
||||
setCorrectly = false;
|
||||
m = j+10;
|
||||
}
|
||||
}
|
||||
return setCorrectly;
|
||||
}
|
||||
|
||||
public void print(){
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
for(int j=0; j<this.dimension; j++){
|
||||
if(this.network[i][j]){
|
||||
System.out.print("1");
|
||||
}else{
|
||||
System.out.print("0");
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
for(int i=0; i<this.dimension; i++){
|
||||
System.out.println(BeanInspector.toString(nodes[i].getPTable()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* has the network already an edge from node i to node j
|
||||
* @param i the node from which the edge originates
|
||||
* @param j the node to which the edge points
|
||||
* @return is the edge already there
|
||||
*/
|
||||
public boolean hasEdge(int i, int j){
|
||||
return this.network[i][j];
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
BayNet b = new BayNet(3, 0.9, 0.1);
|
||||
b.addEdge(0, 2);
|
||||
b.addEdge(1, 2);
|
||||
Population pop = new Population();
|
||||
GAIndividualBinaryData indy1 = new GAIndividualBinaryData();
|
||||
indy1.setBinaryDataLength(3);
|
||||
GAIndividualBinaryData indy2 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy3 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy4 = (GAIndividualBinaryData) indy1.clone();
|
||||
GAIndividualBinaryData indy5 = (GAIndividualBinaryData) indy1.clone();
|
||||
BitSet data1 = indy1.getBinaryData();
|
||||
BitSet data2 = indy2.getBinaryData();
|
||||
BitSet data3 = indy3.getBinaryData();
|
||||
BitSet data4 = indy4.getBinaryData();
|
||||
BitSet data5 = indy5.getBinaryData();
|
||||
data1.set(0, true);
|
||||
data1.set(1, true);
|
||||
data1.set(2, false);
|
||||
data2.set(0, true);
|
||||
data2.set(1, true);
|
||||
data2.set(2, true);
|
||||
data3.set(0, false);
|
||||
data3.set(1, true);
|
||||
data3.set(2, false);
|
||||
data4.set(0, false);
|
||||
data4.set(1, true);
|
||||
data4.set(2, true);
|
||||
data5.set(0, true);
|
||||
data5.set(1, false);
|
||||
data5.set(2, false);
|
||||
indy1.SetBinaryGenotype(data1);
|
||||
indy2.SetBinaryGenotype(data2);
|
||||
indy3.SetBinaryGenotype(data3);
|
||||
indy4.SetBinaryGenotype(data4);
|
||||
indy5.SetBinaryGenotype(data5);
|
||||
pop.add(indy1);
|
||||
pop.add(indy2);
|
||||
pop.add(indy3);
|
||||
pop.add(indy4);
|
||||
pop.add(indy5);
|
||||
|
||||
// System.out.println("-----");
|
||||
// System.out.println(pop.getStringRepresentation());
|
||||
// System.out.println("-----");
|
||||
System.out.println(b.bayesianDirichletMetric(pop));
|
||||
}
|
||||
|
||||
}
|
111
src/eva2/tools/math/BayNode.java
Normal file
111
src/eva2/tools/math/BayNode.java
Normal file
@ -0,0 +1,111 @@
|
||||
package eva2.tools.math;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class BayNode {
|
||||
|
||||
private int id;
|
||||
private int numberOfParents = 0;
|
||||
private double[] pTable = {0.5};
|
||||
private boolean calculated = false;
|
||||
private List<Integer> parents = new LinkedList<Integer>();
|
||||
private List<Integer> children = new LinkedList<Integer>();
|
||||
|
||||
public BayNode(int id){
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public BayNode(BayNode b){
|
||||
this.id = b.id;
|
||||
this.numberOfParents = b.numberOfParents;
|
||||
this.pTable = b.pTable.clone();
|
||||
this.parents = new LinkedList<Integer>();
|
||||
this.children = new LinkedList<Integer>();
|
||||
for(int i: b.parents){
|
||||
this.parents.add(i);
|
||||
}
|
||||
for(int i: b.children){
|
||||
this.children.add(i);
|
||||
}
|
||||
this.calculated = b.calculated;
|
||||
}
|
||||
|
||||
public Object clone(){
|
||||
return new BayNode(this);
|
||||
}
|
||||
|
||||
public double getProbability(int i){
|
||||
return pTable[i];
|
||||
}
|
||||
|
||||
public void generateNewPTable(){
|
||||
this.pTable = new double[(int) Math.pow(2, this.numberOfParents)];
|
||||
for(int i=0; i<this.pTable.length; i++){
|
||||
this.pTable[i] = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> getParents(){
|
||||
return this.parents;
|
||||
}
|
||||
|
||||
public void addParent(Integer b){
|
||||
if(!this.parents.contains(b)){
|
||||
this.parents.add(b);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeParent(Integer b){
|
||||
this.parents.remove(b);
|
||||
}
|
||||
|
||||
public List<Integer> getChildren(){
|
||||
return this.children;
|
||||
}
|
||||
|
||||
public void addChild(Integer b){
|
||||
if(!this.children.contains(b)){
|
||||
this.children.add(b);
|
||||
}
|
||||
}
|
||||
public void removeChild(Integer b){
|
||||
this.children.remove(b);
|
||||
}
|
||||
|
||||
public void setPTable(double[] table){
|
||||
this.pTable = table;
|
||||
}
|
||||
|
||||
public void setPTable(int i, double v){
|
||||
this.pTable[i] = v;
|
||||
}
|
||||
|
||||
public void incrNumberOfParents(){
|
||||
this.numberOfParents++;
|
||||
}
|
||||
|
||||
public void decrNumberOfParents(){
|
||||
this.numberOfParents--;
|
||||
}
|
||||
|
||||
public int getNumberOfParents(){
|
||||
return this.numberOfParents;
|
||||
}
|
||||
|
||||
public int getId(){
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public double[] getPTable(){
|
||||
return this.pTable;
|
||||
}
|
||||
|
||||
public boolean getCalculated(){
|
||||
return this.calculated;
|
||||
}
|
||||
|
||||
public void setCalculated(boolean b){
|
||||
this.calculated = b;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user