Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 456e1b8

Browse files
committed
chapter 5
1 parent 2f1181b commit 456e1b8

File tree

4 files changed

+311
-0
lines changed

4 files changed

+311
-0
lines changed

‎CCSPiJ/src/chapter5/Chromosome.java‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package chapter5;
2+
3+
import java.util.List;
4+
5+
public abstract class Chromosome<T extends Chromosome<T>> implements Comparable<T> {
6+
public abstract double fitness();
7+
8+
public abstract List<T> crossover(T other);
9+
10+
public abstract void mutate();
11+
12+
public abstract T copy();
13+
14+
@Override
15+
public int compareTo(T other) {
16+
Double mine = this.fitness();
17+
Double theirs = other.fitness();
18+
return mine.compareTo(theirs);
19+
}
20+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package chapter5;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.Random;
7+
8+
public class GeneticAlgorithm<C extends Chromosome<C>> {
9+
10+
public enum SelectionType {
11+
ROULETTE, TOURNAMENT;
12+
}
13+
14+
private ArrayList<C> population;
15+
private double mutationChance;
16+
private double crossoverChance;
17+
private SelectionType selectionType;
18+
private Random random;
19+
20+
public GeneticAlgorithm(List<C> initialPopulation,
21+
double mutationChance, double crossoverChance, SelectionType selectionType) {
22+
this.population = new ArrayList<>(initialPopulation);
23+
this.mutationChance = mutationChance;
24+
this.crossoverChance = crossoverChance;
25+
this.selectionType = selectionType;
26+
this.random = new Random();
27+
}
28+
29+
// Use the probability distribution wheel to pick numPicks individuals
30+
private List<C> pickRoulette(double[] wheel, int numPicks) {
31+
List<C> picks = new ArrayList<>();
32+
for (int i = 0; i < numPicks; i++) {
33+
double pick = random.nextDouble();
34+
for (int j = 0; j < wheel.length; j++) {
35+
pick -= wheel[j];
36+
if (pick <= 0) { // we had one that took us over, leads to a pick
37+
picks.add(population.get(j));
38+
break;
39+
}
40+
}
41+
}
42+
return picks;
43+
}
44+
45+
// Pick a certain number of individuals via a tournament
46+
private List<C> pickTournament(int numParticipants, int numPicks) {
47+
// Find numParticipants random participants to be in the tournament
48+
Collections.shuffle(population);
49+
List<C> tournament = population.subList(0, numParticipants);
50+
// Find the numPicks highest fitnesses in the tournament
51+
Collections.sort(tournament, Collections.reverseOrder());
52+
return tournament.subList(0, numPicks);
53+
}
54+
55+
// Replace the population with a new generation of individuals
56+
private void reproduceAndReplace() {
57+
ArrayList<C> nextPopulation = new ArrayList<>();
58+
// keep going until we've filled the new generation
59+
while (nextPopulation.size() < population.size()) {
60+
// pick the two parents
61+
List<C> parents;
62+
if (selectionType == SelectionType.ROULETTE) {
63+
// create the probability distribution wheel
64+
double totalFitness = population.stream().mapToDouble(C::fitness).sum();
65+
double[] wheel = population.stream()
66+
.mapToDouble(C -> C.fitness() / totalFitness).toArray();
67+
parents = pickRoulette(wheel, 2);
68+
} else { // tournament
69+
parents = pickTournament(population.size() / 2, 2);
70+
}
71+
// potentially crossover the 2 parents
72+
if (random.nextDouble() < crossoverChance) {
73+
C parent1 = parents.get(0);
74+
C parent2 = parents.get(1);
75+
nextPopulation.addAll(parent1.crossover(parent2));
76+
} else { // just add the two parents
77+
nextPopulation.addAll(parents);
78+
}
79+
}
80+
// if we have an odd number, we'll have 1 exra, so we remove it
81+
if (nextPopulation.size() > population.size()) {
82+
nextPopulation.remove(0);
83+
}
84+
population = nextPopulation; // replace the reference/generation
85+
}
86+
87+
// With mutationChance probability, mutate each individual
88+
private void mutate() {
89+
for (C individual : population) {
90+
if (random.nextDouble() < mutationChance) {
91+
individual.mutate();
92+
}
93+
}
94+
}
95+
96+
// Run the genetic algorithm for maxGenerations iterations
97+
// and return the best individual found
98+
public C run(int maxGenerations, double threshold) {
99+
C best = Collections.max(population).copy();
100+
for (int generation = 0; generation < maxGenerations; generation++) {
101+
// early exit if we beat threshold
102+
if (best.fitness() >= threshold) {
103+
return best;
104+
}
105+
// Debug printout
106+
System.out.println("Generation " + generation +
107+
" Best " + best.fitness() +
108+
" Avg " + population.stream()
109+
.mapToDouble(C::fitness).average().orElse(0.0));
110+
reproduceAndReplace();
111+
mutate();
112+
C highest = Collections.max(population);
113+
if (highest.fitness() > best.fitness()) {
114+
best = highest.copy();
115+
}
116+
}
117+
return best;
118+
}
119+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package chapter5;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.Random;
7+
8+
public class SendMoreMoney2 extends Chromosome<SendMoreMoney2> {
9+
10+
private List<Character> letters;
11+
private Random random;
12+
13+
public SendMoreMoney2(List<Character> letters) {
14+
this.letters = letters;
15+
random = new Random();
16+
}
17+
18+
public static SendMoreMoney2 randomInstance() {
19+
List<Character> letters = new ArrayList<>(
20+
List.of('S', 'E', 'N', 'D', 'M', 'O', 'R', 'Y', ' ', ' '));
21+
Collections.shuffle(letters);
22+
return new SendMoreMoney2(letters);
23+
}
24+
25+
@Override
26+
public double fitness() {
27+
int s = letters.indexOf('S');
28+
int e = letters.indexOf('E');
29+
int n = letters.indexOf('N');
30+
int d = letters.indexOf('D');
31+
int m = letters.indexOf('M');
32+
int o = letters.indexOf('O');
33+
int r = letters.indexOf('R');
34+
int y = letters.indexOf('Y');
35+
int send = s * 1000 + e * 100 + n * 10 + d;
36+
int more = m * 1000 + o * 100 + r * 10 + e;
37+
int money = m * 10000 + o * 1000 + n * 100 + e * 10 + y;
38+
int difference = Math.abs(money - (send + more));
39+
return 1.0 / (difference + 1.0);
40+
}
41+
42+
@Override
43+
public List<SendMoreMoney2> crossover(SendMoreMoney2 other) {
44+
SendMoreMoney2 child1 = new SendMoreMoney2(new ArrayList<>(letters));
45+
SendMoreMoney2 child2 = new SendMoreMoney2(new ArrayList<>(other.letters));
46+
int idx1 = random.nextInt(letters.size());
47+
int idx2 = random.nextInt(other.letters.size());
48+
Character l1 = letters.get(idx1);
49+
Character l2 = other.letters.get(idx2);
50+
int idx3 = letters.indexOf(l2);
51+
int idx4 = other.letters.indexOf(l1);
52+
Collections.swap(child1.letters, idx1, idx3);
53+
Collections.swap(child2.letters, idx2, idx4);
54+
return List.of(child1, child2);
55+
}
56+
57+
@Override
58+
public void mutate() {
59+
int idx1 = random.nextInt(letters.size());
60+
int idx2 = random.nextInt(letters.size());
61+
Collections.swap(letters, idx1, idx2);
62+
}
63+
64+
@Override
65+
public SendMoreMoney2 copy() {
66+
return new SendMoreMoney2(new ArrayList<>(letters));
67+
}
68+
69+
@Override
70+
public String toString() {
71+
int s = letters.indexOf('S');
72+
int e = letters.indexOf('E');
73+
int n = letters.indexOf('N');
74+
int d = letters.indexOf('D');
75+
int m = letters.indexOf('M');
76+
int o = letters.indexOf('O');
77+
int r = letters.indexOf('R');
78+
int y = letters.indexOf('Y');
79+
int send = s * 1000 + e * 100 + n * 10 + d;
80+
int more = m * 1000 + o * 100 + r * 10 + e;
81+
int money = m * 10000 + o * 1000 + n * 100 + e * 10 + y;
82+
int difference = Math.abs(money - (send + more));
83+
return (send + " + " + more + " = " + money + " Difference: " + difference);
84+
}
85+
86+
public static void main(String[] args) {
87+
ArrayList<SendMoreMoney2> initialPopulation = new ArrayList<>();
88+
for (int i = 0; i < 1000; i++) {
89+
initialPopulation.add(SendMoreMoney2.randomInstance());
90+
}
91+
GeneticAlgorithm<SendMoreMoney2> ga = new GeneticAlgorithm<>(
92+
initialPopulation,
93+
0.2, 0.7, GeneticAlgorithm.SelectionType.ROULETTE);
94+
SendMoreMoney2 result = ga.run(1000, 1.0);
95+
System.out.println(result);
96+
}
97+
98+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package chapter5;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.Random;
6+
7+
public class SimpleEquation extends Chromosome<SimpleEquation> {
8+
private int x, y;
9+
10+
public SimpleEquation(int x, int y) {
11+
this.x = x;
12+
this.y = y;
13+
}
14+
15+
public static SimpleEquation randomInstance() {
16+
Random random = new Random();
17+
return new SimpleEquation(random.nextInt(100), random.nextInt(100));
18+
}
19+
20+
// 6x - x^2 + 4y - y^2
21+
@Override
22+
public double fitness() {
23+
return 6 * x - x * x + 4 * y - y * y;
24+
}
25+
26+
@Override
27+
public List<SimpleEquation> crossover(SimpleEquation other) {
28+
SimpleEquation child1 = new SimpleEquation(x, other.y);
29+
SimpleEquation child2 = new SimpleEquation(other.x, y);
30+
return List.of(child1, child2);
31+
}
32+
33+
@Override
34+
public void mutate() {
35+
Random random = new Random();
36+
if (random.nextDouble() > 0.5) { // mutate x
37+
if (random.nextDouble() > 0.5) {
38+
x += 1;
39+
} else {
40+
x -= 1;
41+
}
42+
} else { // otherwise mutate y
43+
if (random.nextDouble() > 0.5) {
44+
y += 1;
45+
} else {
46+
y -= 1;
47+
}
48+
}
49+
50+
}
51+
52+
@Override
53+
public SimpleEquation copy() {
54+
return new SimpleEquation(x, y);
55+
}
56+
57+
@Override
58+
public String toString() {
59+
return "X: " + x + " Y: " + y + " Fitness: " + fitness();
60+
}
61+
62+
public static void main(String[] args) {
63+
ArrayList<SimpleEquation> initialPopulation = new ArrayList<>();
64+
for (int i = 0; i < 20; i++) {
65+
initialPopulation.add(SimpleEquation.randomInstance());
66+
}
67+
GeneticAlgorithm<SimpleEquation> ga = new GeneticAlgorithm<>(
68+
initialPopulation,
69+
0.1, 0.7, GeneticAlgorithm.SelectionType.TOURNAMENT);
70+
SimpleEquation result = ga.run(100, 13.0);
71+
System.out.println(result);
72+
}
73+
74+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /