java實現模擬退火演算法解決配單最優路線
阿新 • • 發佈:2021-08-04
用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);//評估函式,計算新解優度 doubledE = 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; }