|
@@ -0,0 +1,323 @@
|
|
|
+package exampleAlgorithms;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.TreeSet;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import javax.swing.JFrame;
|
|
|
+
|
|
|
+import api.AlgorithmFramework;
|
|
|
+import ui.model.DecoratedState;
|
|
|
+
|
|
|
+public class PsoAlgorithm2 extends AlgorithmFramework{
|
|
|
+
|
|
|
+ private int swarmSize = 20;
|
|
|
+ private int maxIterations = 100;
|
|
|
+ private double limit = 0.01;
|
|
|
+ private double dependency = 2.07;
|
|
|
+ private int mutationInterval = 1;
|
|
|
+ private boolean useIntervalMutation = true;
|
|
|
+ private double mutateProbabilityInterval = 0.01;
|
|
|
+ private double maxMutationPercent = 0.01;
|
|
|
+ private double c1, c2, w;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public static void main(String[] args)
|
|
|
+ {
|
|
|
+ JFrame newFrame = new JFrame("exampleWindow");
|
|
|
+ PsoAlgorithm2 instance = new PsoAlgorithm2();
|
|
|
+ newFrame.setContentPane(instance.getPanel());
|
|
|
+ newFrame.pack();
|
|
|
+ newFrame.setVisible(true);
|
|
|
+ newFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public PsoAlgorithm2() {
|
|
|
+ super();
|
|
|
+ addIntParameter("swarmSize", swarmSize, intValue -> swarmSize = intValue, 1);
|
|
|
+ addIntParameter("maxIterations", maxIterations, intValue -> maxIterations = intValue, 1);
|
|
|
+ addIntParameter("mutationInterval", mutationInterval, intValue -> mutationInterval = intValue, 0);
|
|
|
+ addDoubleParameter("dependency", dependency, doubleValue -> dependency = doubleValue, 2.001, 2.4);
|
|
|
+ addDoubleParameter("limit", limit, doubleValue -> limit = doubleValue, 0.0, 1.0);
|
|
|
+ addBooleanParameter("useIntervalMutation", useIntervalMutation, booleanValue -> useIntervalMutation = booleanValue);
|
|
|
+ addDoubleParameter("mutateProbabilityInterval", mutateProbabilityInterval, doubleValue -> mutateProbabilityInterval = doubleValue, 0.0, 1.0);
|
|
|
+ addDoubleParameter("maxMutationPercent", maxMutationPercent, doubleValue -> maxMutationPercent = doubleValue, 0.0, 1.0);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected double evaluateState(DecoratedState actualstate) {
|
|
|
+ return Evaluation.getFitnessValueForState(actualstate);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected int getProgressBarMaxCount() {
|
|
|
+ return swarmSize * (maxIterations + 1)* rounds + rounds;
|
|
|
+ }
|
|
|
+
|
|
|
+ * <p>Algo from Paper:</p><font size="3"><pre>
|
|
|
+ *
|
|
|
+ * Begin
|
|
|
+ * t = 0; {t: generation index}
|
|
|
+ * initialize particles x<sub>p,i,j</sub>(t);
|
|
|
+ * evaluation x<sub>p,i,j</sub>(t);
|
|
|
+ * while (termination condition ≠ true) do
|
|
|
+ * v<sub>i,j</sub>(t) = update v<sub>i,j</sub>(t); {by Eq. (6)}
|
|
|
+ * x<sub>g,i,j</sub>(t) = update x<sub>g,i,j</sub>(t); {by Eq. (7)}
|
|
|
+ * x<sub>g,i,j</sub>(t) = mutation x<sub>g,i,j</sub>(t); {by Eq. (11)}
|
|
|
+ * x<sub>p,i,j</sub>(t) = decode x<sub>g,i,j</sub>(t); {by Eqs. (8) and (9)}
|
|
|
+ * evaluate x<sub>p,i,j</sub>(t);
|
|
|
+ * t = t + 1;
|
|
|
+ * end while
|
|
|
+ * End</pre></font>
|
|
|
+ * <p>with:</p><font size="3">
|
|
|
+ *
|
|
|
+ * x<sub>g,i,j</sub>: genotype ->genetic information -> in continuous space<br>
|
|
|
+ * x<sub>p,i,j</sub>: phenotype -> observable characteristics-> in binary space<br>
|
|
|
+ * X<sub>g,max</sub>: is the Maximum here set to 4.<br>
|
|
|
+ * 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>
|
|
|
+ * 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>
|
|
|
+ * Eq. (11):<b>if(</b>rand()<r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
|
|
|
+ * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() < S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
|
|
|
+ * 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>
|
|
|
+ * <p>Parameter:</p>
|
|
|
+ * w inertia, calculated from phi(Variable:{@link #dependency})<br>
|
|
|
+ * c1: influence, calculated from phi(Variable:{@link #dependency}) <br>
|
|
|
+ * c2: influence, calculated from phi(Variable:{@link #dependency})<br>
|
|
|
+ * r<sub>mu</sub>: probability that the proposed operation is conducted defined by limit(Variable:{@link #limit})<br>
|
|
|
+ *
|
|
|
+ *
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ protected Individual executeAlgo() {
|
|
|
+ initDependentParameter();
|
|
|
+ Individual globalBest = new Individual();
|
|
|
+ globalBest.position = extractPositionAndAccess();
|
|
|
+ globalBest.fitness = evaluatePosition(globalBest.position);
|
|
|
+ console.println("Start Value:" + globalBest.fitness);
|
|
|
+ int dimensions = globalBest.position.size();
|
|
|
+ List<Particle> swarm= initializeParticles(dimensions);
|
|
|
+ List<Double> runList = new ArrayList<Double>();
|
|
|
+ runList.add(globalBest.fitness);
|
|
|
+ evaluation(globalBest, swarm);
|
|
|
+ runList.add(globalBest.fitness);
|
|
|
+ for (int iteration = 0; iteration < maxIterations ; iteration++) {
|
|
|
+ int mutationAllowed = iteration % mutationInterval;
|
|
|
+ for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++) {
|
|
|
+ Particle particle = swarm.get(particleNumber);
|
|
|
+
|
|
|
+ if(this.useIntervalMutation) {
|
|
|
+ boolean allowMutation = (Random.nextDouble() < this.mutateProbabilityInterval);
|
|
|
+ TreeSet<Integer> mutationLocation = null;
|
|
|
+ if(allowMutation)mutationLocation = locationsToMutate(dimensions);
|
|
|
+ for(int index = 0; index < dimensions; index++) {
|
|
|
+ updateVelocity(particle, index, globalBest);
|
|
|
+ updateGenotype(particle, index);
|
|
|
+ if(allowMutation &&mutationAllowed == 0 && iteration != 0 && mutationLocation.contains(index))mutation(particle, index);
|
|
|
+ decode(particle, index);
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ for(int index = 0; index < dimensions; index++) {
|
|
|
+ updateVelocity(particle, index, globalBest);
|
|
|
+ updateGenotype(particle, index);
|
|
|
+ if(mutationAllowed == 0 && iteration != 0)mutation(particle, index);
|
|
|
+ decode(particle, index);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(cancel)return null;
|
|
|
+ evaluation(globalBest, swarm);
|
|
|
+ runList.add(globalBest.fitness);
|
|
|
+ }
|
|
|
+ console.println(" End Value:" + globalBest.fitness);
|
|
|
+ db.insertNewRun(runList);
|
|
|
+ return globalBest;
|
|
|
+ }
|
|
|
+
|
|
|
+ *
|
|
|
+ * @param j maximum index of position in the particle
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<Particle> initializeParticles(int j) {
|
|
|
+ List<Particle> swarm = new ArrayList<Particle>();
|
|
|
+
|
|
|
+ for (int particleNumber = 0; particleNumber < swarmSize; particleNumber++){
|
|
|
+
|
|
|
+ List<Boolean> aRandomPosition = new ArrayList<Boolean>();
|
|
|
+ for (int index = 0; index < j; index++){
|
|
|
+ aRandomPosition.add(Random.nextBoolean());
|
|
|
+ }
|
|
|
+ swarm.add(new Particle(aRandomPosition));
|
|
|
+ }
|
|
|
+ return swarm;
|
|
|
+ }
|
|
|
+
|
|
|
+ * Calculate w, c1, c2
|
|
|
+ */
|
|
|
+ private void initDependentParameter() {
|
|
|
+ w = 1.0 / (dependency - 1 + Math.sqrt(dependency * dependency - 2 * dependency));
|
|
|
+ c1 = c2 = dependency * w;
|
|
|
+ }
|
|
|
+
|
|
|
+ * Evaluate each particle and update the global Best position;
|
|
|
+ * @param globalBest
|
|
|
+ * @param swarm
|
|
|
+ */
|
|
|
+ private void evaluation(Individual globalBest, List<Particle> swarm) {
|
|
|
+ for(Particle p: swarm) {
|
|
|
+ double localEvaluationValue = evaluatePosition(p.xPhenotype);
|
|
|
+ p.checkNewEvaluationValue(localEvaluationValue);
|
|
|
+ if(localEvaluationValue < globalBest.fitness) {
|
|
|
+ globalBest.fitness = localEvaluationValue;
|
|
|
+ globalBest.position = p.localBest.position;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ * 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>
|
|
|
+ * @param particle
|
|
|
+ * @param index
|
|
|
+ * @param globalBest
|
|
|
+ */
|
|
|
+ private void updateVelocity(Particle particle, int index, Individual globalBest) {
|
|
|
+ double r1 = Random.nextDouble();
|
|
|
+ double r2 = Random.nextDouble();
|
|
|
+ double posValue = particle.xPhenotype.get(index)?1.0:0.0;
|
|
|
+ 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)) );
|
|
|
+ }
|
|
|
+
|
|
|
+ * 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>
|
|
|
+ * @param particle
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ private void updateGenotype(Particle particle, int index) {
|
|
|
+ particle.xGenotype.set(index, clamp(particle.xGenotype.get(index) + particle.velocity.get(index)));
|
|
|
+ }
|
|
|
+
|
|
|
+ * Eq. (11):<b>if(</b>rand()<r<sub>mu</sub><b>)then</b> x<sub>g,i,j</sub>(t + 1) = -x<sub>g,i,j</sub>(t + 1)<br>
|
|
|
+ * @param particle
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ private void mutation(Particle particle, int index) {
|
|
|
+ if(Random.nextDouble() < limit) particle.xGenotype.set(index, -particle.xGenotype.get(index));
|
|
|
+ }
|
|
|
+
|
|
|
+ * Eq. (8):x<sub>p,i,j</sub>(t + 1) = <b>(</b>rand() < S(x<sub>g,i,j</sub>(t + 1))<b>) ?</b> 1 <b>:</b> 0<br>
|
|
|
+ * @param particle
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ private void decode(Particle particle, int index) {
|
|
|
+ particle.xPhenotype.set(index, Random.nextDouble() < Sigmoid(particle.xGenotype.get(index)));
|
|
|
+ }
|
|
|
+
|
|
|
+ * 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>
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private double Sigmoid(double value) {
|
|
|
+ return 1.0 / (1.0 + Math.exp(-value));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ * 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}
|
|
|
+ * @param value
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private double clamp(double value) {
|
|
|
+ return Math.max(-4.0, Math.min(4.0, value));
|
|
|
+ }
|
|
|
+ private TreeSet<Integer> locationsToMutate(int dimensions) {
|
|
|
+ TreeSet<Integer> mutationLocation = new TreeSet<Integer>();
|
|
|
+ int maximumAmountOfMutatedBits = Math.max(1, (int)Math.round(((double) dimensions) * this.maxMutationPercent));
|
|
|
+ int randomUniformAmountOfMutatedValues = Random.nextIntegerInRange(1,maximumAmountOfMutatedBits + 1);
|
|
|
+ for(int i = 0; i< randomUniformAmountOfMutatedValues; i++) {
|
|
|
+ boolean success = mutationLocation.add(Random.nextIntegerInRange(0, dimensions));
|
|
|
+ if(!success) i--;
|
|
|
+ }
|
|
|
+
|
|
|
+ return mutationLocation;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * Class to represent a Particle.
|
|
|
+ */
|
|
|
+ private class Particle{
|
|
|
+
|
|
|
+ * The velocity of a particle.
|
|
|
+ */
|
|
|
+ public List<Double> velocity;
|
|
|
+
|
|
|
+ * The positions genotype.
|
|
|
+ */
|
|
|
+ public List<Double> xGenotype;
|
|
|
+
|
|
|
+ * The positions phenotype. Alias the current position.
|
|
|
+ */
|
|
|
+ public List<Boolean> xPhenotype;
|
|
|
+
|
|
|
+ public Individual localBest;
|
|
|
+
|
|
|
+ Particle(List<Boolean> position){
|
|
|
+ this.xPhenotype = position;
|
|
|
+
|
|
|
+ this.velocity = position.stream().map(bool -> 0.0).collect(Collectors.toList());
|
|
|
+ this.xGenotype = position.stream().map(bool -> 0.0).collect(Collectors.toList());
|
|
|
+ localBest = new Individual();
|
|
|
+ localBest.fitness = Double.MAX_VALUE;
|
|
|
+ }
|
|
|
+ public void checkNewEvaluationValue(double newEvaluationValue) {
|
|
|
+ if(newEvaluationValue < localBest.fitness) {
|
|
|
+ localBest.fitness = newEvaluationValue;
|
|
|
+ localBest.position = xPhenotype.stream().map(bool -> bool).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public String toString() {
|
|
|
+ return "Particle with xPhenotype(Position), xGenotype, velocity:["
|
|
|
+ + listToString(xPhenotype) + "],[" + listToString(xGenotype) + "],["
|
|
|
+ + listToString(velocity) + "]";
|
|
|
+ }
|
|
|
+ private <Type> String listToString(List<Type> list) {
|
|
|
+ return list.stream().map(Object::toString).collect(Collectors.joining(", "));
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|