用遗传算法解决tsp问题

用遗传算法解决tsp问题

/**
* 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++;
    }

}

}

你可能感兴趣的:(与君语)