蚁群算法JAVA带数据

之前下了几个蚁群算法,一堆问题,决定自己写一个。数据在下面。

 

 

package hggh;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
import java.util.Vector;

import javax.naming.InitialContext;

public class all {
    static int cityNum = 31;
    static int m = 50; // 蚂蚁数量
    static double alpha = 1; // 信息素重要程度因子
    static double beta = 5; // 启发函数重要程度因子
    static double rho = 0.1; // 信息素挥发因子
    static double Q = 1; // 常系数
    private static double[][] distance; // 距离矩阵
    private static double[][] eta; // 启发函数
    private static double[][] tau; // 信息素
    private static int[][] table; // 路径表
    private static int itermax = 200;
    private static Vector<Integer> allowedCities = new Vector<Integer>(); // 允许搜索的城市

    private static double length[];

    private static double bestlength[];
    private static Random random  = new Random(System.currentTimeMillis());

    public static void main(String[] args) throws IOException {

        // 距离初始化
        initDistance();

        // 启发函数初始化
        initEta();

        // 信息素初始化
        initTau();

        // 路径初始化
        initTable();

        length = new double[m];
        bestlength = new double[m];

        for (int i = 0; i < m; i++) {
            bestlength[i] = Double.MAX_VALUE;
        }
        // 迭代
        sovle();

        for (int i = 0; i < m; i++) {
            System.out.println(bestlength[i]);
        }
        double temp = Double.MAX_VALUE;
        for(int i = 0;i < m;i++)
        {
            if(temp > bestlength[i])
            {
                temp = bestlength[i];
            }
        }
        System.out.println(temp);

    }

    private static void sovle() {
        int iter = 0;

        while (iter <= itermax) {
            int[] start = new int[m];
            for (int i = 0; i < start.length; i++) {
                
                int firstCity = random.nextInt(cityNum);
                start[i] = firstCity;
            }

            for (int i = 0; i < start.length; i++) {
                table[i][0] = start[i];
            }

            for (int i = 0; i < m; i++) {
                Vector<Integer> visitedCity = new Vector<Integer>();
                visitedCity.add(start[i]);

                allowedCities.clear();
                for (int k = 0; k < cityNum; k++) {
                    allowedCities.add(k);
                }

                for (int j = 1; j < cityNum; j++) {
                    // 禁忌表

                    // 允许的城市
                    allowedCities.removeAll(visitedCity);

                    // 轮盘法选择
                    int target = selectNextCity(visitedCity.lastElement());

                    // 赋值路径
                    table[i][j] = target;

                    visitedCity.add(target);
                }
            }

            // 统计距离
            getToalLength();

            // 更新信息素
            updataTau();

            // 清空路径
            clearTable();

            iter++;
        }

    }

    private static void clearTable() {
        initTable();
    }

