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;
        }
  • 相关阅读:
    leetcode 576. Out of Boundary Paths 、688. Knight Probability in Chessboard
    leetcode 129. Sum Root to Leaf Numbers
    leetcode 542. 01 Matrix 、663. Walls and Gates(lintcode) 、773. Sliding Puzzle 、803. Shortest Distance from All Buildings
    leetcode 402. Remove K Digits 、321. Create Maximum Number
    leetcode 139. Word Break 、140. Word Break II
    leetcode 329. Longest Increasing Path in a Matrix
    leetcode 334. Increasing Triplet Subsequence
    leetcode 403. Frog Jump
    android中webView加载H5,JS不能调用问题的解决
    通过nginx中转获取不到IP的问题解决
  • 原文地址:https://www.cnblogs.com/uip001/p/15098470.html
Copyright © 2011-2022 走看看