Initializing help system before first use

Resource usage profiles


Type: Scheduling
Rating: 3 (intermediate)
Description: Special cases of resource constraints:
  • residle.mos: Preemptive scheduling ('resource idle times'); definition of resource usage profiles.
  • resprofile.mos: Scheduling with resource usage profiles; 'requires' constraints with sets of 'resusage'
  • altresource.mos: Scheduling with resource choice; 'requires' constraints with sets of 'resusage'
File(s): residle.mos, resprofile.mos, resprofile_graph.mos, altresource.mos, altresource_graph.mos


residle.mos
(!****************************************************************
   CP example problems
   ===================
   
   file residle.mos
   ````````````````
   Preemptive scheduling.

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2008, rev. Sep. 2018        
*****************************************************************!)
model "Preemption"
 uses "kalis"
 
 setparam("KALIS_DEFAULT_LB", 0)

 declarations
  aprofile,bprofile: list of integer
  a,b: cptask
  R: cpresource
 end-declarations 
 
! Define a discrete resource
 set_resource_attributes(R, KALIS_DISCRETE_RESOURCE, 3)

! Create a 'hole' in the availability of the resource:
! Uncomment one of the following two lines to compare their effect
! setcapacity(R, 1, 2, 0);  setcapacity(R, 7, 8, 0)
 setidletimes(R, (1..2)+(7..8))

! Define two tasks (a: constant resource use, b: resource profile) 
 a.duration >= 4
 a.name:= "task_a"
 aprofile:= [1,1,1,1]
 
 b.duration >= 8
 b.name:= "task_b"
 bprofile:= [1,1,1,2,2,2,1,1]
 
! Resource usage constraints 
 requires(a, resusage(R,aprofile))
 requires(b, resusage(R,bprofile)) 

 cp_set_solution_callback("print_solution")   

! Solve the problem 
 if cp_schedule(getmakespan)<>0 then
  cp_show_sol
 else
  writeln("No solution") 
 end-if

! ****************************************************************

 public procedure print_solution    
  writeln("Solution: ", getsol(getmakespan))
  writeln("Schedule: a: ", getsol(getstart(a)), "-", getsol(getend(a))-1,  
          ", b: ", getsol(getstart(b)), "-", getsol(getend(b))-1)
  writeln("Resource usage:")
  forall(t in 0..getsol(getmakespan)-1)
   writeln(strfmt(t,5), ": Cap: ", getcapacity(R,t), ", a:", 
           getrequirement(a, R, t), ", b:", getrequirement(b, R, t)) 
 end-procedure

end-model