    private static void updataTau() {

        double[][] Delta_Tau = new double[cityNum][cityNum];
        for (int i = 0; i < cityNum; i++) {
            for (int j = 0; j < cityNum; j++) {
                Delta_Tau[i][j] = 0;
            }
        }

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < cityNum - 1; j++) {
                Delta_Tau[table[i][j]][table[i][j + 1]] += Q / length[i];
            }
            Delta_Tau[table[i][cityNum - 1]][table[i][0]] += Q / length[i];
        }

        // 信息素挥发
        for (int i = 0; i < cityNum; i++) 
        {
            for (int j = 0; j < cityNum; j++) {
                tau[i][j] = tau[i][j] * (1 - rho) + Delta_Tau[i][j];
            }
        }
    }

    private static void getToalLength() {
        
        for (int i = 0; i < m; i++) {
            length[i] =0;
            for (int j = 0; j < cityNum - 1; j++) {
                length[i] += distance[table[i][j]][table[i][j + 1]];
            }
            length[i] += distance[table[i][cityNum - 1]][table[i][0]];
            if (length[i] < bestlength[i]) {
                bestlength[i] = length[i];
            }
        }
    }

    private static int selectNextCity(int currentCity) {
        double[] p = new double[cityNum];
        double sum = 0;

        // 计算分母部分
        for (Integer i : allowedCities) {
            sum += Math.pow(tau[currentCity][i.intValue()], alpha)
                    * Math.pow(1.0 / distance[currentCity][i.intValue()], beta);
        }

        // 计算概率矩阵
        for (int i = 0; i < cityNum; i++) {
            boolean flag = false;
            for (Integer j : allowedCities) {
                if (i == j.intValue()) {
                    p[i] = (Math.pow(tau[currentCity][i], alpha) * Math
                            .pow(1.0 / distance[currentCity][i], beta)) / sum;
                    flag = true;
                    break;
                }
            }
            if (flag == false) {
                p[i] = 0.f;
            }
        }
        // 轮盘赌选择下一个城市
        
        
        double sleectP = random.nextFloat();
        int selectCity = 0;
        double sum1 = 0;
        for (int i = 0; i < cityNum; i++) {
            sum1 += p[i];
            if (sum1 >= sleectP) {
                selectCity = i;
                break;
            }
        }

        return selectCity;
    }

    

    

    private static void initTable() {
        table = new int[m][cityNum];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < cityNum; j++) {
                table[i][j] = -1;
            }
        }
    }

    private static void initTau() {
        tau = new double[cityNum][cityNum];
        for (int i = 0; i < cityNum; i++) {
            for (int j = 0; j < cityNum; j++) {
                tau[i][j] = 1;
            }
        }
    }

    private static void initEta() {
        eta = new double[cityNum][cityNum];
        for (int i = 0; i < cityNum; i++) {
            for (int j = 0; j < cityNum; j++) {
                if (distance[i][j] == 0) {
                    eta[i][j] = 10000;
                } else {
                    eta[i][j] = 1 / distance[i][j];
                }
            }
        }

    }

    private static void initDistance() {

        distance = new double[cityNum][cityNum];
        double[] x;
        double[] y;
        String strbuff = null;
        String filename = "c://data.txt";
        BufferedReader data = null;
        try {
            data = new BufferedReader(new InputStreamReader(
                    new FileInputStream(filename)));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        distance = new double[cityNum][cityNum];
        x = new double[cityNum];
        y = new double[cityNum];
        for (int i = 0; i < cityNum; i++) {
            // 读取一行数据,数据格式1 6734 1453
            try {
                strbuff = data.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 字符分割
            String[] strcol = strbuff.split(" ");
            x[i] = Double.valueOf(strcol[1]);// x坐标
            y[i] = Double.valueOf(strcol[2]);// y坐标
        }
        // 计算距离矩阵
        // 针对具体问题,距离计算方法也不一样,此处用的是att48作为案例,它有48个城市,距离计算方法为伪欧氏距离,最优值为10628
        for (int i = 0; i < cityNum - 1; i++) {
            distance[i][i] = 0.0001; // 对角线为0
            for (int j = i + 1; j < cityNum; j++) {
                double rij = Math
                        .sqrt(((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j])
                                * (y[i] - y[j])));
                {
                    distance[i][j] = rij;
                    distance[j][i] = distance[i][j];
                }
            }
            distance[cityNum - 1][cityNum - 1] = 0.0001;
        }
    }
}
 

数据,路径c://data.txt:

1 1304 2312
2 3639 1315
3 4177 2244
4 3712 1399
5 3488 1535
6 3326 1556
7 3238 1229
8 4196 1004
9 4312 790
10 4386 570
11 3007 1970
12 2562 1756
13 2788 1491
14 2381 1676
15 1332 695
16 3715 1678
17 3918 2179
18 4061 2370
19 3780 2212
20 3676 2578
21 4029 2838
22 4263 2931
23 3429 1908
24 3507 2367
25 3394 2643
26 3439 3201
27 2935 3240
28 3140 3550
29 2545 2357
30 2778 2826
31 2370 2975

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值