File: LeungPalemPnueli.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (109 lines) | stat: -rw-r--r-- 4,035 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(*
 * This is my algorithm from PACT '98.
 *
 * -- Allen
 *)
structure LeungPalemPnueli :> LEUNG_PALEM_PNUELI =
struct

   structure G = Graph
   structure A = Array
   structure PQ = PriorityQueue

   exception Infeasible

   fun rank{dag,l,r,d,m} =
   let val G.GRAPH G = dag 
       val N         = #capacity G ()
       val r'        = A.array(N,0) (* modified release times *)
       val d'        = A.array(N,0) (* modified deadlines *)
       val r_hat     = A.array(N,0) (* backschedule modified release times *)
       val d_hat     = A.array(N,0) (* backschedule modified deadlines *)

       val node_ids  = map #1 (#nodes G ())

       fun initReleaseTimes() = 
       let fun update i =
               A.update(r',i,
                  foldr (fn (e as (j,_,_),r_i) => 
                           Int.max(A.sub(r',j) + l e + 1,r_i)) 
                        (r(i,#node_info G i)) (#in_edges G i))
       in  app update (GraphTopsort.topsort dag node_ids) end

       fun initDeadlines() = 
       let fun update i =
               A.update(d',i,
                  foldr (fn (e as (_,j,_),d_i) => 
                           Int.min(A.sub(d',j) - l e - 1,d_i)) 
                        (d (i,#node_info G i)) (#out_edges G i))
       in  app update (GraphTopsort.topsort (ReversedGraphView.rev_view dag) 
                       node_ids) 
       end


          (* unit time tasks, no-precedence constraints with
           * deadlines d_hat and release times r_hat.
           * I'm using an asymtotically slower (n log n) 
           * algorithm than the one described in the paper. 
           *)
       fun UET(S) =
       let fun byReleaseTimes(i,j) = A.sub(r_hat,i) > A.sub(r_hat,j)
           fun byDeadlines(i,j) = A.sub(d_hat,i) < A.sub(d_hat,j)
           val ready = PQ.create byDeadlines 
           val ins   = PQ.insert ready
           fun listSchedule(waiting,t,0) = listSchedule(waiting,t+1,m)
             | listSchedule(waiting,t,m) = 
               let val j = PQ.deleteMin ready
               in  t < A.sub(d_hat,j) andalso (* check for infeasbility! *)
                   listSchedule(waiting,t,m-1)
               end handle PQ.EmptyPriorityQueue =>
                   (* no more ready nodes *)
               let fun release(t,[]) = (t,[])
                     | release(t,l as j::waiting) = 
                        if A.sub(r_hat,j) > t then (t,l)
                        else (ins j; release(t,waiting))
               in  case waiting of
                     [] => true (* feasible *)
                   | waiting as j::_ => 
                     let val (t,waiting) = release(A.sub(r_hat,j),waiting)
                     in  listSchedule(waiting,t,m) end
               end
       in  listSchedule(ListMergeSort.sort byReleaseTimes S,0,m) end

       fun backSchedule(i,r'_i,S) = 
       let fun loop d'_i = 
           if r'_i >= d'_i then raise Infeasible
           else
           let val _ = A.update(d_hat,i,d'_i)
               val _ = A.update(r_hat,i,d'_i-1)
               val _ = app (fn e as (_,j,_) => 
                          A.update(r_hat,j,Int.max(d'_i + l e,A.sub(r',j))))
                            (#out_edges G i)
           in  if UET S then d'_i 
               else loop(d'_i-1)
           end
  
       in  app (fn j => (A.update(d_hat,j,A.sub(d',j));
                         A.update(r_hat,j,A.sub(r',j)))) S;
           loop(A.sub(d',i)) 
       end

       fun mainLoop([],_) = ()
         | mainLoop(i::U,S) = 
           let val r'_i = A.sub(r',i)
               val S = i::S
               val d'_i = backSchedule(i,r'_i,S)
           in  A.update(d',i,d'_i); 
               if d'_i <= r'_i then raise Infeasible 
               else mainLoop(U,S)
           end
       fun byNonIncreasingReleaseTimes(i,j) = A.sub(r',i) < A.sub(r',j)

   in  (* initialize the modified deadlines/release times *)
       initReleaseTimes();
       initDeadlines();
       mainLoop(ListMergeSort.sort byNonIncreasingReleaseTimes node_ids,[]);
       {r'=r',d'=d'}
   end

end