Problem solver for computing plans: Plan.oz

Source File

functor 
 
import 
   Search(base)
   FD
   Country(getDist getDetourDist)
   Configure(capacity: Capacity)
    
export 
   make: MakePlan
 
define 
 
   %% 
   %% Defaults used
   %% 
 
    
   proc {InsertSrc JA|Js Src Dst Weight What ?C ?NJs}
      case Js of nil then 
         if Src==JA.city then  
            NJs = [act(city:Src
                       load:Weight  
                       lift:What|JA.lift
                       drop:JA.drop)
                   act(city:Dst
                       load:0      
                       lift:nil
                       drop:[What])]
            C   = {Country.getDist Src Dst}
         else 
            NJs = [JA
                   act(city: Src
                       load: Weight
                       lift: [What]
                       drop: nil)  
                   act(city: Dst
                       load: 0
                       lift: nil
                       drop: [What])]
            C   = ({Country.getDist JA.city Src}
                   + {Country.getDist Src Dst})
         end 
      [] JB|then 
         NewLoad = JA.load + Weight
      in 
         if NewLoad>Capacity then 
            %% Job cannot placed here, because load would exceed the
            %% capacity of the truck
            NJs=JA|{InsertSrc Js Src Dst Weight What ?C}
         else 
            dis NewJob in 
               if Src==JA.city then 
                  %% Okay, the truck drives to this city anyway, so
                  %% simply add this good
                  NJs = (act(city: Src
                             load: NewLoad
                             lift: What|JA.lift
                             drop: JA.drop) = NewJob)
                      | {InsertDst NewJob Js Dst Weight What ?C}
               else TmpTour={FD.int 0#FD.sup} in 
                  %% Add the city to the towns the truck has to visit
                  NJs = (JA  
                         | (act(city: Src
                                load: NewLoad
                                lift: [What]
                                drop: nil) = NewJob)
                         | {InsertDst NewJob Js Dst Weight What ?TmpTour})
                  C =: TmpTour
                       + {Country.getDetourDist JA.city Src JB.city}
               end 
            [] % ...or somewhere else
               NJs=JA|{InsertSrc Js Src Dst Weight What ?C}
            end 
         end 
      end 
   end 
 
   proc {InsertDst JA Js Dst Weight What ?C ?NJs}
      %% JA is loaded with Order. Order.to has to be placed  
      %% after JA either between planned cities or on planned
      %% cities. Recursion tries to keep Order transported up to  
      %% cities later in Plan
      case Js of nil then 
         C   = {Country.getDist JA.city Dst}
         NJs = [act(city: Dst
                    load: 0
                    lift: nil
                    drop: [What])]
      [] JB|Jr then 
         dis 
            if JB.city==Dst then 
               C   = 0
               NJs = {AdjoinAt JB drop What|JB.drop} | Jr
            else 
               C   = {Country.getDetourDist JA.city Dst JB.city}
               NJs = act(city: Dst
                         load: JA.load-Weight
                         lift: nil
                         drop: [What]) | Js
            end 
         [] NewLoad = JB.load + Weight
            NewJob  = {AdjoinAt JB load NewLoad}
         in 
            NewLoad =<: Capacity
         then 
            NJs = NewJob | {InsertDst NewJob Jr Dst Weight What ?C}
         end 
      end 
   end 
 
   proc {MakePlan Tour Task ?Cost ?NewTour}
      Cost # NewTour = case {Search.base.best
                             proc {$ S}
                                C # NewTour = S
                             in 
                                C :: 0#FD.sup
                                {InsertSrc Tour Task.src Task.dst Task.weight
                                 Task.what ?C ?NewTour}
                             end 
                             proc {$ SA SB} SA.1>:SB.end}
                       of nil then false#Tour
                       [] [S] then S
                       end 
   end 
 
end 


Version 1.4.0 (20080702)