策码奔腾

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

 

posted @ 2021-08-04 13:34  策码奔腾  阅读(525)  评论(0编辑  收藏  举报
console.log('欢迎');