如何實現一個高效的啓發式算法?(VRPTW篇)

上一期你們的反饋還不錯,但願小編多多寫寫這種相似心得的文章。恰好小編最近也要學新東西了,打算把以前學的東西都整理一下寫寫,但願給你們帶來一點小小的幫助吧~因此今天仍是基於上一篇的主題,不過今天講講VRP加上了TW以後的算法實現,如何去除冗餘。node

若是你們以爲還不錯的,能夠在末尾打賞一下小編,或者點個再看哦,大家的支持是小編深夜寫文稿最大的動力呢。web

1 時間窗的計算

其實不管是TSP或者是VRP,計算鄰居解的cost值都是很是簡便的。只須要用原解的值減去舊的邊再加上新的邊便可。不明白的小夥伴請回去好好看看上一期的內容哦。可是多了時間窗之後,難度又上升了一個量級。算法

時間窗爲何難呢,由於節點的前後順序是時間窗密切相關,而且前面的節點會影響到後面的節點。在經典的VRPTW中,規定了車輛早到必須等待,不容許晚到(若是晚到,該解不可行)。對於任意一個客戶 ,其時間窗爲 ,假如車輛到達該節點的時間點爲 ,那麼該節點的開始服務時間 爲:編程

由於早到必須等待,所以須要取二者中最大的。客戶 的服務時間爲 ,那麼車輛離開客戶 的時間點爲windows

你們看, 是否是決定了車輛到達下一個客戶的時間點呢?假如 以後的一個客戶是 ,車輛行駛邊<i,j>所須要的時間爲 ,則車輛到達客戶 的時間點爲:微信

好了如今原理講完了。下面講講鄰居解怎樣計算。app

2 鄰居解快速更新

我就拿以前的圖過來了,關於路徑cost的計算我就再也不多講了,這裏講講時間窗的更新,由於在VRPTW的問題中,目標值通常是路徑cost和時間窗違背的總和。假如解 的時間窗違背總量爲 ,顯然當 時, 爲可行解。那麼如何計算 呢?編輯器

發生變化的路徑爲 ,要評估鄰居解 的時間窗,固然了看過上一期的小夥伴確定不會整個解再從新計算一遍。能夠單獨把新的 拎出來,而後計算路徑的,再用解的減去路徑的便可。svg

因爲時間窗層層關聯的這種特性,對於快速計算 仍是有必定的難度,這種難度尤爲是提如今編碼的實現上,由於要維護大量的中間變量,所以大部分同窗的選擇就是將兩條路徑從新計算,省時省力。畢竟有時候選擇比努力重要得多。學習

不太小編固然不能退縮,所以今天就來說講鄰居解的時間窗如何去除計算冗餘。

首先咱們來看移除一個客戶的情景, 移除了客戶11和客戶17之間的一個客戶以後造成的 以下:

客戶節點變更只會影響該節點以後的節點時間窗,所以對於前半截路段0->15->12->11是不須要從新計算的。如今問題來了:對於後半段17->7->0上的全部節點須要從新所有更新嗎?

答案是不必定須要。只須要更新後面有可能發生改變的節點便可。那麼對於節點 而言,在原先的路徑中,車輛到達該節點的時間點爲 ,若是 ,其中 爲節點 的開始時間窗。那麼在新的路徑中,該節點以及該節點之後的節點都不須要進行更新了。

至於爲何,由於早到須要等待,若是在原先的路徑中,車輛早到了,那麼車輛的服務時間開始時間會重置到客戶的開始時間窗,在移除一個客戶後,那麼車輛在新的路徑中確定會比以前的更早到達。總之,新路徑中該客戶處的開始服務時間就是客戶的開始時間窗,與原路徑保持一致,該客戶以及後面全部的都無需更新了。

再來看看插入一個客戶 的場景:

客戶19以前的確定不用管了。更新須要從該客戶起,更新車輛到達客戶19的時間,而後是客戶2,一直到末尾。這裏也和上面的同樣,有一個臨界條件的,達到該條件後就能夠跳出更新。對於節點 而言,在新的(注意和上面的區別)的路徑中,車輛到達該節點的時間點爲 ,若是 ,其中 爲節點 的開始時間窗。那麼在新的路徑中,該節點以及該節點之後的節點都不須要進行更新了。