resprofile.mos
(!****************************************************************
   CP example problems
   ===================
   
   file resprofile.mos
   ```````````````````
   Scheduling tasks with resource usage profiles.

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2008, rev. Sep. 2018        
*****************************************************************!)
model "Task resource usage profiles"
 uses "kalis"
 
 setparam("KALIS_DEFAULT_LB", 0)
 
 declarations
  TASKS = {"a","b","c","d"}           ! Index set of tasks
  Profile: array(TASKS) of list of integer   ! Task profiles
  DUR: array(TASKS) of integer        ! Durations of tasks
 
  T: array(TASKS) of cptask           ! Tasks
  R: cpresource                       ! Cumulative resource
 end-declarations 

 DUR::(["a","b","c","d"])[7, 9, 8, 5]
 Profile("a"):= [12, 12, 6, 2, 2, 2, 2]
 Profile("b"):= [12, 12, 6, 2, 2, 2, 2, 2, 2]
 Profile("c"):= [12, 12, 3, 3, 3, 3, 3, 3]
 Profile("d"):= [6, 6, 6, 6, 6]
 
! Define a discrete resource
 set_resource_attributes(R, KALIS_DISCRETE_RESOURCE, 18)
 R.name:="machine"
 
! Define tasks with profiled resource usage 
 forall(t in TASKS) do
  T(t).duration:= DUR(t)
  T(t).name:= t
  requires(T(t), resusage(R, Profile(t)))   
 end-do

 cp_set_solution_callback("print_solution")   
 starttime:=timestamp
 
! Solve the problem 
 if cp_schedule(getmakespan)=0 then
  writeln("No solution")
  exit(0)
 end-if

! Solution printing
 writeln("Schedule with makespan ", getsol(getmakespan), ":")
 forall(t in TASKS)
  writeln(t, ": ", getsol(getstart(T(t))), " - ", getsol(getend(T(t))))

! ****************************************************************

! Print solutions during enumeration at the node where they are found. 
! 'getrequirement' can only be used here to access solution information,
! not after the enumeration (it returns a value corresponding to the  
! current state, that is, 0 after the enumeration).
 public procedure print_solution    
  writeln(timestamp-starttime, "sec. Solution: ", getsol(getmakespan))

  forall(i in 0..getsol(getmakespan)-1) do
   write(strfmt(i,2), ": ")
   forall(t in TASKS | getrequirement(T(t), R, i)>0) 
    write(t, ":", getrequirement(T(t), R, i), "  " )
   writeln(" (total ", sum(t in TASKS) getrequirement(T(t), R, i), ")" )
  end-do   
 end-procedure

end-model

resprofile_graph.mos
(!****************************************************************
   CP example problems
   ===================
   
   file resprofile_graph.mos
   `````````````````````````
   Scheduling tasks with resource usage profiles.
   - Graphical solution representation -

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2008, rev. Sep. 2017        
*****************************************************************!)
model "Task resource usage profiles"
 uses "kalis", "mmsvg"
 
 setparam("KALIS_DEFAULT_LB", 0)
 
 declarations
  TASKS = {"a","b","c","d"}           ! Index set of tasks
  Profile: array(TASKS) of list of integer   ! Task profiles
  DUR: array(TASKS) of integer        ! Durations of tasks
 
  T: array(TASKS) of cptask           ! Tasks
  R: cpresource                       ! Cumulative resource
 end-declarations 

 DUR::(["a","b","c","d"])[7, 9, 8, 5]
 Profile("a"):= [12, 12, 6, 2, 2, 2, 2]
 Profile("b"):= [12, 12, 6, 2, 2, 2, 2, 2, 2]
 Profile("c"):= [12, 12, 3, 3, 3, 3, 3, 3]
 Profile("d"):= [6, 6, 6, 6, 6]
 
! Define a discrete resource
 set_resource_attributes(R, KALIS_DISCRETE_RESOURCE, 18)
 R.name:="machine"
 
! Define tasks with profiled resource usage 
 forall(t in TASKS) do
  T(t).duration:= DUR(t)
  T(t).name:= t
  requires(T(t), resusage(R, Profile(t)))   
 end-do

! Solve the problem 
 if cp_schedule(getmakespan)=0 then
  writeln("No solution")
  exit(0)
 end-if

 writeln("Solution: ", getsol(getmakespan))

! ************ Drawing a resource usage diagram ************

 declarations
  AProfile: array(TASKS) of array(S:range) of integer   ! Task profile arrays
 end-declarations 

 forall(t in TASKS) do
  ct:=1
  forall(l in Profile(t), ct as counter) AProfile(t,ct):=l
 end-do  

 L:=getsol(getmakespan)

 svgaddgroup("Res", "Resource capacity", SVG_RED)
 forall(i in 2..L)
  svgaddline([i-1, getcapacity(R,i-1), i-1, getcapacity(R,i), i, getcapacity(R,i)]) 

 declarations
  TLIST: list of string
 end-declarations 	

 ! Task graph colors
 ct:= 0
 forall(t in TASKS, ct as counter) do
  svgaddgroup(t, "Task "+t, svgcolor(25+ct*25, 25+ct*25, 50+ct*50))
  svgsetstyle(SVG_FILL,SVG_CURRENT)
 end-do 

 ! Order tasks by start times to obtain a nicer graph
 TCopy:= TASKS
 while (TCopy<>{}) do
  val:=L
  forall(t in TCopy)
   if getsol(getstart(T(t)))<val then
    val:=getsol(getstart(T(t)))
    ind:=t
   end-if 
  TLIST += [ind]
  TCopy-= {ind}
 end-do 

 ! Drawing task graphs
 forall(i in 1..L) do
  CUM:=0

  ! We cannot use 'getrequirement' here to access solution information
  ! if this graph is not drawn directly at the solution node
  forall(t in TLIST | i>getsol(getstart(T(t))) and i<=getsol(getend(T(t))) ) do
   REQ:= AProfile(t,i-getsol(getstart(T(t))))
   svgaddrectangle(t, i-1, CUM, 1, REQ)
   CUM+= REQ
  end-do 
 end-do 
 
 svgsetgraphscale(10)
 svgsetgraphviewbox(svggetgraphviewbox)
 svgsetgraphlabels("Time","Resource usage")

 svgsave("resprof.svg")
 svgrefresh
 svgwaitclose("Close browser window to terminate model execution.", 1)
