diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fb50116 --- /dev/null +++ b/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..77e2734 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + pso-example-java + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..b196c64 --- /dev/null +++ b/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/README.md b/README.md index ad813cb..2e240d7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -pso-example-java +Particle Swarm Optimization with UI ================ -Particle Swarm Optimization (PSO) Sample Code using Java +Swing library is used here for UI programming. -This project is a complete version of Particle Swarm Optimization with Java sample code described in http://gandhim.wordpress.com/2010/04/04/particle-swarm-optimization-pso-sample-code-using-java. +Thanks to https://github.com/therealmanalu for PSO implementation on Java. diff --git a/src/org/gandhim/pso/Main.java b/src/org/gandhim/pso/Main.java new file mode 100644 index 0000000..d73e5e1 --- /dev/null +++ b/src/org/gandhim/pso/Main.java @@ -0,0 +1,15 @@ +package org.gandhim.pso; + +import javax.swing.JFrame; + +public class Main { + + public static void main(String[] args) + { + MainFrame frame1 = new MainFrame(); + frame1.setSize(600, 400); + frame1.setVisible(true); + frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + +} diff --git a/src/org/gandhim/pso/MainFrame.java b/src/org/gandhim/pso/MainFrame.java new file mode 100644 index 0000000..0fc91f3 --- /dev/null +++ b/src/org/gandhim/pso/MainFrame.java @@ -0,0 +1,155 @@ +package org.gandhim.pso; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Hashtable; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.basic.BasicArrowButton; + +public class MainFrame extends JFrame implements PSOConstants +{ + private PaintPanel panel1; + private JPanel panel2; + private Hashtable labelTable1; + private JPanel container1; + private JButton button1, button2; + private JCheckBox checkbox1; + private JSlider slider1; + private static JTextArea textarea1; + private JScrollPane scroll1; + + public MainFrame() + { + super("Particle Swarm Optimization"); + + container1 = new JPanel(new GridBagLayout()); + add(container1, BorderLayout.CENTER); + + panel2 = new JPanel(); + add(panel2, BorderLayout.SOUTH); + + button1 = new JButton("Back to the begin"); + panel2.add(button1, BorderLayout.WEST); + + + button2 = new JButton("Forward"); + panel2.add(button2, BorderLayout.WEST); + + checkbox1 = new JCheckBox("Iterate automatically"); + panel2.add(checkbox1, BorderLayout.CENTER); + + labelTable1 = new Hashtable(); + labelTable1.put(new Integer(MIN_DELAY), new JLabel(MIN_DELAY/1000f + "it/sec")); + labelTable1.put(new Integer((MIN_DELAY + MAX_DELAY)/2), new JLabel((MIN_DELAY + MAX_DELAY)/2000f + "it/sec")); + labelTable1.put(new Integer(MAX_DELAY), new JLabel(MAX_DELAY/1000f + "it/sec")); + + slider1 = new JSlider(JSlider.VERTICAL, MIN_DELAY, MAX_DELAY, MIN_DELAY); + slider1.setLabelTable(labelTable1); + slider1.setPaintLabels(true); + add(slider1, BorderLayout.WEST); + + textarea1 = new JTextArea(20, 22); + textarea1.setEditable(false); + textarea1.setLineWrap(true); + scroll1 = new JScrollPane(textarea1); + scroll1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + + add(scroll1, BorderLayout.EAST); + + panel1 = new PaintPanel(); + container1.add(panel1); + + container1.addComponentListener(new ComponentListenerOne()); + button1.addActionListener(new ActionListenerOne(false)); + button2.addActionListener(new ActionListenerOne(true)); + checkbox1.addItemListener(new ItemListenerOne()); + slider1.addChangeListener(new ChangeListenerOne()); + } + + public static void appendText(String text) + { + textarea1.append(text + "\n"); + textarea1.setCaretPosition(textarea1.getDocument().getLength()); + } + + class ComponentListenerOne implements ComponentListener + { + + @Override + public void componentResized(ComponentEvent e) { + + int w = container1.getWidth(); + int h = container1.getHeight(); + int size = Math.min(w, h); + panel1.setPreferredSize(new Dimension(size, size)); + container1.revalidate(); + } + + @Override + public void componentMoved(ComponentEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void componentShown(ComponentEvent e) { + // TODO Auto-generated method stub + + } + + @Override + public void componentHidden(ComponentEvent e) { + // TODO Auto-generated method stub + + } + } + + class ActionListenerOne implements ActionListener + { + private boolean forward; + + public ActionListenerOne(boolean forward) + { + super(); + this.forward = forward; + } + + public void actionPerformed(ActionEvent e) + { + panel1.executeProcess(this.forward); + } + + } + + class ItemListenerOne implements ItemListener + { + public void itemStateChanged(ItemEvent e) + { + panel1.setAutoIterate(checkbox1.isSelected()); + } + } + + class ChangeListenerOne implements ChangeListener + { + public void stateChanged(ChangeEvent e) + { + JSlider source = (JSlider)e.getSource(); + if(!source.getValueIsAdjusting()) + { + int delay = (int)source.getValue(); + panel1.setIterateTimerDelay(delay); + } + } + } +} diff --git a/src/org/gandhim/pso/PSOConstants.java b/src/org/gandhim/pso/PSOConstants.java index 4b9c60d..294ae4e 100644 --- a/src/org/gandhim/pso/PSOConstants.java +++ b/src/org/gandhim/pso/PSOConstants.java @@ -9,8 +9,10 @@ public interface PSOConstants { int SWARM_SIZE = 30; int MAX_ITERATION = 100; int PROBLEM_DIMENSION = 2; - double C1 = 2.0; - double C2 = 2.0; - double W_UPPERBOUND = 1.0; - double W_LOWERBOUND = 0.0; + double C1 = 1; + double C2 = 1; + double W_UPPERBOUND = 0.9; + double W_LOWERBOUND = 0.4; + int MIN_DELAY = 100; + int MAX_DELAY = 1000; } diff --git a/src/org/gandhim/pso/PSODriver.java b/src/org/gandhim/pso/PSODriver.java deleted file mode 100644 index 6889d4a..0000000 --- a/src/org/gandhim/pso/PSODriver.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.gandhim.pso; - -/* author: gandhi - gandhi.mtm [at] gmail [dot] com - Depok, Indonesia */ - -// this is a driver class to execute the PSO process - -public class PSODriver { - public static void main(String args[]) { - new PSOProcess().execute(); - } -} diff --git a/src/org/gandhim/pso/PSOProcess.java b/src/org/gandhim/pso/PSOProcess.java index 2bccb53..a7dfe40 100644 --- a/src/org/gandhim/pso/PSOProcess.java +++ b/src/org/gandhim/pso/PSOProcess.java @@ -16,23 +16,44 @@ public class PSOProcess implements PSOConstants { private double gBest; private Location gBestLocation; private double[] fitnessValueList = new double[SWARM_SIZE]; + private int t = 0; + private double w; + private double err = 9999; + public int getT() { + return t; + } + Random generator = new Random(); - public void execute() { - initializeSwarm(); - updateFitnessList(); + public void execute(boolean forward) { - for(int i=0; i 0) + { + t = 0; } + else if(t >= MAX_ITERATION) + return; - int t = 0; - double w; - double err = 9999; + if(t == 0) + { + initializeSwarm(); + System.out.println("LAL"); + updateFitnessList(); + + for(int i=0; i ProblemSet.ERR_TOLERANCE) { + if(t < MAX_ITERATION && err > ProblemSet.ERR_TOLERANCE) + { // step 1 - update pBest for(int i=0; i getSwarm() { + return swarm; + } + + public Vector getpBestLocation() { + return pBestLocation; + } + + public Location getgBestLocation() { + return gBestLocation; + } } diff --git a/src/org/gandhim/pso/PaintPanel.java b/src/org/gandhim/pso/PaintPanel.java new file mode 100644 index 0000000..e6762b7 --- /dev/null +++ b/src/org/gandhim/pso/PaintPanel.java @@ -0,0 +1,132 @@ +package org.gandhim.pso; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.*; + +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.Timer; + +public class PaintPanel extends JPanel +{ + private PSOProcess process; + private double minX, maxX, minY, maxY; + private Font font; + private boolean autoIterate; + private Timer IterateTimer; + + public PaintPanel() + { + super(); + setBackground(Color.LIGHT_GRAY); + process = new PSOProcess(); + executeProcess(false); + autoIterate = false; + + IterateTimer = new Timer(100, new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + if(autoIterate) + executeProcess(true); + } + } + ); + IterateTimer.start(); + + minX = ProblemSet.LOC_X_LOW; + maxX = ProblemSet.LOC_X_HIGH; + minY = ProblemSet.LOC_Y_LOW; + maxY = ProblemSet.LOC_Y_HIGH; + + font = new Font("Serif", Font.PLAIN, 10); + } + + public void setAutoIterate(boolean autoIterate) { + this.autoIterate = autoIterate; + } + public void setIterateTimerDelay(int delay) + { + IterateTimer.setDelay(delay); + } + + private Point formattedPoint(double x, double y) + { + + double normX = (x - (minX + maxX)/2)/((maxX - minX)/2); + double normY = (y - (minY + maxY)/2)/((maxY - minY)/2); + + return new Point(getWidth()/2 + (int)(getWidth()/2*normX), getHeight()/2 - ((int)(getHeight()/2*normY))); + } + + public void executeProcess(boolean forward) + { + process.execute(forward); + repaint(); + } + + public int getT() + { + return process.getT(); + } + + private void drawGrid(Graphics g) + { + Point point1, point2; + + for(int i = (int) minX; i <= maxX; i++) + { + point1 = formattedPoint(i, minY); + point2 = formattedPoint(i, maxY); + g.drawLine(point1.x, point1.y, point2.x, point2.y); + g.drawString(String.valueOf(i), point1.x, (point1.y + point2.y)/2); + } + + for(int i = (int) minY; i <= maxY; i++) + { + point1 = formattedPoint(minX, i); + point2 = formattedPoint(maxX, i); + g.drawLine(point1.x, point1.y, point2.x, point2.y); + g.drawString(String.valueOf(i), (point1.x + point2.x)/2, point1.y); + } + } + + public void drawCircle(Graphics g, int x, int y, int size) + { + g.drawOval(x - size/2, y - size/2, size, size); + } + + public void fillCircle(Graphics g, int x, int y, int size) + { + g.fillOval(x - size/2, y - size/2, size, size); + } + + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + Point point; + + g.setColor(Color.GRAY); + g.setFont(font); + + drawGrid(g); + + g.setColor(Color.BLUE); + + for(Particle particle: process.getSwarm()) + { + point = formattedPoint(particle.getLocation().getLoc()[0], particle.getLocation().getLoc()[1]); + fillCircle(g, point.x, point.y, 4); + } + + g.setColor(Color.RED); + + point = formattedPoint(process.getgBestLocation().getLoc()[0], process.getgBestLocation().getLoc()[1]); + drawCircle(g, point.x, point.y, 8); + + } +} diff --git a/src/org/gandhim/pso/ProblemSet.java b/src/org/gandhim/pso/ProblemSet.java index 663aa68..e27daf6 100644 --- a/src/org/gandhim/pso/ProblemSet.java +++ b/src/org/gandhim/pso/ProblemSet.java @@ -12,10 +12,10 @@ // you need to introduce a new variable (other than x and y) public class ProblemSet { - public static final double LOC_X_LOW = 1; - public static final double LOC_X_HIGH = 4; - public static final double LOC_Y_LOW = -1; - public static final double LOC_Y_HIGH = 1; + public static final double LOC_X_LOW = -3; + public static final double LOC_X_HIGH = 3; + public static final double LOC_Y_LOW = -3; + public static final double LOC_Y_HIGH = 3; public static final double VEL_LOW = -1; public static final double VEL_HIGH = 1; @@ -27,9 +27,7 @@ public static double evaluate(Location location) { double x = location.getLoc()[0]; // the "x" part of the location double y = location.getLoc()[1]; // the "y" part of the location - result = Math.pow(2.8125 - x + x * Math.pow(y, 4), 2) + - Math.pow(2.25 - x + x * Math.pow(y, 2), 2) + - Math.pow(1.5 - x + x * y, 2); + result = Math.pow(1 - x, 2) + 100 * Math.pow(y - x * x, 2); return result; }