由於早到須要等待,若是在原先的路徑中,車輛早到了,那麼車輛的服務時間開始時間會重置到客戶的開始時間窗,在插入一個客戶後,那麼車輛在新的路徑中確定會比以前的更晚到達,若是新路徑中車輛到達客戶的時間點仍然小於等於客戶的開始時間窗,那麼該客戶以及後面全部的都無需更新了。

3 編程實現

固然了,仍是得放一下代碼,由於我們是實幹派,不吹牛皮不煲雞湯。對於時間窗,每一個客戶節點仍是須要維護一些中間變量的,難點就在於如何正確無誤的維護這些中間變量。寫去冗餘的啓發式難就難在調試……

首先是插入一個節點的代碼:

    /**
     * This function simulate the insertion of the customer in the given route on the given position.
     * Computes the new cost and return it.
     * It is an optimized version of the evaluate route. Calculates only for the customers affected
     * by the insertion. Starts from the given position and could finish before reaching the end of
     * the list if there is no modification in the arrive time at the customers.
     * Does not alter the route or the customer
     * @param route
     * @param customer
     * @param position
     * @return
     */

    private Cost evaluateInsertRoute(Route route, Customer customer, int position) {
     Cost varCost = new Cost(route.getCost());
     double arriveCustomer = 0;
     double arriveNextCustomer = 0;
     double waitingTimeCustomer = 0;
     double waitingTimeNextCustomer = 0;
     double twViolCustomer = 0;
     double twViolNextCustomer = 0;

     // if route is empty insert: depot - customer - depot
     if(route.isEmpty()) {
      varCost.initialize();
      // arrive time at the customer
      arriveCustomer = route.getDepot().getStartTw()
               + instance.getTravelTime(route.getDepotNr(), customer.getNumber());
         // waiting time for the customer if any
      waitingTimeCustomer = Math.max(0, customer.getStartTw() - arriveCustomer);
      // time window violation of the customer if any
      twViolCustomer = Math.max(0, arriveCustomer - customer.getEndTw());
      // arrive time at the depot
      arriveNextCustomer = Math.max(customer.getStartTw(), arriveCustomer)
                   + customer.getServiceDuration()
                   + instance.getTravelTime(customer.getNumber(), route.getDepotNr());
      // time window violation of the depot if any
      twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
      //variation of the travel time
      varCost.travelTime = instance.getTravelTime(route.getDepotNr(), customer.getNumber())
             + instance.getTravelTime(customer.getNumber(), route.getDepotNr());
      // variation of the capacity
      varCost.load = customer.getCapacity();
      // route service time
      varCost.serviceTime = customer.getServiceDuration();
      //variation of the waiting time
      varCost.waitingTime = waitingTimeCustomer;
      // variation of the time windows violation
      varCost.twViol = twViolCustomer + twViolNextCustomer;
      
     }else{     
      // insertion at the end of the list: customer before - customer - depot
      if(position == route.getCustomersLength()){
       Customer customerBefore = route.getCustomer(position - 1);
       arriveCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                + customerBefore.getServiceDuration()
                + instance.getTravelTime(customerBefore.getNumber(), customer.getNumber());
          // waiting time for the customer if any
       waitingTimeCustomer = Math.max(0, customer.getStartTw() - arriveCustomer);
       // time window violation of the customer if any
       twViolCustomer = Math.max(0, arriveCustomer - customer.getEndTw());
       // arrive time at the depot
       arriveNextCustomer = Math.max(customer.getStartTw(), arriveCustomer)
                    + customer.getServiceDuration()
                    + instance.getTravelTime(customer.getNumber(), route.getDepotNr());
       // time window violation of the depot if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
       //variation of the travel time
       varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), route.getDepotNr())
                       + instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
              + instance.getTravelTime(customer.getNumber(), route.getDepotNr());
       // variation of the capacity
       varCost.load += customer.getCapacity();
       // route service time
       varCost.serviceTime += customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime += waitingTimeCustomer;
       // variation of the time windows violation
       varCost.twViol += - varCost.depotTwViol + twViolCustomer + twViolNextCustomer;
      }else {
       double variation = 0;
       Customer customerAfter = route.getCustomer(position);
       // insertion on the first position: depot - customer - customer after
       if(position == 0){
        // time before arrive at the customer
        arriveCustomer = route.getDepot().getStartTw()
                 + instance.getTravelTime(route.getDepotNr(), customer.getNumber());
        //variation of the travel time
        varCost.travelTime += - instance.getTravelTime(route.getDepotNr(), customerAfter.getNumber())
                        + instance.getTravelTime(route.getDepotNr(), customer.getNumber())
               + instance.getTravelTime(customer.getNumber(), customerAfter.getNumber());
      
       // insertion in the middle of the list:  customer before - customer - customer after
       }else {
        Customer customerBefore = route.getCustomer(position - 1);
        // time before arrive at the customer
        arriveCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                 + customerBefore.getServiceDuration()
                 + instance.getTravelTime(customerBefore.getNumber(), customer.getNumber());
        //variation of the travel time
        varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), customerAfter.getNumber())
                        + instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
               + instance.getTravelTime(customer.getNumber(), customerAfter.getNumber());
       } // end if else beginning or middle
       
       // this code runs when inserting at the beginning or in the middle
          // waiting time for the customer if any
       waitingTimeCustomer = Math.max(0, customer.getStartTw() - arriveCustomer);
       // time window violation of the customer if any
       twViolCustomer = Math.max(0, arriveCustomer - customer.getEndTw());
       // before arrive time at the customer after
       arriveNextCustomer = Math.max(customer.getStartTw(), arriveCustomer)
                    + customer.getServiceDuration()
                    + instance.getTravelTime(customer.getNumber(), customerAfter.getNumber());
       // waiting time for the customer after if any
       waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
       // time window violation of the customer after if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
       
       // variation of the capacity
       varCost.load += customer.getCapacity();
       // route service time
       varCost.serviceTime += customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime += - customerAfter.getWaitingTime() + waitingTimeCustomer + waitingTimeNextCustomer;
       // variation of the time windows violation
       varCost.twViol +=  - customerAfter.getTwViol() + twViolCustomer + twViolNextCustomer;
       
