|
5 | 5 | import java.util.Random; |
6 | 6 |
|
7 | 7 | public class GenerationAlgorithm { |
8 | | - public final int POPULATION; |
9 | | - public final int NUMBER_OF_GENERATIONS = 10; |
| 8 | + public final int POPULATION; |
| 9 | + public final int NUMBER_OF_GENERATIONS = 10; |
10 | 10 | public final double MUTATION_CHANCE = 0.1; |
11 | | - public final int ELITISM_NUMBER = 5; |
12 | | - public final int NUMBER_OF_GENERATIONS_PER_INCREASE = 10; |
| 11 | + public final int MAX_MUTATION_COUNT = 5; |
| 12 | + public final int ELITISM_NUMBER = 2; |
| 13 | + public final int NUMBER_OF_GENERATIONS_PER_INCREASE = 10; |
13 | 14 | static Random rand = new Random(0); |
14 | | - int[] eliteIndexes = new int[ELITISM_NUMBER]; |
| 15 | + ArrayList<Integer> eliteIndexes = new ArrayList<Integer>(); |
15 | 16 | int generationNumber = 0; |
16 | | - boolean sessionStarted = false; |
| 17 | + int instructionSize = 20; |
17 | 18 | Agent[] agents; |
| 19 | + |
18 | 20 | public GenerationAlgorithm(Agent[] agents){ |
19 | 21 | this.agents = agents; |
20 | 22 | this.POPULATION = agents.length; |
21 | 23 | createPopulation(); |
22 | 24 | } |
23 | 25 | public void checkGeneration(){ |
24 | | - if(agents[agents.length-1].isFinished && !sessionStarted){ |
25 | | - getFitness(); |
| 26 | + if(agents[agents.length-1].isFinished){ |
| 27 | + ArrayList<Double> fitnesses = getFitness(); |
| 28 | + ArrayList<Double> weights = getWeights(fitnesses); |
| 29 | + ArrayList<Integer[]> parentsList = getParents(weights); |
| 30 | + for (Integer[] integers : parentsList) { |
| 31 | + System.out.println(Arrays.toString(integers)); |
| 32 | + } |
| 33 | + System.out.printf("Generation completed number: %d\n",generationNumber); |
| 34 | + crossOver(parentsList); |
26 | 35 | for(Agent agent : agents){ |
27 | 36 | agent.reset(); |
28 | 37 | } |
29 | | - sessionStarted = true; |
30 | 38 | generationNumber++; |
31 | 39 | } |
32 | 40 | } |
33 | 41 | public void createPopulation(){ |
34 | 42 | for (Agent agent : agents) { |
35 | | - assignRandomInstructions(agent,20); |
| 43 | + assignRandomInstructions(agent,instructionSize); |
36 | 44 | } |
37 | 45 | } |
38 | 46 | public void assignRandomInstructions(Agent agent,int size){ |
39 | 47 | for(int i = 0; i<size;i++){ |
40 | 48 | agent.instructions.add(rand.nextInt(5)); |
41 | 49 | } |
42 | 50 | } |
43 | | - public ArrayList<Integer> getFitness(){ |
44 | | - ArrayList<Integer> fitness = new ArrayList<>(); |
| 51 | + public ArrayList<Double> getFitness(){ |
| 52 | + ArrayList<Double> fitness = new ArrayList<>(); |
45 | 53 | for (Agent agent : agents) { |
46 | 54 | fitness.add(agent.getPoints()); |
47 | 55 | } |
48 | | - ArrayList<Integer> fitnessCopy = new ArrayList<>(fitness); |
| 56 | + ArrayList<Double> fitnessCopy = new ArrayList<>(fitness); |
49 | 57 | Collections.sort(fitnessCopy, Collections.reverseOrder(null)); |
50 | 58 | for(int i = 0; i<ELITISM_NUMBER;i++){ |
51 | | - eliteIndexes[i] = fitness.indexOf(fitnessCopy.get(i)); |
| 59 | + eliteIndexes.add(fitness.indexOf(fitnessCopy.get(i))); |
52 | 60 | } |
53 | | - System.out.println(fitness.toString()); |
54 | | - System.out.println(Arrays.toString(eliteIndexes)); |
55 | 61 | return fitness; |
56 | 62 | } |
57 | | - |
| 63 | + public ArrayList<Double> getWeights(ArrayList<Double> fitness){ |
| 64 | + double sum = 0; |
| 65 | + ArrayList<Double> weights = new ArrayList<Double>(); |
| 66 | + for (double d : fitness) { |
| 67 | + sum += Math.exp(d); |
| 68 | + } |
| 69 | + for (int i = 0; i<fitness.size();i++) { |
| 70 | + double softMaxed = Math.exp(fitness.get(i))/sum; |
| 71 | + weights.add(softMaxed); |
| 72 | + } |
| 73 | + return weights; |
| 74 | + } |
| 75 | + public ArrayList<Integer[]> getParents(ArrayList<Double> weights){ |
| 76 | + ArrayList<Integer[]> parentsList = new ArrayList<Integer[]>(); |
| 77 | + double totalWeight = 0.0; //in case the sum of weights is not 1 |
| 78 | + for (double i : weights) { |
| 79 | + totalWeight += i; |
| 80 | + } |
| 81 | + for(int i = 0; i<weights.size(); i++){ |
| 82 | + Integer[] parents = new Integer[2]; |
| 83 | + for(int j = 0; j<2;j++){ |
| 84 | + int idx = 0; |
| 85 | + for (double r = Math.random() * totalWeight; idx < weights.size() - 1; ++idx) { |
| 86 | + r -= weights.get(idx); |
| 87 | + if (r <= 0.0) break; |
| 88 | + } |
| 89 | + parents[j] = idx; |
| 90 | + } |
| 91 | + parentsList.add(parents); |
| 92 | + } |
| 93 | + return parentsList; |
| 94 | + } |
| 95 | + public void crossOver(ArrayList<Integer[]> parents){ |
| 96 | + ArrayList<ArrayList<Integer>> instructionsTemp = new ArrayList<ArrayList<Integer>>(); |
| 97 | + for(int i = 0; i<POPULATION; i++){ |
| 98 | + instructionsTemp.add(agents[i].instructions); |
| 99 | + } |
| 100 | + for (int i = 0; i<parents.size();i++) { |
| 101 | + Integer[] parentPair = parents.get(i); |
| 102 | + if(eliteIndexes.contains(parentPair[0])){ |
| 103 | + continue; |
| 104 | + } |
| 105 | + if(parentPair[0] != parentPair[1]){ |
| 106 | + int crossOverLength = rand.nextInt(10); |
| 107 | + int indexOfCrossing = rand.nextInt(agents[parentPair[0]].instructions.size()-crossOverLength); |
| 108 | + for(int j = indexOfCrossing; j<indexOfCrossing+crossOverLength;j++){ |
| 109 | + agents[parentPair[0]].instructions.set(j,instructionsTemp.get(parentPair[1]).get(j)); |
| 110 | + } |
| 111 | + } |
| 112 | + if(Math.random()<MUTATION_CHANCE){ |
| 113 | + int numberOfMutations = rand.nextInt(MAX_MUTATION_COUNT); |
| 114 | + for(int m = 0; m<numberOfMutations;m++){ |
| 115 | + int randomInstructionIndex = rand.nextInt(agents[parentPair[0]].instructions.size()); |
| 116 | + agents[parentPair[0]].instructions.set(randomInstructionIndex,rand.nextInt(5)); //randomize instructions |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + } |
| 121 | + } |
58 | 122 | } |
0 commit comments