目前我正试图创建一个刺激退火算法来解决旅行商问题以及为它创建一个gui。初始城市(点)和线显示,但我无法成功运行doSA()方法。任何想法,有点难过。
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();
}
}
}
答案 0 :(得分:0)
可能是您的初始参数:模拟退火对参数非常敏感,它需要2个参数(初始温度和冷却时间表),这使得很难对它们进行调整。在my implementation中,我通过将冷却时间基于仍然可用的时间量将其减少为1个参数。
也可能是acceptanceProbability
方法中的错误。编写单元测试,涵盖角落案例,以证明它是正确的。这是my test impl。