Skip to content

Commit 696cc02

Browse files
Debabrata AcharyaDebabrata Acharya
authored andcommitted
add ZDT1 Test Suite
1 parent c0b2ee7 commit 696cc02

File tree

11 files changed

+341
-4
lines changed

11 files changed

+341
-4
lines changed

src/main/java/com/debacharya/nsgaii/Reporter.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public static void reportChromosome(Chromosome chromosome) {
119119
Reporter.reportGeneticCode(chromosome.getGeneticCode());
120120

121121
p(">> " + chromosome.toString());
122+
p("");
122123
}
123124

124125
public static void reportGeneticCode(List<AbstractAllele> geneticCode) {

src/main/java/com/debacharya/nsgaii/datastructure/BooleanAllele.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ public BooleanAllele(boolean gene) {
3232

3333
@Override
3434
public Boolean getGene() {
35-
return (Boolean) this.gene;
35+
return (boolean) this.gene;
3636
}
3737

3838
@Override
3939
public AbstractAllele getCopy() {
40-
return new BooleanAllele((Boolean) this.gene);
40+
return new BooleanAllele((boolean) this.gene);
4141
}
4242

4343
@Override

src/main/java/com/debacharya/nsgaii/datastructure/Chromosome.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public void reset() {
159159
@Override
160160
public String toString() {
161161

162-
StringBuilder response = new StringBuilder("Objective values: [");
162+
StringBuilder response = new StringBuilder("Objective values: [ ");
163163

164164
for(double value : this.objectiveValues)
165165
response.append(value).append(" ");
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.debacharya.nsgaii.datastructure;
2+
3+
public class ValueAllele extends AbstractAllele {
4+
5+
public ValueAllele(double gene) {
6+
super(gene);
7+
}
8+
9+
@Override
10+
public Double getGene() {
11+
return (double) this.gene;
12+
}
13+
14+
@Override
15+
public AbstractAllele getCopy() {
16+
return new ValueAllele((double) this.gene);
17+
}
18+
19+
@Override
20+
public String toString() {
21+
return String.valueOf((double) this.gene);
22+
}
23+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.debacharya.nsgaii.objectivefunction;
2+
3+
import com.debacharya.nsgaii.datastructure.BooleanAllele;
4+
import com.debacharya.nsgaii.datastructure.Chromosome;
5+
import com.debacharya.nsgaii.datastructure.ValueAllele;
6+
import com.debacharya.nsgaii.plugin.SinglePointMutation;
7+
8+
import java.util.stream.Collector;
9+
import java.util.stream.Collectors;
10+
11+
public class ZDT1_1 extends AbstractObjectiveFunction {
12+
13+
private static final String VALUE_ALLELE_INSTANCE_ERROR = "ZDT1 works with ValueAllele only. Please implement your own objective " +
14+
"function class by extending the AbstractObjectiveFunction class to get " +
15+
"your desired results or use genetic code of type ValueAllele to use this " +
16+
"default implementation";
17+
18+
public ZDT1_1() {
19+
this.objectiveFunctionTitle = "x1";
20+
}
21+
22+
@Override
23+
public double getValue(Chromosome chromosome) {
24+
25+
if(!(chromosome.getAllele(0) instanceof ValueAllele))
26+
throw new UnsupportedOperationException(ZDT1_1.VALUE_ALLELE_INSTANCE_ERROR);
27+
28+
return chromosome.getGeneticCode().stream().map(e -> (ValueAllele) e).collect(Collectors.toList()).get(0).getGene();
29+
}
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.debacharya.nsgaii.objectivefunction;
2+
3+
import com.debacharya.nsgaii.datastructure.BooleanAllele;
4+
import com.debacharya.nsgaii.datastructure.Chromosome;
5+
import com.debacharya.nsgaii.datastructure.ValueAllele;
6+
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
10+
public class ZDT1_2 extends AbstractObjectiveFunction {
11+
12+
private static final String VALUE_ALLELE_INSTANCE_ERROR = "ZDT1 works with ValueAllele only. Please implement your own objective " +
13+
"function class by extending the AbstractObjectiveFunction class to get " +
14+
"your desired results or use genetic code of type ValueAllele to use this " +
15+
"default implementation";
16+
17+
public ZDT1_2() {
18+
this.objectiveFunctionTitle = "g(x) [1 - sqrt(x1 / g(x)]";
19+
}
20+
21+
@Override
22+
public double getValue(Chromosome chromosome) {
23+
24+
if(!(chromosome.getAllele(0) instanceof ValueAllele))
25+
throw new UnsupportedOperationException(ZDT1_2.VALUE_ALLELE_INSTANCE_ERROR);
26+
27+
List<ValueAllele> geneticCode = chromosome.getGeneticCode().stream().map(e -> (ValueAllele) e).collect(Collectors.toList());
28+
double size = geneticCode.size();
29+
double sum = 0;
30+
31+
for(int i = 1; i < size; i++)
32+
sum += geneticCode.get(i).getGene();
33+
34+
double g = 1 + ((9 * sum) / size);
35+
double f = g * (1 - Math.sqrt(geneticCode.get(0).getGene() / g));
36+
37+
return f;
38+
}
39+
}

src/main/java/com/debacharya/nsgaii/plugin/DefaultPluginProvider.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.debacharya.nsgaii.datastructure.BooleanAllele;
2929
import com.debacharya.nsgaii.datastructure.Chromosome;
3030
import com.debacharya.nsgaii.datastructure.Population;
31+
import com.debacharya.nsgaii.datastructure.ValueAllele;
3132

3233
import java.util.ArrayList;
3334
import java.util.List;
@@ -47,6 +48,30 @@ public static GeneticCodeProducer defaultGeneticCodeProducer() {
4748
};
4849
}
4950

51+
public static GeneticCodeProducer valueEncodedGeneticCodeProducer(double origin, double bound) {
52+
return length -> {
53+
54+
List<ValueAllele> geneticCode = new ArrayList<>();
55+
56+
for(int i = 0; i < length; i++) {
57+
58+
double value = ThreadLocalRandom.current().nextDouble(origin, (bound + 0.1));
59+
60+
if(value > bound)
61+
value = bound;
62+
63+
value = Service.roundOff(value, 4);
64+
65+
geneticCode.add(
66+
i,
67+
new ValueAllele(value)
68+
);
69+
}
70+
71+
return geneticCode;
72+
};
73+
}
74+
5075
public static PopulationProducer defaultPopulationProducer() {
5176
return (populationSize, chromosomeLength, geneticCodeProducer, fitnessCalculator) -> {
5277

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.debacharya.nsgaii.plugin;
2+
3+
import com.debacharya.nsgaii.Service;
4+
import com.debacharya.nsgaii.datastructure.Chromosome;
5+
import com.debacharya.nsgaii.datastructure.ValueAllele;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.concurrent.ThreadLocalRandom;
10+
import java.util.stream.Collectors;
11+
12+
public class PolynomialMutation extends AbstractMutation {
13+
14+
private final double origin;
15+
private final double bound;
16+
private final double distributionIndex;
17+
18+
public PolynomialMutation(double origin, double bound, double distributionIndex, float mutationProbability) {
19+
super(mutationProbability);
20+
this.origin = origin;
21+
this.bound = bound;
22+
this.distributionIndex = distributionIndex;
23+
}
24+
25+
public PolynomialMutation(double origin, double bound, double distributionIndex) {
26+
super();
27+
this.origin = origin;
28+
this.bound = bound;
29+
this.distributionIndex = distributionIndex;
30+
}
31+
32+
public PolynomialMutation(double origin, double bound) {
33+
this(origin, bound, 20);
34+
}
35+
36+
public PolynomialMutation(double distributionIndex) {
37+
this(0, 1, distributionIndex);
38+
}
39+
40+
public PolynomialMutation(float mutationProbability) {
41+
this(0, 1, 20, mutationProbability);
42+
}
43+
44+
@Override
45+
public Chromosome perform(Chromosome chromosome) {
46+
47+
List<ValueAllele> childGeneticCode = new ArrayList<>();
48+
List<ValueAllele> parentGeneticCode = chromosome.getGeneticCode().stream().map(e -> (ValueAllele) e).collect(Collectors.toList());
49+
50+
for(int i = 0; i < parentGeneticCode.size(); i++)
51+
childGeneticCode.add(i, new ValueAllele(
52+
this.shouldPerformMutation() ?
53+
this.getMutatedValue(parentGeneticCode.get(i).getGene()) :
54+
parentGeneticCode.get(i).getGene()
55+
));
56+
57+
return new Chromosome(new ArrayList<>(childGeneticCode));
58+
}
59+
60+
private double getMutatedValue(double originalValue) {
61+
62+
double probability = ThreadLocalRandom.current().nextDouble();
63+
double delta = Service.roundOff(this.generateDelta(probability), 4);
64+
double result;
65+
66+
if(probability < 0.5)
67+
result = originalValue + (delta * (originalValue - this.origin));
68+
else
69+
result = originalValue + (delta * (this.bound - originalValue));
70+
71+
if(result < this.origin)
72+
result = this.origin;
73+
else if(result > this.bound)
74+
result = this.bound;
75+
76+
return Service.roundOff(result, 4);
77+
}
78+
79+
private double generateDelta(double probability) {
80+
return (probability < 0.5)
81+
? (Math.pow(
82+
2 * probability,
83+
1 / (this.distributionIndex + 1)
84+
) - 1)
85+
: (1 - Math.pow(
86+
2 * (1 - probability),
87+
1 / (this.distributionIndex + 1)
88+
));
89+
}
90+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.debacharya.nsgaii.plugin;
2+
3+
import com.debacharya.nsgaii.Service;
4+
import com.debacharya.nsgaii.datastructure.AbstractAllele;
5+
import com.debacharya.nsgaii.datastructure.Chromosome;
6+
import com.debacharya.nsgaii.datastructure.Population;
7+
import com.debacharya.nsgaii.datastructure.ValueAllele;
8+
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
import java.util.concurrent.ThreadLocalRandom;
12+
import java.util.stream.Collectors;
13+
14+
public class SimulatedBinaryCrossover extends AbstractCrossover {
15+
16+
private final double distributionIndex;
17+
18+
public SimulatedBinaryCrossover(CrossoverParticipantCreator crossoverParticipantCreator, double distributionIndex) {
19+
super(crossoverParticipantCreator);
20+
this.distributionIndex = distributionIndex;
21+
}
22+
23+
public SimulatedBinaryCrossover(CrossoverParticipantCreator crossoverParticipantCreator) {
24+
this(crossoverParticipantCreator, 20);
25+
}
26+
27+
@Override
28+
public List<Chromosome> perform(Population population) {
29+
30+
List<Chromosome> result = new ArrayList<>();
31+
List<Chromosome> selected = this.crossoverParticipantCreator.create(population);
32+
33+
if(this.shouldPerformCrossover())
34+
result = this.prepareChildChromosomes(
35+
selected.get(0),
36+
selected.get(1)
37+
);
38+
else {
39+
result.add(selected.get(0).getCopy());
40+
result.add(selected.get(1).getCopy());
41+
}
42+
43+
return result;
44+
}
45+
46+
private List<Chromosome> prepareChildChromosomes(Chromosome parent1, Chromosome parent2) {
47+
48+
List<Chromosome> result = new ArrayList<>();
49+
List<AbstractAllele> child1GeneticCode = new ArrayList<>();
50+
List<AbstractAllele> child2GeneticCode = new ArrayList<>();
51+
List<ValueAllele> geneticCode1 = parent1.getGeneticCode().stream().map(e -> (ValueAllele) e).collect(Collectors.toList());
52+
List<ValueAllele> geneticCode2 = parent2.getGeneticCode().stream().map(e -> (ValueAllele) e).collect(Collectors.toList());
53+
54+
for(int i = 0; i < geneticCode1.size(); i++) {
55+
56+
double beta = Service.roundOff(this.generateBeta(), 4);
57+
double x1 = Service.roundOff((geneticCode1.get(i).getGene() + geneticCode2.get(i).getGene()) / 2, 4);
58+
double x2 = Service.roundOff(Math.abs(geneticCode1.get(i).getGene() - geneticCode2.get(i).getGene()) / 2, 4);
59+
60+
child1GeneticCode.add(i, new ValueAllele(
61+
Service.roundOff((x1 + (beta * x2)), 4)
62+
)
63+
);
64+
65+
child2GeneticCode.add(i, new ValueAllele(
66+
Service.roundOff((x1 - (beta * x2)), 4)
67+
)
68+
);
69+
}
70+
71+
result.add(0, new Chromosome(child1GeneticCode));
72+
result.add(1, new Chromosome(child2GeneticCode));
73+
74+
return result;
75+
}
76+
77+
private double generateBeta() {
78+
79+
double probability = ThreadLocalRandom.current().nextDouble();
80+
81+
return (probability <= 0.5d)
82+
? Math.pow(
83+
2 * probability,
84+
1 / (this.distributionIndex + 1)
85+
)
86+
: Math.pow(
87+
2 * (1 - probability),
88+
-1 / (this.distributionIndex + 1)
89+
);
90+
}
91+
}

src/main/java/com/debacharya/nsgaii/plugin/SinglePointMutation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
public class SinglePointMutation extends AbstractMutation {
3535

36-
private static final String BOOLEAN_ALLELE_INSTANCE_ERROR = "SinglePointMutation only works with BooleanAllele only. " +
36+
private static final String BOOLEAN_ALLELE_INSTANCE_ERROR = "SinglePointMutation works with BooleanAllele only. " +
3737
"Please implement your own Mutation class by extending the AbstractMutation class " +
3838
"to get your desired results.";
3939

0 commit comments

Comments
 (0)