end-model

altresource.mos
(!****************************************************************
   CP example problems
   ===================
   
   file altresource.mos
   ````````````````````
   Scheduling tasks with resource choice.

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2008, rev. Sep. 2018       
*****************************************************************!)
model "Alternative resources"
 uses "kalis"
 
 setparam("KALIS_DEFAULT_LB", 0)
 
 declarations
  TASKS = {"a","b","c","d"}           ! Index set of tasks
  MACH = {"M1", "M2"}                 ! Index set of resources
  USE: array(TASKS,MACH) of integer   ! Machine-dependent res. requirement
  DUR: array(TASKS) of integer        ! Durations of tasks
 
  T: array(TASKS) of cptask           ! Tasks
  R: array(MACH) of cpresource        ! Resources
 end-declarations 

 DUR::(["a","b","c","d"])[7, 9, 8, 5]
 USE::(["a","b","c","d"],["M1","M2"])[
      4, 3,
      2, 3,
      2, 1,
      4, 5]

! Define discrete resources
 forall(m in MACH)
  set_resource_attributes(R(m), KALIS_DISCRETE_RESOURCE, 5) 

! Define tasks with machine-dependent resource usages 
 forall(j in TASKS) do
  T(j).duration:= DUR(j)
  T(j).name:= j
  requires(T(j), union(m in MACH) {resusage(R(m), USE(j,m))})   
 end-do

 cp_set_solution_callback("print_solution")   
 starttime:=timestamp

! Solve the problem 
 if cp_schedule(getmakespan)=0 then
  writeln("No solution")
  exit(0)
 end-if

! Solution printing
 forall(j in TASKS)
  writeln(j, ": ", getsol(getstart(T(j))), " - ", getsol(getend(T(j))))
 forall(t in 1..getsol(getmakespan)) do
  write(strfmt(t-1,2), ": ")

  ! We cannot use 'getrequirement' here to access solution information
  ! (it returns a value corresponding to the current state, that is 0)
  forall(j in TASKS | t>getsol(getstart(T(j))) and t<=getsol(getend(T(j)))) 
   write(j, ":", 
         sum(m in MACH) USE(j,m)*getsol(getassignment(T(j),R(m))), "  " )
  writeln
 end-do   

! ****************************************************************

! Print solutions during enumeration at the node where they are found 
 public procedure print_solution    
  writeln(timestamp-starttime, "sec. Solution: ", getsol(getmakespan))

  forall(m in MACH) do
   writeln(m, ":")

   forall(t in 0..getsol(getmakespan)-1) do
    write(strfmt(t,2), ": ")
    forall(j in TASKS | getrequirement(T(j), R(m), t)>0) 
     write(j, ":", getrequirement(T(j), R(m), t), "  " )
    writeln(" (total ", sum(j in TASKS) getrequirement(T(j), R(m), t), ")" )
   end-do

  end-do 
 end-procedure

end-model

altresource_graph.mos
(!****************************************************************
   CP example problems
   ===================
   
   file altresource_graph.mos
   ``````````````````````````
   Scheduling tasks with resource choice.
   - Graphical solution representation -

   (c) 2008 Artelys S.A. and Fair Isaac Corporation
       Creation: 2008, rev. Sep. 2018       
*****************************************************************!)
model "Alternative resources"
 uses "kalis", "mmsvg"
 
 setparam("KALIS_DEFAULT_LB", 0)
 
 declarations
  TASKS = {"a","b","c","d"}           ! Index set of tasks
  MACH = {"M1", "M2"}                 ! Index set of resources
  USE: array(TASKS,MACH) of integer   ! Machine-dependent res. requirement
  DUR: array(TASKS) of integer        ! Durations of tasks
 
  T: array(TASKS) of cptask           ! Tasks
  R: array(MACH) of cpresource        ! Resources
 end-declarations 

 DUR::(["a","b","c","d"])[7, 9, 8, 5]
 USE::(["a","b","c","d"],["M1","M2"])[
      4, 3,
      2, 3,
      2, 1,
      4, 5]

