PsoAlgorithm.java 14 KB

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