PsoAlgorithm.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. package algorithm.topologie;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.LinkedList;
  6. import java.util.List;
  7. import java.util.ListIterator;
  8. import java.util.TreeSet;
  9. import java.util.stream.Collectors;
  10. import algorithm.objectiveFunction.ObjectiveFunctionByCarlos;
  11. import algorithm.objectiveFunction.TopologieObjectiveFunction;
  12. import api.TopologieAlgorithmFramework;
  13. import api.AlgorithmFrameworkFlex.Individual;
  14. import api.TopologieAlgorithmFramework.IndexCable;
  15. import ui.model.DecoratedState;
  16. import utility.Random;
  17. public class PsoAlgorithm extends TopologieAlgorithmFramework {
  18. private int popsize = 20;
  19. private int maxGenerations = 500;
  20. private double dependency = 2.07;
  21. private double c1, c2, w;
  22. private double maxVelocity = 10.0;
  23. private double deviation = 0.5;
  24. //mutation
  25. private int mutationInterval = 1;
  26. private boolean useIntervalMutation = false;
  27. private double mutationRate = 0.005;
  28. private double mutateProbabilityInterval = 0.01;
  29. private double maxMutationPercent = 0.01;
  30. private boolean moreInformation = false;
  31. public PsoAlgorithm(){
  32. addIntParameter("Swarmsize", popsize, intValue -> popsize = intValue, () -> popsize, 1);
  33. addIntParameter("Iterations", maxGenerations, intValue -> maxGenerations = intValue, () -> maxGenerations, 1);
  34. addSeperator();
  35. addDoubleParameter("Deviation", deviation, doubleValue -> deviation = doubleValue, () -> deviation, 0);
  36. addDoubleParameter("Dependency", dependency, doubleValue -> dependency = doubleValue, () -> dependency, true, 2.001, 2.4);
  37. addDoubleParameter("Particle Max-Velocity", maxVelocity, doubleValue -> maxVelocity = doubleValue, () -> maxVelocity, 0.0);
  38. addSeperator();
  39. addIntParameter("Mutation Frequency (Iteration)", mutationInterval, intValue -> mutationInterval = intValue, () -> mutationInterval, 0);
  40. addBooleanParameter("Use Interval Mutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue, Arrays.asList("Probability for Frequency Mutation", "Scope of Mutation"), Arrays.asList("Probability for Bit-wise Mutation"));
  41. addDoubleParameter("Probability for Frequency Mutation", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, () -> mutateProbabilityInterval, useIntervalMutation, 0.0, 1.0);
  42. addDoubleParameter("Probability for Bit-wise Mutation", mutationRate, doubleValue -> mutationRate = doubleValue, () -> mutationRate, !useIntervalMutation, 0.0, 1.0);
  43. addDoubleParameter("Scope of Mutation", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, () -> maxMutationPercent, useIntervalMutation, 0.0, 1.0);
  44. addSeperator();
  45. addBooleanParameter("Print Auxiliary Information", moreInformation, booleanValue -> moreInformation = booleanValue, new LinkedList<String>(), new LinkedList<String>());
  46. }
  47. public static double linearInterpolate(double first, double second, double alpha) {
  48. return first * (1.0 - alpha) + second * alpha;
  49. }
  50. public static double inverseLinearInterpolation(double min, double max, double value) {
  51. if (max - min == 0) return max;
  52. else return (value - min) / (max - min);
  53. }
  54. @Override
  55. protected double evaluateState(DecoratedState actualstate, int amountOfAddedSwitch, double addedCableMeters, boolean moreInformation) {
  56. return TopologieObjectiveFunction.getFitnessValueForState(actualstate, amountOfAddedSwitch, addedCableMeters, moreInformation);
  57. }
  58. @Override
  59. /**
  60. * <p>Algo from Paper:</p><font size="3"><pre>
  61. *
  62. * Begin
  63. * t = 0; {t: generation index}
  64. * initialize particles x<sub>p,i,j</sub>(t);
  65. * evaluation x<sub>p,i,j</sub>(t);
  66. * while (termination condition &ne; true) do
  67. * v<sub>i,j</sub>(t) = update v<sub>i,j</sub>(t); {by Eq. (6)}
  68. * x<sub>g,i,j</sub>(t) = update x<sub>g,i,j</sub>(t); {by Eq. (7)}
  69. * x<sub>g,i,j</sub>(t) = mutation x<sub>g,i,j</sub>(t); {by Eq. (11)}
  70. * x<sub>p,i,j</sub>(t) = decode x<sub>g,i,j</sub>(t); {by Eqs. (8) and (9)}
  71. * evaluate x<sub>p,i,j</sub>(t);
  72. * t = t + 1;
  73. * end while
  74. * End</pre></font>
  75. * <p>with:</p><font size="3">
  76. *
  77. * x<sub>g,i,j</sub>: genotype ->genetic information -> in continuous space<br>
  78. * x<sub>p,i,j</sub>: phenotype -> observable characteristics-> in binary space<br>
  79. * X<sub>g,max</sub>: is the Maximum here set to 4.<br>
  80. * Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
  81. * Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
  82. * Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
  83. * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
  84. * Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
  85. * <p>Parameter:</p>
  86. * w inertia, calculated from phi(Variable:{@link #dependency})<br>
  87. * c1: influence, calculated from phi(Variable:{@link #dependency}) <br>
  88. * c2: influence, calculated from phi(Variable:{@link #dependency})<br>
  89. * r<sub>mu</sub>: probability that the proposed operation is conducted defined by limit(Variable:{@link #limit})<br>
  90. *
  91. *
  92. */
  93. protected Individual executeAlgo() {
  94. resetWildcards();
  95. initDependentParameter();
  96. Individual globalBest = new Individual();
  97. globalBest.position = extractPositionAndAccess();
  98. globalBest.fitness = evaluatePosition(globalBest.position);
  99. console.println("Start Value:" + globalBest.fitness);
  100. int dimensions = globalBest.position.size();
  101. List<Particle> swarm= initializeParticles(dimensions);
  102. List<Double> runList = new ArrayList<Double>();
  103. runList.add(globalBest.fitness);
  104. evaluation(globalBest, swarm);
  105. runList.add(globalBest.fitness);
  106. for (int iteration = 0; iteration < this.maxGenerations ; iteration++) {
  107. int mutationAllowed = iteration % mutationInterval;
  108. double bitsFlipped = 0;
  109. for (int particleNumber = 0; particleNumber < this.popsize; particleNumber++) {
  110. Particle particle = swarm.get(particleNumber);
  111. if(this.useIntervalMutation) {
  112. boolean allowMutation = (Random.nextDouble() < this.mutateProbabilityInterval);
  113. TreeSet<Integer> mutationLocationSet = null;
  114. if(allowMutation)mutationLocationSet = locationsToMutate(dimensions);
  115. for(int index = 0; index < dimensions; index++) {
  116. updateVelocity(particle, index, globalBest);
  117. updateGenotype(particle, index);
  118. if(allowMutation &&mutationAllowed == 0 && iteration != 0 && mutationLocationSet.contains(index))mutation(particle, index);
  119. decode(particle, index);
  120. }
  121. }else {
  122. int count = 0;
  123. for(int index = 0; index < dimensions; index++) {
  124. updateVelocity(particle, index, globalBest);
  125. updateGenotype(particle, index);
  126. if(mutationAllowed == 0 && iteration != 0 && Random.nextDouble() < mutationRate) {
  127. count++;
  128. mutation(particle, index);
  129. }
  130. decode(particle, index);
  131. }
  132. bitsFlipped += count;
  133. }
  134. }
  135. if(moreInformation) console.println("\t\t\t\t\t\tAvgBitsMutate: " + (bitsFlipped / (double)popsize));
  136. if(cancel)return null;
  137. evaluation(globalBest, swarm);
  138. runList.add(globalBest.fitness);
  139. if(moreInformation) console.println("------------------------");
  140. }
  141. console.println(" End Value:" + globalBest.fitness);
  142. this.runList = runList;
  143. return globalBest;
  144. }
  145. @Override
  146. protected int getProgressBarMaxCount() {
  147. return rounds * maxGenerations * popsize + 1;
  148. }
  149. @Override
  150. protected String algoInformationToPrint() {
  151. return "PsoAlgo"+ " Rounds:" + rounds
  152. + " maxIterations:" + maxGenerations
  153. + " swarmSize:" + popsize
  154. + " dependency:" + dependency
  155. + " mutationInterval:" + mutationInterval
  156. + " maxVelocity: " + maxVelocity
  157. + " deviation: " + deviation
  158. + (useIntervalMutation?
  159. (" mutateProbabilityInterval:" + mutateProbabilityInterval
  160. + " maxMutationPercent:" + maxMutationPercent) : " mutationRate:" + mutationRate);
  161. }
  162. @Override
  163. protected String plottFileName() {
  164. return "pso-topologie.txt";
  165. }
  166. /**
  167. *
  168. * @param problemSize maximum index of position in the particle
  169. * @return
  170. */
  171. private List<Particle> initializeParticles(int problemSize) {
  172. List<Particle> swarm = new ArrayList<Particle>();
  173. //Create The Particle
  174. for (int particleNumber = 0; particleNumber < popsize; particleNumber++){
  175. //Create a Random position
  176. List<Integer> aRandomPosition = new ArrayList<Integer>();
  177. for (int index = 0; index < problemSize; index++){
  178. aRandomPosition.add(Random.nextIntegerInRange(0, this.getMaximumIndexObjects(index) + 1));
  179. }
  180. swarm.add(new Particle(aRandomPosition));
  181. }
  182. return swarm;
  183. }
  184. /**
  185. * Calculate w, c1, c2
  186. */
  187. private void initDependentParameter() {
  188. w = 1.0 / (dependency - 1 + Math.sqrt(dependency * dependency - 2 * dependency));
  189. c1 = c2 = dependency * w;
  190. }
  191. /**
  192. * Evaluate each particle and update the global Best position;
  193. * @param globalBest
  194. * @param swarm
  195. */
  196. private void evaluation(Individual globalBest, List<Particle> swarm) {
  197. for(Particle p: swarm) {
  198. double localEvaluationValue = evaluatePosition(p.xPhenotype);
  199. if(moreInformation) console.println("Fitness " + localEvaluationValue);
  200. p.checkNewEvaluationValue(localEvaluationValue);
  201. if(localEvaluationValue < globalBest.fitness) {
  202. globalBest.fitness = localEvaluationValue;
  203. globalBest.position = p.localBest.position;
  204. }
  205. }
  206. }
  207. /**
  208. * Eq. (6):v<sub>i,j</sub>(t + 1) = wv<sub>i,j</sub>+c<sub>1</sub>R<sub>1</sub>(P<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))+c<sub>2</sub>R<sub>2</sub>(g<sub>best,i,j</sub>-x<sub>p,i,j</sub>(t))<br>
  209. * @param particle
  210. * @param index
  211. * @param globalBest
  212. */
  213. private void updateVelocity(Particle particle, int index, Individual globalBest) {
  214. double r1 = Random.nextDouble();
  215. double r2 = Random.nextDouble();
  216. double posValue = particle.xPhenotype.get(index);
  217. particle.velocity.set(index, clamp(w*particle.velocity.get(index) + c1*r1*((particle.localBest.position.get(index)) - posValue) + c2*r2*((globalBest.position.get(index))- posValue)) );
  218. }
  219. /**
  220. * Eq. (7):x<sub>g,i,j</sub>(t + 1) = x<sub>g,i,j</sub>(t) + v<sub>i,j</sub>(t + 1)<br>
  221. * @param particle
  222. * @param index
  223. */
  224. private void updateGenotype(Particle particle, int index) {
  225. particle.xGenotype.set(index, clamp(particle.xGenotype.get(index) + particle.velocity.get(index)));
  226. }
  227. /**
  228. * Eq. (11):<b>if(</b>rand()&lt;r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
  229. * @param particle
  230. * @param index
  231. */
  232. private void mutation(Particle particle, int index) {
  233. //if(Random.nextDouble() < limit)
  234. particle.xGenotype.set(index, -particle.xGenotype.get(index));
  235. }
  236. /**
  237. * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() &lt; S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
  238. * @param particle
  239. * @param index
  240. */
  241. private void decode(Particle particle, int index) {
  242. double value = clamp(Random.nextGaussian(particle.xGenotype.get(index), deviation));
  243. double alpha = inverseLinearInterpolation(-maxVelocity, +maxVelocity, value);
  244. double result = linearInterpolate(0, this.getMaximumIndexObjects(index), alpha);
  245. particle.xPhenotype.set(index, (int)Math.round(result));
  246. }
  247. /**
  248. * Eq. (9) Sigmoid:S(x<sub>g,i,j</sub>(t + 1)) := 1/(1 + e<sup>-x<sub>g,i,j</sub>(t + 1)</sup>)<br></font>
  249. * @param value
  250. * @return
  251. */
  252. private double Sigmoid(double value) {
  253. return 1.0 / (1.0 + Math.exp(-value));
  254. }
  255. /**
  256. * To clamp X<sub>g,j,i</sub> and v<sub>i,j</sub> in Range [-X<sub>g,max</sub>|+X<sub>g,max</sub>] with {X<sub>g,max</sub>= 4}
  257. * @param value
  258. * @return
  259. */
  260. private double clamp(double value) {
  261. return Math.max(-maxVelocity, Math.min(maxVelocity, value));
  262. }
  263. private TreeSet<Integer> locationsToMutate(int dimensions) {
  264. TreeSet<Integer> mutationLocation = new TreeSet<Integer>(); //sortedSet
  265. int maximumAmountOfMutatedBits = Math.max(1, (int)Math.round(((double) dimensions) * this.maxMutationPercent));
  266. int randomUniformAmountOfMutatedValues = Random.nextIntegerInRange(1,maximumAmountOfMutatedBits + 1);
  267. for(int i = 0; i< randomUniformAmountOfMutatedValues; i++) {
  268. boolean success = mutationLocation.add(Random.nextIntegerInRange(0, dimensions));
  269. if(!success) i--; //can be add up to some series long loops if maximumAmountOfMutatedBits get closed to problemsize.
  270. }
  271. return mutationLocation;
  272. }
  273. /**
  274. * Class to represent a Particle.
  275. */
  276. private class Particle{
  277. /**
  278. * The velocity of a particle.
  279. */
  280. public List<Double> velocity;
  281. /**
  282. * The positions genotype.
  283. */
  284. public List<Double> xGenotype;
  285. /**
  286. * The positions phenotype. Alias the current position.
  287. */
  288. public List<Integer> xPhenotype;
  289. public Individual localBest;
  290. Particle(List<Integer> position){
  291. this.xPhenotype = position;
  292. //Init velocity, xGenotype with 0.0 values.
  293. this.velocity = position.stream().map(bool -> 0.0).collect(Collectors.toList());
  294. this.xGenotype = position.stream().map(bool -> 0.0).collect(Collectors.toList());
  295. localBest = new Individual();
  296. localBest.fitness = Double.MAX_VALUE;
  297. }
  298. public void checkNewEvaluationValue(double newEvaluationValue) {
  299. if(newEvaluationValue < localBest.fitness) {
  300. localBest.fitness = newEvaluationValue;
  301. localBest.position = xPhenotype.stream().collect(Collectors.toList());
  302. }
  303. }
  304. public String toString() {
  305. return "Particle with xPhenotype(Position), xGenotype, velocity:["
  306. + listToString(xPhenotype) + "],[" + listToString(xGenotype) + "],["
  307. + listToString(velocity) + "]";
  308. }
  309. private <Type> String listToString(List<Type> list) {
  310. return list.stream().map(Object::toString).collect(Collectors.joining(", "));
  311. }
  312. }
  313. }