! Define discrete resources
 forall(m in MACH) do
  set_resource_attributes(R(m), KALIS_DISCRETE_RESOURCE, 5)
  R(m).name:=m
 end-do 

! Define tasks with machine-dependent resource usages 
 forall(j in TASKS) do
  T(j).duration:= DUR(j)
  T(j).name:= j
  requires(T(j), union(m in MACH) {resusage(R(m), USE(j,m))})   
 end-do

 cp_set_solution_callback("print_solution")   
 starttime:=timestamp

! Solve the problem 
 if cp_schedule(getmakespan)=0 then
  writeln("No solution")
  exit(0)
 end-if

! Solution printing
 forall(j in TASKS)
  writeln(j, ": ", getsol(getstart(T(j))), " - ", getsol(getend(T(j))))
 forall(t in 1..getsol(getmakespan)) do
  write(strfmt(t-1,2), ": ")

  ! We cannot use 'getrequirement' here to access solution information
  ! (it returns a value corresponding to the current state, that is 0)
  forall(j in TASKS | t>getsol(getstart(T(j))) and t<=getsol(getend(T(j)))) 
   write(j, ":", 
         sum(m in MACH) USE(j,m)*getsol(getassignment(T(j),R(m))), "  " )
  writeln
 end-do   

! ****************************************************************

! Print solutions during enumeration at the node where they are found 
 public procedure print_solution    
  writeln(timestamp-starttime, "sec. Solution: ", getsol(getmakespan))

  forall(m in MACH) do
   writeln(m, ":")

   forall(t in 0..getsol(getmakespan)-1) do
    write(strfmt(t,2), ": ")
    forall(j in TASKS | getrequirement(T(j), R(m), t)>0) 
     write(j, ":", getrequirement(T(j), R(m), t), "  " )
    writeln(" (total ", sum(j in TASKS) getrequirement(T(j), R(m), t), ")" )
   end-do

  end-do 
 end-procedure

! ************ Drawing a resource usage diagram ************

 L:=maxlist(15,getsol(getmakespan))
 C:=5

 ct:=-1
 forall(m in MACH, ct as counter) do
  svgaddgroup(m, "Resource "+m, svgcolor(255,255-50*ct,200-75*ct))
  svgsetstyle(SVG_FILL,SVG_CURRENT)
  svgaddpolygon([0, C*ct]+sum(t in 0..L) [t, getcapacity(R(m),t)+C*ct]+ [L,C*ct])
 end-do
 
 declarations
  TLIST: list of string
 end-declarations 	

 ! Task graph colors
 ct:= 0
 forall(j in TASKS, ct as counter) do
  svgaddgroup(j, "Task "+j, svgcolor(75+ct*25, 75+ct*25, minlist(100+ct*50,255)))
  svgsetstyle(SVG_FILL,SVG_CURRENT)
 end-do

 ! Order tasks by start times to obtain a nicer graph
 TCopy:= TASKS
 while (TCopy<>{}) do
  val:=L
  forall(j in TCopy)
   if getsol(getstart(T(j)))<val then
    val:=getsol(getstart(T(j)))
    ind:=j
   end-if 
  TLIST += [ind]
  TCopy-= {ind}
 end-do 

 ! Drawing task graphs
 forall(t in 1..L) do
  ct:=-1
  forall(m in MACH, ct as counter) do
   CUM:=ct*C

  ! We cannot use 'getrequirement' here to access solution information
  ! if this graph is not drawn directly at the solution node
   forall(j in TLIST | getsol(getassignment(T(j),R(m)))>0 and
                       t>getsol(getstart(T(j))) and t<=getsol(getend(T(j))) ) do
    REQ:= USE(j,m)*getsol(getassignment(T(j),R(m)))
!    svgaddrectanglec(j, t-1, CUM, t, CUM+REQ)
    svgaddrectangle(j, t-1, CUM, 1, REQ)
    CUM+= REQ
   end-do 
  end-do
 end-do 
 
 svgsetgraphscale(20)
 svgsetgraphviewbox(0,0,L,2*C+1)
 svgsetgraphlabels("Time", "Resource usage")

 svgsave("altres.svg")
 svgrefresh
 svgwaitclose("Close browser window to terminate model execution.", 1)

end-model