1. 程式人生 > 其它 >java實現模擬退火演算法解決配單最優路線

java實現模擬退火演算法解決配單最優路線

用java實現模擬退火演算法,解決遍歷所有限時訂單的最優路徑

double V0 = 0.1;//初始速度
        int T0 = 1000;//初始溫度
        double q = 0.98;//退火係數
        int N = orders.size();//樣本數量
        int L = N;//鏈長

        double T_end = 1e-6;//結束溫度
        int count = 0;//退火次數

        List<AlOrder> tempOrders = AlgorithmUtil.cloneOrders(orders);
        AlDriver tempDriver 
= driver.clone(); int oldNum = numCompute(tempOrders, tempDriver);//評估函式,計算解優度 List<AlOrder> bestOrders = AlgorithmUtil.cloneOrders(tempOrders);//最優解 AlDriver bestDriver = tempDriver.clone(); int bestNum = oldNum;//最優解優度 int T = T0;//初始溫度 while (T > T_end) {//
迴圈降溫直到溫度低於結束溫度 for (int i = 0; i < L; i++) { List<AlOrder> newOrders = createNewOrders(tempOrders);//生成新解(使用交換訂單等方法) AlDriver newDriver = driver.clone(); int newNum = numCompute(newOrders, newDriver);//評估函式,計算新解優度 double
dE = newNum - oldNum; //Metropolis準則 double r = Math.random(); if (dE < 0 || Math.exp(-dE / T) >= r) { tempOrders = newOrders;//更優解必定保留,更差解概率保留 tempDriver = newDriver; oldNum = newNum; if (newNum < bestNum) {//記錄最優解 bestOrders = newOrders; bestDriver = newDriver; bestNum = newNum; break;//產生最優解直接降溫一次 } } } T *= q; // 降溫 count++; } int num = 0; for (AlOrder bestOrder : bestOrders) { if (bestOrder.getDriverId() != null) { num++; } }

評估函式,以配送訂單最多,配送時間最少為最優。必須保證在指定時間範圍內送達

{
        int LOST_TIME = 180;
        //如果騎手配送起始時間戳為空,設定上班時間為配送起始時間
        if (driver.getStartTimeStamp() == null) {
            driver.setStartTimeStamp(TimeUtil.toTimeStamp(driver.getTimezone().substring(0, 5).trim(), true));
        }
        String origin = driver.getLocation();

        int lost = 0;
        int duration = 0;

        for (int i = 0; i < orders.size(); i++) {
            AlOrder nextOrder = orders.get(i);
            int startTimeStamp = driver.getStartTimeStamp();
            //計算配送結束時間
            String destination = nextOrder.getLocation();
            HashMap<String, String> realityDistance = DistanceUtil.getRealityDistance(origin, destination, driver.getSpeed());
            if ("true".equals(realityDistance.get(DistanceUtil.RESULT))) {
                int durationMin = (int) (Double.parseDouble(realityDistance.get(DistanceUtil.DURATION)) / 60 / driver.getSpeedUp());
                int endTimeStamp = startTimeStamp + durationMin;
                //獲取訂單的起始時間和結束時間
                int[] timezoneStamps = TimeUtil.timezoneToTimeStamp(nextOrder.getTimezone());
                int deadLine = timezoneStamps[timezoneStamps.length - 1];
                int aliveLine = timezoneStamps[0];
                if (endTimeStamp > deadLine || (driver.getDeadLineStamp() != null && endTimeStamp > driver.getDeadLineStamp())) {
                    lost++;
                } else {
                    //判斷如果配送時間超前,如果超前,延時至訂單的起始時間
                    if (endTimeStamp < aliveLine) {
                        endTimeStamp = aliveLine;
                        startTimeStamp = endTimeStamp - durationMin;
                    }
                    nextOrder.setStartTime(TimeUtil.toTime(startTimeStamp));
                    nextOrder.setPreDuration(durationMin);
                    nextOrder.setPreDistance(Integer.parseInt(realityDistance.get(DistanceUtil.DISTANCE)));
                    nextOrder.setDriverId(driver.getId());
                    driver.setStartTimeStamp(endTimeStamp + nextOrder.getWorkDuration());
                    driver.setLatitude(nextOrder.getLatitude());
                    driver.setLongitude(nextOrder.getLongitude());
                    duration += nextOrder.getTotalDuration();
                    origin = destination;
                }
            }
        }
        int result = lost * LOST_TIME + duration;
        return result*10;
    }