• 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;
        }
  • 相关阅读:
    HDU 5883 F
    关于codeblock 为什么不能调试
    Codeforces Round #378 (Div. 2) D. Kostya the Sculptor 分组 + 贪心
    51NOD 区间的价值 V2
    NYOJ 42 一笔画问题
    如何对二维字符数组进行排序
    hihoCoder 1383 : The Book List 北京网络赛
    利用IDA学习一个简单的安卓脱壳
    iOS APP可执行文件的组成
    Mac10.11 搭建php开发环境
  • 原文地址:https://www.cnblogs.com/uip001/p/15098470.html
Copyright © 2020-2023  润新知