//       variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
       variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
       variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation;

       // if there is a variation update the nodes after too
       int i = position + 1;
       while (variation != 0 && i < route.getCustomersLength()){ 
         customerAfter = route.getCustomer(i);
         // arrive at the customer after
         arriveNextCustomer = customerAfter.getArriveTime() + variation;
            waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
            twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
            //variation of the waiting time
            varCost.waitingTime += - customerAfter.getWaitingTime() + waitingTimeNextCustomer;
            // variation of the time windows violation
            varCost.twViol += - customerAfter.getTwViol() + twViolNextCustomer;
            
//            variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
            variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
            variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation;

            i++;
       }// end while
        
       if(i == route.getCustomersLength() && variation != 0 ){
        // update the return to the depot
        arriveNextCustomer = varCost.returnToDepotTime + variation;
        twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
        // variation of the time windows violation
           varCost.twViol += - varCost.depotTwViol + twViolNextCustomer;
           
       }// end if return to depot
       
       } // end if else of position cases
     } // end if else route is empty
     
  varCost.waitingTime = Math.abs(varCost.waitingTime) < instance.getPrecision() ? 0 : varCost.waitingTime;
  varCost.twViol = Math.abs(varCost.twViol) < instance.getPrecision() ? 0 : varCost.twViol;
     
  varCost.setLoadViol(Math.max(0, varCost.load - route.getLoadAdmited()));
  varCost.setDurationViol(Math.max(0, varCost.getDuration() - route.getDurationAdmited()));

  return varCost;
    } // end method evaluate insert route
 
 
 /**
  * This function simulate the deletion of a customer in the given route on the given position.
     * Computes the new cost and return it.
     * It is an optimized version of the evaluate route. Calculates only for the customers affected
     * by the deletion. Starts from the given position and could finish before reaching the end of
     * the list if there is no modification in the arrive time at the customers.
     * Does not alter the route.
  * @param route
  * @param position
  * @return
  */

    private Cost evaluateDeleteRoute(Route route, Customer customer, int position) {
     Cost varCost = new Cost(route.getCost());
     double arriveNextCustomer = 0;
     double waitingTimeNextCustomer = 0;
     double twViolNextCustomer = 0;

     // if route has only the customer that will be deleted
     if(route.getCustomersLength() - 1 == 0) {
      varCost.initialize();      
     
     }else{     
      // case when customer is the last one: customer before - depot
      if(position == route.getCustomersLength() - 1){
       Customer customerBefore = route.getCustomer(position - 1);
       //arrive time at the depot
       arriveNextCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                    + customerBefore.getServiceDuration()
                    + instance.getTravelTime(customerBefore.getNumber(), route.getDepotNr());
       // time window violation of the depot if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
       //variation of the travel time
       varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
              - instance.getTravelTime(customer.getNumber(), route.getDepotNr())
               + instance.getTravelTime(customerBefore.getNumber(), route.getDepotNr());
                     
       // variation of the capacity
       varCost.load -= customer.getCapacity();
       // route service time
       varCost.serviceTime -= customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime -= customer.getWaitingTime();
       // variation of the time windows violation
       varCost.twViol += - customer.getTwViol() - route.getDepotTwViol() + twViolNextCustomer;

      }else{
       double variation = 0;
       Customer customerAfter = route.getCustomer(position + 1);
       // delete on the first position
       if(position == 0){
        // time before arrive at customer after
        arriveNextCustomer = route.getDepot().getStartTw()
                           + instance.getTravelTime(route.getDepotNr(), customerAfter.getNumber());
        //variation of the travel time
        varCost.travelTime  += - instance.getTravelTime(route.getDepotNr(), customer.getNumber())
                - instance.getTravelTime(customer.getNumber(), customerAfter.getNumber())
                         + instance.getTravelTime(route.getDepotNr(), customerAfter.getNumber());
      
       // insertion in the middle of the list
       }else{
        Customer customerBefore = route.getCustomer(position - 1);
        // time before arrive at customer after
        arriveNextCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                           + customerBefore.getServiceDuration()
                           + instance.getTravelTime(customerBefore.getNumber(), customerAfter.getNumber());
        //variation of the travel time
        varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
               - instance.getTravelTime(customer.getNumber(), customerAfter.getNumber())
                        + instance.getTravelTime(customerBefore.getNumber(), customerAfter.getNumber());
        } // end if else beginning or middle
       // this code runs when inserting at the beginning or in the middle
       
          // waiting time for the customer after if any
       waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
       // time window violation of the customer after if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
       
       // variation of the capacity
       varCost.load -= customer.getCapacity();
       // route service time
       varCost.serviceTime -= customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime += - customer.getWaitingTime() - customerAfter.getWaitingTime() + waitingTimeNextCustomer;
       // variation of the time windows violation
       varCost.twViol += - customer.getTwViol() - customerAfter.getTwViol() +  twViolNextCustomer;
       
//       variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
//       variation = arriveNextCustomer -customerAfter.getArriveTime();
       variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
       variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation;   

       // if there is a variation update the nodes after too
       // the node after the customer is already updated
       int i = position + 2;
       while (variation != 0 && i < route.getCustomersLength()){ 
         customerAfter = route.getCustomer(i);
         // arrive at the customer after
         arriveNextCustomer = customerAfter.getArriveTime() + variation;
            waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
            twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
            //variation of the waiting time
            varCost.waitingTime += -customerAfter.getWaitingTime() + waitingTimeNextCustomer;
            // variation of the time windows violation
            varCost.twViol += -customerAfter.getTwViol() + twViolNextCustomer;
            
//            variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
//            variation = arriveNextCustomer -customerAfter.getArriveTime();
            variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
            variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation; 
                        
            i++;
       }// end while
        
       // update depot violation too if any
       if(i == route.getCustomersLength() && variation != 0 ){
        // update the return to the depot
        arriveNextCustomer = route.getReturnToDepotTime() + variation;
        twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
        // variation of the time windows violation
           varCost.twViol += - route.getDepotTwViol() + twViolNextCustomer;
                      
       }// end if return to depot
       
       
       
       
       } // end if else of position cases
     } // end if else route is empty

//     route.removeCustomer(position);
     // be careful about precision; if there are subtraction
  varCost.waitingTime = Math.abs(varCost.waitingTime) < instance.getPrecision() ? 0 : varCost.waitingTime;
  varCost.twViol = Math.abs(varCost.twViol) < instance.getPrecision() ? 0 : varCost.twViol;
  
  varCost.setLoadViol(Math.max(0, varCost.load - route.getLoadAdmited()));
  varCost.setDurationViol(Math.max(0, varCost.getDuration() - route.getDurationAdmited()));
  
  return varCost;
    } // end method evaluate delete route

