用遗传算法解决旅行商问题
genetic algorithm to solve TSP problem
参考连接:Genetic algorithm – Wikipedia
Travellingsalesman problem – Wikipedia
Travelling-Salesman–a-Genetic-Algorithm
旅行商问题:
给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。它是组合优化中的一个NP困难问题,在运筹学和理论计算机科学中非常重要。
遗传算法:
遗传算法通常实现方式为一种计算机模拟。对于一个最优化问题,一定数量的候选解(称为个体)可抽象表示为染色体,使种群向更好的解进化。传统上,解用二进制表示(即0和1的串),但也可以用其他表示方法。进化从完全随机个体的种群开始,之后一代一代发生。在每一代中评价整个种群的适应度,从当前种群中随机地选择多个个体(基于它们的适应度),通过自然选择和突变产生新的生命种群,该种群在算法的下一次迭代中成为当前种群。
流程与步骤
第一步:初始化 t←0进化代数计数器;T是最大进化代数;随机生成M个个体作为初始 群体P(t);
第二步:个体评价计算P(t)中各个个体的适应度;
第三步:选择运算将选择算子作用于群体;
第四步:交叉运算将交叉算子作用于群体;
第五步:变异运算将变异算子作用于群体,并通过以上运算得到下一代群体P(t + 1);
第六步:终止条件判断 t≦T:t← t+1 转到步骤2;t>T:终止 输出解。
基本上可以归结为随机取种群中元素然后两两交配生成下一代,其中可能存在变异,每次通过估价函数来淘汰调一部分,这样迭代。终止条件可以是种群估价可接受或者自己设定迭代次数.
现在假定问题中的城市是在二维平面上的点,两城市距离为两点的直线距离。
存储城市信息类City
//通过(x,y)表示一个城市
public class City {
int x;
int y;
// 生成随机的城市(x,y)
public City(){
this.x = (int)(Math.random()*200);
this.y = (int)(Math.random()*200);
}
// 生成城市
public City(int x, int y){
this.x = x;
this.y = y;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
// 从本城市(this)到城市city的距离
public double distanceTo(City city){
int xDistance = Math.abs(getX() - city.getX());
int yDistance = Math.abs(getY() - city.getY());
double distance = Math.sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
return distance;
}
@Override
public String toString(){
return getX()+", "+getY();
}
}
存储所有的城市——全局变量TourManger类
//全局变量list 存储所有的城市
public class TourManager {
private static ArrayList destinationCities = new ArrayList<City>();
public static void addCity(City city) {
destinationCities.add(city);
}
public static City getCity(int index){
return (City)destinationCities.get(index);
}
public static int numberOfCities(){
return destinationCities.size();
}
}
处理旅游路径信息类Tour
//旅游的路径类
public class Tour{
// 用list存储city路径
private ArrayList tour = new ArrayList<City>();
// fitness=1/distance
private double fitness = 0;
private int distance = 0;
// 生成一个空路径
public Tour(){
for (int i = 0; i < TourManager.numberOfCities(); i++) {
tour.add(null);
}
}
public Tour(ArrayList tour){
this.tour = tour;
}
// 随机生成一个个体
public void generateIndividual() {
for (int cityIndex = 0; cityIndex < TourManager.numberOfCities(); cityIndex++) {
setCity(cityIndex, TourManager.getCity(cityIndex));
}
//随机打乱顺序
Collections.shuffle(tour);
}
// 返回路径的tourPosition 元素
public City getCity(int tourPosition) {
return (City)tour.get(tourPosition);
}
// 设置路径的turPositio元素
public void setCity(int tourPosition, City city) {
tour.set(tourPosition, city);
// If the tours been altered we need to reset the fitness and distance
fitness = 0;
distance = 0;
}
// 获得路径的估价
public double getFitness() {
if (fitness == 0) {
fitness = 1/(double)getDistance();
}
return fitness;
}
// 返回路径总代价
public int getDistance(){
if (distance == 0) {
int tourDistance = 0;
// 遍历路径
for (int cityIndex=0; cityIndex < tourSize(); cityIndex++) {
// 出发城市
City fromCity = getCity(cityIndex);
// 目的城市
City destinationCity;
// 如果出发城市是路径的最后一个则返回起点
//否则去往路径的后一个城市
if(cityIndex+1 < tourSize()){
destinationCity = getCity(cityIndex+1);
}
else{
destinationCity = getCity(0);
}
tourDistance += fromCity.distanceTo(destinationCity);
}
distance = tourDistance;
}
return distance;
}
// 路径中城市的个数
public int tourSize() {
return tour.size();
}
// 路径是否含有该城市
public boolean containsCity(City city){
return tour.contains(city);
}
@Override
public String toString() {
String geneString = "|";
for (int i = 0; i < tourSize(); i++) {
geneString += getCity(i)+"|";
}
return geneString;
}
}
存储一组旅游路径—–种群类Population
//路径的种群 Population of tour
public class Population {
Tour[] tours;
public Population(int populationSize, boolean initialise) {
tours = new Tour[populationSize];
// 如果需要initialise 为true 初始化 Population
if (initialise) {
for (int i = 0; i < populationSize(); i++) {
Tour newTour = new Tour();
newTour.generateIndividual();
saveTour(i, newTour);
}
}
}
public void saveTour(int index, Tour tour) {
tours[index] = tour;
}
public Tour getTour(int index) {
return tours[index];
}
// 返回最优路径
public Tour getFittest() {
Tour fittest = tours[0];
for (int i = 1; i < populationSize(); i++) {
if (fittest.getFitness() <= getTour(i).getFitness()) {
fittest = getTour(i);
}
}
return fittest;
}
public int populationSize() {
return tours.length;
}
}
遗传算法(genetic algorithm)实现类——GA
//genetic algorithm
public class GA{
private static final double mutationRate=0.015;
private static final int tournemetSize=5;
//生成下一代
public static Population evolvePopulation(Population pop){
Population nextPopulation=new Population(pop.populationSize(),false);
//保存本代最优
nextPopulation.saveTour(0,pop.getFittest());
//交叉产生下一代
for(int i=1;i<nextPopulation.populationSize();i++){
//选取父辈
Tour parent1 = tournamentSeletction(pop);
Tour parent2 = tournamentSeletction(pop);
//交叉产生下一代
Tour child= crossover(parent1,parent2);
nextPopulation.addTour(child);
}
//变异
for(int i=1;i<nextPopulation;i++){
mutate(nextPopulation.getTour(i));
}
return nextPopulation;
}
//交叉产生下一代
public static Tour crossover(Tour parent1, Tour parent2){
Tour child=new Tour();
int startPos=(int)(Math.random()*parent1.tourSize());
int endPos=(int)(Math.random()*parent2.tourSize());
if(startPos<endPos) {int tmp=startPos; startPos=endPos;endPos=tmp;}
//从parent1选取元素传递给下一代
for(int i=0;i<child.tourSize();i++)
if(i>startPos&&i<endPos) child.setCity(i,parent1.getCity(i));
//从parent2中选取元素传递给下一代
for(int i=0;i<parent2.tourSize();i++)
if(!child.containsCity(parent2.get(i)))
for(int j=0;j<child.tourSize();j++)
if(child.getCity(j)==null){
child.setCity(j,parent2.getCity(i));
break;
}
return child;
}
//随机生成数字判断是否需要变异
//通过交换路径中的两个元素变异
public static void mutate(Tour tour){
for(int tourPos1=0; tourPos1< tour.tourSize(); tourPos1++)
if(Math.random()<mutationRate){
int tourPos2 = (int) (tour.tourSize() * Math.random());
City city1 = tour.getCity(tourPos1);
City city2 = tour.getCity(tourPos2);
tour.setCity(tourPos2, city1);
tour.setCity(tourPos1, city2);
}
}
//选取若干各路径Tour选出最优的
private static Tour tournamentSeletction(Population pop){
Population tournament = new Population(tournamentSize, false);
for (int i = 0; i < tournamentSize; i++) {
int randomId = (int) (Math.random() * pop.populationSize());
tournament.saveTour(i, pop.getTour(randomId));
}
Tour fittest = tournament.getFittest();
return fittest;
}
}
测试类TSP_GA:
public class TSP_GA {
public static void main(String[] args) {
City city = new City(60, 200);
TourManager.addCity(city);
City city2 = new City(180, 200);
TourManager.addCity(city2);
City city3 = new City(80, 180);
TourManager.addCity(city3);
City city4 = new City(140, 180);
TourManager.addCity(city4);
City city5 = new City(20, 160);
TourManager.addCity(city5);
City city6 = new City(100, 160);
TourManager.addCity(city6);
City city7 = new City(200, 160);
TourManager.addCity(city7);
City city8 = new City(140, 140);
TourManager.addCity(city8);
City city9 = new City(40, 120);
TourManager.addCity(city9);
City city10 = new City(100, 120);
TourManager.addCity(city10);
City city11 = new City(180, 100);
TourManager.addCity(city11);
City city12 = new City(60, 80);
TourManager.addCity(city12);
City city13 = new City(120, 80);
TourManager.addCity(city13);
City city14 = new City(180, 60);
TourManager.addCity(city14);
City city15 = new City(20, 40);
TourManager.addCity(city15);
City city16 = new City(100, 40);
TourManager.addCity(city16);
City city17 = new City(200, 40);
TourManager.addCity(city17);
City city18 = new City(20, 20);
TourManager.addCity(city18);
City city19 = new City(60, 20);
TourManager.addCity(city19);
City city20 = new City(160, 20);
TourManager.addCity(city20);
Population pop = new Population(50, true);
System.out.println("Initial distance: " + pop.getFittest().getDistance());
pop = GA.evolvePopulation(pop);
for (int i = 0; i < 100; i++) {
pop = GA.evolvePopulation(pop);
}
System.out.println("Finished");
System.out.println("Final distance: " + pop.getFittest().getDistance());
System.out.println("Solution:");
System.out.println(pop.getFittest());
}
}
运行结果: