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; }