GaAlgorithm.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. package holeg.algorithm.binary;
  2. import holeg.api.AlgorithmFrameworkFlex;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.ListIterator;
  6. import java.util.TreeSet;
  7. import javax.swing.JFrame;
  8. public class GaAlgorithm extends AlgorithmFrameworkFlex {
  9. /**
  10. * Should be even.
  11. */
  12. private int popsize = 20;
  13. private int maxGenerations = 100;
  14. private double tournamentSize = 2.0;
  15. private double swapProbability = 0.02;
  16. private double mutateProbability = 0.02;
  17. private boolean useIntervalMutation = false;
  18. //private double mutateProbabilityInterval = 0.01;
  19. private double maxMutationPercent = 0.01;
  20. private boolean moreInformation = false;
  21. public GaAlgorithm() {
  22. super();
  23. addIntParameter("Population size", popsize, intValue -> popsize = intValue, () -> popsize, 1);
  24. addIntParameter("Generations", maxGenerations, intValue -> maxGenerations = intValue,
  25. () -> maxGenerations, 1);
  26. addDoubleParameter("Tournament size", tournamentSize,
  27. doubleValue -> tournamentSize = doubleValue, () -> tournamentSize, 1.0);
  28. addDoubleParameter("Swap probability", swapProbability,
  29. doubleValue -> swapProbability = doubleValue, () -> swapProbability, 0.0, 1.0);
  30. addDoubleParameter("Mutation probability", mutateProbability,
  31. doubleValue -> mutateProbability = doubleValue, () -> mutateProbability, 0.0, 1.0);
  32. addBooleanParameter("Interval-based mutation", useIntervalMutation,
  33. booleanValue -> useIntervalMutation = booleanValue);
  34. //addDoubleParameter("mutateProbabilityInterval", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, 0.0, 1.0);
  35. addDoubleParameter("Mutation severity (% of problem size)", maxMutationPercent,
  36. doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, 0.0, 1.0);
  37. addBooleanParameter("Detailed Information", moreInformation,
  38. booleanValue -> moreInformation = booleanValue);
  39. }
  40. public static void main(String[] args) {
  41. JFrame newFrame = new JFrame("exampleWindow");
  42. GaAlgorithm instance = new GaAlgorithm();
  43. newFrame.setContentPane(instance.getPanel());
  44. newFrame.pack();
  45. newFrame.setVisible(true);
  46. newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  47. }
  48. @Override
  49. protected int getProgressBarMaxCount() {
  50. return this.maxGenerations * this.popsize * this.rounds + rounds;
  51. }
  52. @Override
  53. protected Individual executeAlgo() {
  54. Individual best = new Individual();
  55. best.position = extractPositionAndAccess();
  56. if (moreInformation) {
  57. console.println("Bit-Array_length: " + best.position.size());
  58. }
  59. best.fitness = evaluatePosition(best.position);
  60. List<Double> runList = new ArrayList<Double>();
  61. runList.add(best.fitness);
  62. console.print("Start with: " + best.fitness);
  63. if (moreInformation) {
  64. console.println("");
  65. }
  66. int problemSize = best.position.size();
  67. List<Individual> population = initPopuluationRandom(problemSize, best);
  68. if (moreInformation) {
  69. console.println("Size To Test:" + population.size());
  70. }
  71. for (int generation = 0; generation < maxGenerations; generation++) {
  72. if (moreInformation) {
  73. console.println("Generation" + generation + " start with Fitness: " + best.fitness);
  74. }
  75. for (Individual i : population) {
  76. i.fitness = evaluatePosition(i.position);
  77. if (moreInformation) {
  78. console.println("Fitness" + i.fitness);
  79. }
  80. if (i.fitness < best.fitness) {
  81. best = i;
  82. }
  83. }
  84. runList.add(best.fitness);
  85. List<Individual> childList = new ArrayList<Individual>();
  86. for (int k = 0; k < popsize / 2; k++) {
  87. Individual parentA = selectAParent(population, popsize);
  88. Individual parentB = selectAParent(population, popsize);
  89. Individual childA = new Individual(parentA);
  90. Individual childB = new Individual(parentB);
  91. crossover(childA, childB, problemSize);
  92. if (useIntervalMutation) {
  93. mutateInterval(childA, problemSize);
  94. } else {
  95. mutate(childA, problemSize);
  96. }
  97. if (useIntervalMutation) {
  98. mutateInterval(childB, problemSize);
  99. } else {
  100. mutate(childB, problemSize);
  101. }
  102. childList.add(childA);
  103. childList.add(childB);
  104. }
  105. population = childList;
  106. if (moreInformation) {
  107. console.println("________________");
  108. }
  109. if (cancel) {
  110. return null;
  111. }
  112. }
  113. console.println(" End with:" + best.fitness);
  114. this.runList = runList;
  115. return best;
  116. }
  117. /**
  118. * Algorithm 22 Bit-Flip Mutation.
  119. */
  120. private void mutate(Individual child, int problemSize) {
  121. ListIterator<Boolean> iter = child.position.listIterator();
  122. while (iter.hasNext()) {
  123. boolean boolValue = iter.next();
  124. if (Random.nextDouble() <= this.mutateProbability) {
  125. iter.set(!boolValue);
  126. }
  127. }
  128. }
  129. /**
  130. * Algorithm rolf
  131. */
  132. private void mutateInterval(Individual child, int problemSize) {
  133. //If not mutate skip
  134. if (Random.nextDouble() > this.mutateProbability) {
  135. return;
  136. }
  137. //println("problemSize:" + problemSize + " maxMutationPercent:" + maxMutationPercent);
  138. int maximumAmountOfMutatedBits = Math.max(1,
  139. (int) Math.round(((double) problemSize) * this.maxMutationPercent));
  140. int randomUniformAmountOfMutatedValues = Random.nextIntegerInRange(1,
  141. maximumAmountOfMutatedBits + 1);
  142. //println("max:" + maximumAmountOfMutatedBits + " actual:" + randomUniformAmountOfMutatedValues);
  143. TreeSet<Integer> mutationLocation = new TreeSet<Integer>(); //sortedSet
  144. //Choose the location to mutate
  145. for (int i = 0; i < randomUniformAmountOfMutatedValues; i++) {
  146. boolean success = mutationLocation.add(Random.nextIntegerInRange(0, problemSize));
  147. if (!success) {
  148. i--; //can be add up to some series long loops if maximumAmountOfMutatedBits get closed to problemsize.
  149. }
  150. }
  151. //println("Set:" + mutationLocation);
  152. ListIterator<Boolean> iter = child.position.listIterator();
  153. if (mutationLocation.isEmpty()) {
  154. return;
  155. }
  156. int firstindex = mutationLocation.pollFirst();
  157. while (iter.hasNext()) {
  158. int index = iter.nextIndex();
  159. boolean boolValue = iter.next();
  160. if (index == firstindex) {
  161. iter.set(!boolValue);
  162. if (mutationLocation.isEmpty()) {
  163. break;
  164. }
  165. firstindex = mutationLocation.pollFirst();
  166. }
  167. }
  168. }
  169. /**
  170. * Algorithm 25 Uniform Crossover. Probability is set to 1/Problemsize when not changed.
  171. */
  172. private void crossover(Individual childA, Individual childB, int problemSize) {
  173. ListIterator<Boolean> iterA = childA.position.listIterator();
  174. ListIterator<Boolean> iterB = childB.position.listIterator();
  175. for (int i = 0; i < problemSize; i++) {
  176. boolean boolA = iterA.next();
  177. boolean boolB = iterB.next();
  178. if (Random.nextDouble() <= this.swapProbability) {
  179. //Swap
  180. iterA.set(boolB);
  181. iterB.set(boolA);
  182. }
  183. }
  184. }
  185. /**
  186. * Algorithm 32 Tournament Selection. The fitnessValues are calculated for the Population List.
  187. * PseudoCode
  188. */
  189. private Individual selectAParent(List<Individual> population, int popsize) {
  190. Individual tournamentBest = population.get(Random.nextIntegerInRange(0, popsize));
  191. double participants;
  192. for (participants = tournamentSize; participants >= 2; participants -= 1.0) {
  193. Individual next = population.get(Random.nextIntegerInRange(0, popsize));
  194. if (next.fitness < tournamentBest.fitness) {
  195. tournamentBest = next;
  196. }
  197. }
  198. //if tournament size is not a whole number like 2.5 or 3.6
  199. //the remaining part is the chance to fight another time; 2.7 -> 70% chance to fight a second time
  200. if (participants > 1) {
  201. if (Random.nextDouble() < participants - 1.0) {
  202. //println("Chance to find a match");
  203. Individual next = population.get(Random.nextIntegerInRange(0, popsize));
  204. if (next.fitness < tournamentBest.fitness) {
  205. tournamentBest = next;
  206. }
  207. }
  208. }
  209. return tournamentBest;
  210. }
  211. /**
  212. * Initialize the Population with Individuals that have a random Position.
  213. */
  214. private List<Individual> initPopuluationRandom(int problemSize, Individual startIndidual) {
  215. List<Individual> population = new ArrayList<Individual>();
  216. for (int i = 0; i < popsize - 1; i++) {
  217. population.add(createRandomIndividualWithoutFitness(problemSize));
  218. }
  219. //Add Start Position
  220. population.add(new Individual(startIndidual));
  221. return population;
  222. }
  223. /**
  224. * Algorithm 21 The BooleanVeator initialization.
  225. *
  226. * @param problemSize
  227. * @return
  228. */
  229. private Individual createRandomIndividualWithoutFitness(int problemSize) {
  230. //create Random Individual Without Fitness
  231. Individual result = new Individual();
  232. result.position = new ArrayList<Boolean>();
  233. for (int index = 0; index < problemSize; index++) {
  234. result.position.add(Random.nextBoolean());
  235. }
  236. return result;
  237. }
  238. @Override
  239. protected String algoInformationToPrint() {
  240. // private int popsize = 20;
  241. // private int maxGenerations = 100;
  242. // private double tournamentSize = 2.0;
  243. // private double fixedSwapProbability = 0.02;
  244. // private boolean useFixedSpawProbability = false;
  245. // private double fixedMutateProbability = 0.02;
  246. // private boolean useFixedMutateProbability = false;
  247. // private boolean useIntervalMutation = true;
  248. // private double mutateProbabilityInterval = 0.01;
  249. // private double maxMutationPercent = 0.01;
  250. return "GaAlgo"
  251. + " Rounds: " + rounds
  252. + " Iterations: " + maxGenerations
  253. + " Individuals: " + popsize
  254. + " TournamentSize: " + tournamentSize
  255. + " SwapProbability: " + swapProbability
  256. + (useIntervalMutation ?
  257. (//" MutateProbabilityInterval: " + mutateProbabilityInterval
  258. " MaxMutationPercent: " + maxMutationPercent)
  259. :
  260. (" MutateProbability: " + mutateProbability));
  261. }
  262. @Override
  263. protected String plottFileName() {
  264. return "plottGaAlgo.txt";
  265. }
  266. }