0

Currently i'm trying to create a stimulated annealing algorithm solving the traveling salesman problem as well as creating a gui for it. The initial cities(points) and lines display but I can't get the doSA() method to successfully run. Any ideas, sorta stumped.

class SAPanel extends JPanel implements ActionListener{
    private static final long serialVersionUID = 1L;
    private City city,city2,city3,city4,city5,city6,city7,city8,city9,city10,city11,city12,city13,city14,city15,city16,city17,city18,city19,city20;
    private int temp;
    private Tour best, currentSolution;
    int delay  = 10;
    static int POINTWIDTH = 8;
    static Color POINTCOLOR = Color.MAGENTA;
    static Color LINECOLOR = Color.CYAN;
    Timer timer = new Timer(delay, this);
    private static double coolingRate = .006; 


public void start(){
    temp = 10000;
    timer.start();
}


public void intiSA(){
    city = new City(60, 200);
    TourManager.addCity(city);
    city2 = new City(180, 200);
    TourManager.addCity(city2);
    city3 = new City(80, 180);
    TourManager.addCity(city3);
    city4 = new City(140, 180);
    TourManager.addCity(city4);
    city5 = new City(20, 160);
    TourManager.addCity(city5);
    city6 = new City(100, 160);
    TourManager.addCity(city6);
    city7 = new City(200, 160);
    TourManager.addCity(city7);
    city8 = new City(140, 140);
    TourManager.addCity(city8);
    city9 = new City(40, 120);
    TourManager.addCity(city9);
    city10 = new City(100, 120);
    TourManager.addCity(city10);
    city11 = new City(180, 100);
    TourManager.addCity(city11);
    city12 = new City(60, 80);
    TourManager.addCity(city12);
    city13 = new City(120, 80);
    TourManager.addCity(city13);
    city14 = new City(180, 60);
    TourManager.addCity(city14);
    city15 = new City(20, 40);
    TourManager.addCity(city15);
    city16 = new City(100, 40);
    TourManager.addCity(city16);
    city17 = new City(200, 40);
    TourManager.addCity(city17);
    city18 = new City(20, 20);
    TourManager.addCity(city18);
    city19 = new City(60, 20);
    TourManager.addCity(city19);
    city20 = new City(160, 20);
    TourManager.addCity(city20);

    //Initialize initial solution
    currentSolution = new Tour();
    currentSolution.generateIndividual();
    best = currentSolution;
    System.out.println("Initial solution distance: " + currentSolution.getDistance());
}

//energy represents the total distance of each tour
public static double acceptanceProbability(int energy, int newEnergy, double temp){
    //if currentSolution energy is larger than newEnergy, return 1.0
    if(newEnergy < energy){
        return 1.0;
    }

    //as temp decreases, acceptance of the new solution becomes more selective
    return Math.exp((energy-newEnergy) / temp);

}

public void doSA(){
    //set new solution as the current solution
    Tour newSolution = new Tour(currentSolution.getTour());
    //get two random points on the solution
    int tourPos1  = (int)(newSolution.tourSize() * Math.random());
    int tourPos2 = (int)(newSolution.tourSize() * Math.random());

    //get two cities depending on the selected points
    City citySwap1 = newSolution.getCity(tourPos1);
    City citySwap2 = newSolution.getCity(tourPos2);

    //swap the cities on the selected points
    newSolution.setCity(tourPos1, citySwap2);
    newSolution.setCity(tourPos2, citySwap1);

    int currentEnergy = currentSolution.getDistance();
    int neighborEnergy = currentSolution.getDistance();

    //accept new solution as the current solution if greater than random number
    if(acceptanceProbability(currentEnergy, neighborEnergy, temp) > Math.random()){
        currentSolution = new Tour(newSolution.getTour());
    }

    //keep the current solution as best if distance is greater
    if(currentSolution.getDistance() > newSolution.getDistance()){
        best = new Tour(currentSolution.getTour());
    }
    repaint();

}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2= (Graphics2D)(g);
    g2.setStroke(new BasicStroke(3));
    for(int x =0;x<19;x++){
        //draw lines connecting each city in solution
        g2.setColor(LINECOLOR);
        g2.drawLine(best.getCity(x).getX(), best.getCity(x).getY(), best.getCity(x+1).getX(), best.getCity(x+1).getY());
        g2.setColor(POINTCOLOR);
        //draw all points
        g2.fillOval(best.getCity(x).getX() - POINTWIDTH/2, best.getCity(x).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);
    }

    //draw last reminding line, connecting last city to first city.
    g2.setColor(LINECOLOR);
    g2.drawLine(best.getCity(19).getX(), best.getCity(19).getY(), best.getCity(0).getX(), best.getCity(0).getY());
    g2.setColor(POINTCOLOR);
    g2.fillOval(best.getCity(0).getX() - POINTWIDTH/2, best.getCity(0).getY() - POINTWIDTH/2, POINTWIDTH, POINTWIDTH);
}




public void actionPerformed(ActionEvent e){
    temp *= coolingRate -1;
    if(temp >1){
        doSA();
        System.out.println("Final solution distance: " + best.getDistance());
        System.out.println("Tour: " + best);
    }
    else{
        ((Timer)e.getSource()).stop();

    }
}   

}

  • "but I can't get the doSA() method to successfully run?" You need to elaborate it more. – Juned Ahsan Jan 20 '15 at 01:17
  • What's the relationship between `temp` and the `doSA` method? Should you really be creating new instances of objects in the `doSA` method? Shouldn't you simply be updating there state based on the value of `temp`? – MadProgrammer Jan 20 '15 at 01:19
  • So I should declare the objects as instance variables? – monsterbasher Jan 20 '15 at 01:23

1 Answers1

0

Could be your initial parameters: Simulated Annealing is very parameter sensitive and it requires 2 parameters (initial temp and cooldown schedule), which makes it hard to tweak them. In my implementation, I've reduced it to 1 parameter by basing the cooldown on the amount of time still available.

Could also be a bug in your acceptanceProbability method. Write a unit test, which covers the corner cases, to prove it's correct. Here's my test impl.

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120