/**
* tsp文件采用的是用遗传算法解决,而且文件里的每个数据是城市与城市之间的距离
* 操作注意事项:
* 1、首先输入文件路径,获取文件里全部数据
* 2、设置所需要的城市规模,城市的规模不能超过文件里城市规模的最大数
* 3、设置种群,种群数不能过大,也不能过小
* 文件里数据的数据注意事项:
* 1、文件里的每个数据是城市和城市之间的距离,例如0,56,89…表示的就是第一个城市到第一个城市的距离是0,第一个城市到第二个城市的距离为56,
* 第一个城市到第三个城市的距离为89等等,一直到第一个城市到最后一个城市的距离
* 2、由于程序的局限性,城市的规模最大为26个城市
* 3、数据之间不能出现空格
* 帮助事项:该程序采用的是顺序交叉的方式,变异是采用启发式变异算子,不懂得可以在网上搜索,也可以通过留言
*/
package tsp_3;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Random;
import javax.swing.JOptionPane;
class tsp {
private int data[][] = null;
private int cityNumber = 0;// 存储文件里全部城市的个数
private int cityNeedNumber = 0;// 所需要的城市的个数
private int population = 0;// 种群的个数
private double acrossPoint = 0.9;// 交叉率
private double variationPoint = 0.01;// 变异率
private Random random = new Random();
private String bestPopulation;//存储最优的字符串用于遗传到下一代
/**
* 初始化population条路径
*/
public String[] initialise() {
int city[] = new int[getCityNeedNumber()];
String s[] = new String[getPopulation()];
for (int j = 0; j < s.length; j++) {
String a = "";
boolean tRf = true;
// 初始化数组
for (int i = 0; i < city.length; i++) {
city[i] = -1;
}
for (int i = 0; i < city.length; i++) {
while (tRf) {
int k = random.nextInt(city.length);
/**
* 在city[]数组中寻找k,如果不存在方法isTrue(city, k)会返回true,否则返回false
*/
if (isTrue(city, k)) {
city[i] = k;
tRf = false;
}
}
tRf = true;
}
//把数据转化成字符串
for (int i = 0; i < city.length; i++) {
a = a + digitChangeCharacter(city[i]);
}
s[j] = a;
}
setBestPopulation(s[0]);//初始化数据
return s;
}
/**
* 交叉
*/
public String[] across(String city[]) {
int order[] = new int[city.length];
int n = 0;
int length1 = 0;
int length2 = 0;
int acrossPlacs1 = 0;
int acrossPlacs2 = 0;
String child1 = "";
String child2 = "";
String f1temp1 = "";
String f1temp2 = "";
String f1temp3 = "";
String f2temp1 = "";
String f2temp2 = "";
String f2temp3 = "";
//初始化数组
for (int i = 0; i < city.length; i++) {
order[i] = -1;
}
/**
* 1、产生city.length个不同的数,存入数组
* 2、数组中的数据是用于标识字符串,也就是字符串数组的下标,用意就是打乱字符串数组,随机两两配对,用于交叉
*/
for (int i = 0; i < city.length; i++) {
boolean t = true;
while (t) {
n = random.nextInt(city.length);
if (isTrue(order, n)) {
order[i] = n;
t = false;
}
}
}
//生成两个不同的数,作为交叉的位置
for (int i = 0; i < city.length; i++, i++) {
if (random.nextDouble() < getAcrossPoint()) {
acrossPlacs1 = random.nextInt(getCityNeedNumber());
acrossPlacs1 = acrossPlacs2;
while (acrossPlacs1 == acrossPlacs2) {
acrossPlacs2 = random.nextInt(getCityNeedNumber());// 保证acrossPlace1和acrossPlace2不相等
}
if (acrossPlacs1 > acrossPlacs2) {
int temp = acrossPlacs1;
acrossPlacs1 = acrossPlacs2;// 保证acrossPlace1 getRouteLength(w)) {
beatString = w;
min = getRouteLength(w);
}
// ********************
w = str;
w = w.replace(tem_2, '*'); //
w = w.replace(tem_3, tem_2);
w = w.replace('*', tem_3);
if (min > getRouteLength(w)) {
beatString = w;
min = getRouteLength(w);
}
w = w.replace(tem_3, '*'); // 3 2 1
w = w.replace(tem_1, tem_3);
w = w.replace('*', tem_1);
if (min > getRouteLength(w)) {
beatString = w;
min = getRouteLength(w);
}
// *********************
w = str;
w = w.replace(tem_2, '*'); // two one three
w = w.replace(tem_1, tem_2);
w = w.replace('*', tem_1);
if (min > getRouteLength(w)) {
beatString = w;
min = getRouteLength(w);
}
w = w.replace(tem_3, '*'); // three one two
w = w.replace(tem_1, tem_3);
w = w.replace('*', tem_1);
if (min > getRouteLength(w)) {
beatString = w;
min = getRouteLength(w);
}
return beatString;
}
/**
* 选择
*/
public String[] select(String city[]) {
double point[] = new double[city.length];
double sum = 0;
double q[] = new double[city.length];
for (int i = 0; i < city.length; i++) {
sum = sum + getRouteLength(city[i]);
}
for (int i = 0; i < city.length; i++) {
BigDecimal bg = new BigDecimal(getRouteLength(city[i]) / sum);
point[i] = bg.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue();
}
BigDecimal bg = new BigDecimal(random.nextDouble());
double p = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
for (int i = 0; i < city.length; i++) {
if (i == 0) {
q[i] = point[i];
} else {
q[i] = q[i - 1] + point[i];
}
}
selectPopulation(city);
city[randomSelectPopulation(q)]=getBestPopulation();
return city;
}
/**
* 选择最好的个体
*/
public void selectPopulation(String city[]){
int min=getRouteLength(getBestPopulation());
for(int i=0;igetRouteLength(city[i])){
setBestPopulation(city[i]);
}
}
}
/**
* 轮盘赌注算法
*/
private int randomSelectPopulation(double q[]) {
double r = random.nextDouble();
int b=0;
if (r <= q[0]) {
b=0;
} else {
for (int i = 0; i < q.length; i++) {
if (r < q[0]) {
b=i;
}
}
}
return b;
}
/**
* 获取路劲的长度-ok
*
* @return
*/
public int getRouteLength(String p) {
int s = 0;
int sum = 0;
if (p != "") {
int a[] = new int[p.length()];
for (int x = 0; x < p.length(); x++) {
a[x] = characterChangeDigit(p.charAt(x) + "");
}
for (int j = 0; j < p.length() - 1; j++) {
sum = sum + data[a[j]][a[j + 1]];
}
s = sum + data[a[0]][a[p.length() - 1]];
}
return s;
}
public double getAcrossPoint() {
return acrossPoint;
}
public void setAcrossPoint(double acrossPoint) {
this.acrossPoint = acrossPoint;
}
public double getVariationPoint() {
return variationPoint;
}
public void setVariationPoint(double variationPoint) {
this.variationPoint = variationPoint;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
public int[][] getData() {
return data;
}
public void setData(String filePath) {
readTxtFile(filePath);
}
public int getCityNumber() {
return cityNumber;
}
public String getBestPopulation() {
return bestPopulation;
}
public void setBestPopulation(String bestPopulation) {
this.bestPopulation = bestPopulation;
}
public void setCityNumber(int cityNumber) {
this.cityNumber = cityNumber;
}
public int getCityNeedNumber() {
return cityNeedNumber;
}
/**
* 输入所需要的城市的个数
*
* @param cityNeedNumber
*/
public void setCityNeedNumber(int cityNeedNumber) {
if (getCityNumber() >= getCityNeedNumber()) {
this.cityNeedNumber = cityNeedNumber;
} else {
JOptionPane.showMessageDialog(null,
"输入的城市个数超过文件里城市的最大数",
"稻花香提醒您",
JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* 读取文件中城市的个数
*/
public int readeFileLine(String filePath) {
int i = 0;
InputStreamReader read = null;
BufferedReader bufferedReader = null;
try {
File file = new File(filePath);
if (file.isFile() && file.exists()) { // 判断文件是否存在
read = new InputStreamReader(new FileInputStream(file), "GBK");// 考虑到编码格式
bufferedReader = new BufferedReader(read);
while (bufferedReader.readLine() != null) {
i++;
}
read.close();
} else {
System.out.println("找不到指定的文件");
}
} catch (Exception e) {
System.out.println("读取文件内容出错");
e.printStackTrace();
}
return i;
}
/**
* 读取文件的数据
*
* @param filePath
*/
public void readTxtFile(String filePath) {
try {
setCityNumber(readeFileLine(filePath));
data = new int[getCityNumber()][getCityNumber()];
File file = new File(filePath);
if (file.isFile() && file.exists()) { // 判断文件是否存在
InputStreamReader read = new InputStreamReader(
new FileInputStream(file), "GBK");// 考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
int i = 0;
while ((lineTxt = bufferedReader.readLine()) != null) {
String[] strcol = lineTxt.split(",");// 文件里的数据的格式,如同1,56,23
for (int j = 0; j < strcol.length - 1; j++) {
data[i][j] = Integer.valueOf(strcol[j]);
}
i++;
}
read.close();
} else {
System.out.println("找不到指定的文件");
}
} catch (Exception e) {
System.out.println("读取文件内容出错");
e.printStackTrace();
}
}
/**
* 函数名:isTrue(int s[], int a) 函数功能:判断一条路径是否出现相同的城市 函数的参数:int s[],int a
* 函数的返回值
*/
public boolean isTrue(int s[], int a) {
boolean tRf = true;
for (int i = 0; i < s.length; i++) {
if (s[i] == a) {
tRf = false;
}
}
return tRf;
}
/**
* 把数字转化成字母
*
* @param args
*/
public String digitChangeCharacter(int city) {
String character[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
"V", "X", "Y", "Z" };
return character[city];
}
/**
* 把字母转化成数字
*
* @param args
*/
public int characterChangeDigit(String string) {
int count = 0;
String character[] = { "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
"V", "X", "Y", "Z" };
for (int i = 0; i < character.length; i++) {
if (character[i].equals(string)) {
count = i;
}
}
return count;
}
/**
* 显示
*
* @param args
*/
public void show(String city[]) {
for (int i = 0; i < city.length; i++) {
System.out.println(city[i]);
}
}
public static void main(String[] args) {
int count=0;
tsp tsp = new tsp();
tsp.setData("F:/tsp.txt");
tsp.setCityNeedNumber(10);
tsp.setPopulation(200);
String s[] = new String[tsp.getPopulation()];
System.out.println("初始化");
s = tsp.initialise();
tsp.show(s);
while(count<1000){
s = tsp.across(s);
s = tsp.variation(s);
s = tsp.select(s);
System.out.println("第"+count+"次"+" 最优个体:"+tsp.getBestPopulation()+" 最短路径:"+tsp.getRouteLength(tsp.getBestPopulation()));
count++;
}
}
}