zoukankan      html  css  js  c++  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;
        }
  • 相关阅读:
    c++11强制转化类型
    关于parent指针以及对话框属性
    关于connect函数(Qt)
    lambda表达式
    学习过程中要注意的一些问题
    自动类型转换
    gakki
    排序算法(2)——简单选择排序和直接插入排序
    [Leetcode]414. Third Maximum Number
    [Leetcode]283. Move Zeroes
  • 原文地址:https://www.cnblogs.com/uip001/p/15098470.html
Copyright © 2011-2022 走看看