而後是刪除一個客戶的代碼:

 /**
  * This function simulate the deletion of a customer in the given route on the given position.
     * Computes the new cost and return it.
     * It is an optimized version of the evaluate route. Calculates only for the customers affected
     * by the deletion. Starts from the given position and could finish before reaching the end of
     * the list if there is no modification in the arrive time at the customers.
     * Does not alter the route.
  * @param route
  * @param position
  * @return
  */

    private Cost evaluateDeleteRoute(Route route, Customer customer, int position) {
     Cost varCost = new Cost(route.getCost());
     double arriveNextCustomer = 0;
     double waitingTimeNextCustomer = 0;
     double twViolNextCustomer = 0;

     // if route has only the customer that will be deleted
     if(route.getCustomersLength() - 1 == 0) {
      varCost.initialize();      
     
     }else{     
      // case when customer is the last one: customer before - depot
      if(position == route.getCustomersLength() - 1){
       Customer customerBefore = route.getCustomer(position - 1);
       //arrive time at the depot
       arriveNextCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                    + customerBefore.getServiceDuration()
                    + instance.getTravelTime(customerBefore.getNumber(), route.getDepotNr());
       // time window violation of the depot if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
       //variation of the travel time
       varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
              - instance.getTravelTime(customer.getNumber(), route.getDepotNr())
               + instance.getTravelTime(customerBefore.getNumber(), route.getDepotNr());
                     
       // variation of the capacity
       varCost.load -= customer.getCapacity();
       // route service time
       varCost.serviceTime -= customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime -= customer.getWaitingTime();
       // variation of the time windows violation
       varCost.twViol += - customer.getTwViol() - route.getDepotTwViol() + twViolNextCustomer;

      }else{
       double variation = 0;
       Customer customerAfter = route.getCustomer(position + 1);
       // delete on the first position
       if(position == 0){
        // time before arrive at customer after
        arriveNextCustomer = route.getDepot().getStartTw()
                           + instance.getTravelTime(route.getDepotNr(), customerAfter.getNumber());
        //variation of the travel time
        varCost.travelTime  += - instance.getTravelTime(route.getDepotNr(), customer.getNumber())
                - instance.getTravelTime(customer.getNumber(), customerAfter.getNumber())
                         + instance.getTravelTime(route.getDepotNr(), customerAfter.getNumber());
      
       // insertion in the middle of the list
       }else{
        Customer customerBefore = route.getCustomer(position - 1);
        // time before arrive at customer after
        arriveNextCustomer = Math.max(customerBefore.getStartTw(), customerBefore.getArriveTime())
                           + customerBefore.getServiceDuration()
                           + instance.getTravelTime(customerBefore.getNumber(), customerAfter.getNumber());
        //variation of the travel time
        varCost.travelTime += - instance.getTravelTime(customerBefore.getNumber(), customer.getNumber())
               - instance.getTravelTime(customer.getNumber(), customerAfter.getNumber())
                        + instance.getTravelTime(customerBefore.getNumber(), customerAfter.getNumber());
        } // end if else beginning or middle
       // this code runs when inserting at the beginning or in the middle
       
          // waiting time for the customer after if any
       waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
       // time window violation of the customer after if any
       twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
       
       // variation of the capacity
       varCost.load -= customer.getCapacity();
       // route service time
       varCost.serviceTime -= customer.getServiceDuration();
       //variation of the waiting time
       varCost.waitingTime += - customer.getWaitingTime() - customerAfter.getWaitingTime() + waitingTimeNextCustomer;
       // variation of the time windows violation
       varCost.twViol += - customer.getTwViol() - customerAfter.getTwViol() +  twViolNextCustomer;
       
//       variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
//       variation = arriveNextCustomer -customerAfter.getArriveTime();
       variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
       variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation;   

       // if there is a variation update the nodes after too
       // the node after the customer is already updated
       int i = position + 2;
       while (variation != 0 && i < route.getCustomersLength()){ 
         customerAfter = route.getCustomer(i);
         // arrive at the customer after
         arriveNextCustomer = customerAfter.getArriveTime() + variation;
            waitingTimeNextCustomer = Math.max(0, customerAfter.getStartTw() - arriveNextCustomer);
            twViolNextCustomer = Math.max(0, arriveNextCustomer - customerAfter.getEndTw());
            //variation of the waiting time
            varCost.waitingTime += -customerAfter.getWaitingTime() + waitingTimeNextCustomer;
            // variation of the time windows violation
            varCost.twViol += -customerAfter.getTwViol() + twViolNextCustomer;
            
//            variation = Math.max(customerAfter.getStartTw(), arriveNextCustomer) - Math.max(customerAfter.getStartTw(), customerAfter.getArriveTime());
//            variation = arriveNextCustomer -customerAfter.getArriveTime();
            variation = arriveNextCustomer + waitingTimeNextCustomer - customerAfter.getArriveTime() - customerAfter.getWaitingTime();
            variation = Math.abs(variation) < instance.getPrecision() ? 0 : variation; 
                        
            i++;
       }// end while
        
       // update depot violation too if any
       if(i == route.getCustomersLength() && variation != 0 ){
        // update the return to the depot
        arriveNextCustomer = route.getReturnToDepotTime() + variation;
        twViolNextCustomer = Math.max(0, arriveNextCustomer - route.getDepot().getEndTw());
        // variation of the time windows violation
           varCost.twViol += - route.getDepotTwViol() + twViolNextCustomer;
                      
       }// end if return to depot
       
       
       
       
       } // end if else of position cases
     } // end if else route is empty

//     route.removeCustomer(position);
     // be careful about precision; if there are subtraction
  varCost.waitingTime = Math.abs(varCost.waitingTime) < instance.getPrecision() ? 0 : varCost.waitingTime;
  varCost.twViol = Math.abs(varCost.twViol) < instance.getPrecision() ? 0 : varCost.twViol;
  
  varCost.setLoadViol(Math.max(0, varCost.load - route.getLoadAdmited()));
  varCost.setDurationViol(Math.max(0, varCost.getDuration() - route.getDurationAdmited()));
  
  return varCost;
    } // end method evaluate delete route

完整代碼我會再作一期文章講解的,由於這個寫得實在是太經典了。來源是國外一個大學的一個課堂小組做業?嗯,就是大家上課上到一半老師忽然說我們作一個課堂小做業吧,而後你開始抽出一張白紙開始寫字的那種課堂做業。不得不認可,人家國外講課,仍是比較注重實踐呀~


推薦閱讀:
乾貨 | 想學習優化算法,不知從何學起?
乾貨 | 運籌學從何學起?如何快速入門運籌學算法?
乾貨 | 學習算法,你須要掌握這些編程基礎(包含JAVA和C++)
乾貨 | 算法學習必備訣竅:算法可視化解密
乾貨 | 模擬退火、禁忌搜索、迭代局部搜索求解TSP問題Python代碼分享

記得點個 在看 支持下哦~

本文分享自微信公衆號 - 程序猿聲(ProgramDream)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索