Q1

set.seed(10)
library(ggplot2)
library(reshape)
  # I will only deal with SRPT_pmtn and SPT_pmtn
FileSRPT <- function(n=1000,lambda=0.5,policy="SRPT_pmtn") {
  # simulates a M/GI/1 srpt queue with different preemption policy
  # parameters:
  #    n :  total number of jobs
  #    lambda : arrival rate
  #    policy: SRPT_pmtn, SPT_pmtn, SPT
  # return value:
  #    vector with response time of each task assuming the queue is initially empty
  
  A <- rexp(n,lambda)         # inter arrival
  t1 <- cumsum(A)             # arrival dates
  t2 <- rep(NA,n)  # completion dates
  S<-rexp(n)
  
  #### Variables that define the state of the queue
  t = 0               # time node of each event ocurring
  remaining = rep(NA,n)  # how much work remains to do for each task
  running = NA        # index of the currently running task
  waiting = c()       # stack with tasks which have arrived and have not been completed yet
  next_arrival = 1    # index of the next task to arrive
  
  get_task=function(temp=rep(0,n)){#choose a the right task
    running<<-switch(policy,
                     SRPT_pmtn=waiting[which.min(remaining)], #which.min() to get the index of mininum element
                     SPT_pmtn=waiting[which.min(temp)]
    )
  }
  
  #### A few useful local functions 
  run_task = function() { # runs the last task of the waiting list
    if(length(waiting)>0) {
      temp <- remaining
      if(policy == "SRPT_pmtn" & !is.na(running)){ 
        temp[running]<-S[running] 
        temp[waiting(length(waiting))] <- S[waiting(length(waiting))]
      }
      if(is.na(running))
        running<<-waiting[length(waiting)]
      else
        running <<- get_task(temp)
          
      remaining[running]<<-min(S[running],remaining[running],na.rm=T) 
      waiting <<- waiting[-length(waiting)]        
      
    }
  }
  
  #no change
  push_task = function() { 
        if(!is.na(running)) {
        waiting <<- c(waiting,running)
        }
        running <<- NA      
        waiting <<- c(waiting,next_arrival)
        next_arrival <<- next_arrival+1 
        if(is.na(running)) { run_task() }
    
  }
  
  #### Main simulation loop
  #no change
  while(TRUE) { 
    # Look for next event
    dt = NA
    if(next_arrival <=n) { dt = min(dt,(t1[next_arrival]-t), na.rm=T) }
    if(!is.na(running))  { dt = min(dt,remaining[running], na.rm=T)   }
    if(is.na(dt)) { break }
    
    # Update state
    t=t+dt 
    if(!is.na(running)) {
        remaining[running] = remaining[running] - dt
        if(remaining[running]<=0) { 
          t2[running]<- t 
            running = NA
            run_task()  
        }      
    }
    if((next_arrival<=n) & (t==t1[next_arrival])) { 
          push_task()
    }
  }
  
  t2-t1
} 

Q2

Service <- function(n=1,typeservice,x,y) {
# genere un temps de service
  switch(typeservice,
         det = seq(from=1,to=1,length.out=n),
         uni = runif(n,x,y),
         gamma = rgamma(n,shape=x,scale=y),
         exp = rexp(n,x)
         )
}

#FIFO
Response <- function(n,lambda,typeservice,x,y) {
    # genere une trajectoire de temps de reponse pour une file M/GI/1 FIFO
    # parametres :
    #    n :  taille de la trajectoire
    #    lambda : debit d'arrivee
    #    typeservice : type de service (det uni gamma exp)
    #    x ,y : parametres de la loi de service
    # valeur de retour :
    #    vecteur de n valeurs successives du temps de
    #    réponse dans une M/GI/1 FIFO initialement vide
    
    # generation des arrivees et des temps de service
    A <- rexp(n,lambda)
    t1 <- cumsum(A)
    S <- Service(n,typeservice,x,y)
    
    # initialisation des structures (pour éviter une allocation dynamique et gagner du temps)
    t2 <- seq(0,0,length.out=n)

    # Par curiosité comptons également le nombre de fois où le système se vide
    sys_vide = 1
    
    # initialisation du premier terme
    t2[1] <- t1[1]+ S[1]
    
    # calcul de la trajectoire equation de recurrence de Lindley
    for (i in 2:n) {
        t2[i] <- S[i] + max(t1[i], t2[i-1])
        if(t1[i]>t2[i-1]) {
          sys_vide = sys_vide + 1
        }
    }
        
    df=data.frame(arrival=t1,completion=t2,service=S)

    # Une itération sur ce que l'on vient de calculer pour calculer l'évolution de la
    # taille de la file d'attente au cours du temps.
    t1[n+1] = t2[n]+1;       # Un hack pour sortir de ma boucle
    date = rep.int(0,2*n);     # À initialiser absolument (performance + nom déjà utilisé) !
    count = rep.int(0,2*n);   
    i1 = i2 = 1;
    while(i1<=n | i2 <=n) {
      if(t1[i1]<t2[i2]) {
        date[i1+i2] <- t1[i1];
        count[i1+i2]<- count[i1+i2-1]+1;
        i1 <- i1+1;
      } else {
        date[i1+i2] <- t2[i2];
        count[i1+i2]<- count[i1+i2-1]-1;        
        i2 <- i2+1;
      }
    }
            
    # Une deuxième itération pour avoir l'évolution du travail au cours du temps.
    datework = rep.int(0,2*n);
    work =rep.int(0,2*n);
    i1 = i2 = 1;
    while(i1<=n | i2 <=n) {
      if(t1[i1]<t2[i2]) {
        i = 2*(i1+i2-1);
        datework[i] <- t1[i1];
        if(work[i-1]>0) {
           work[i] <- work[i-1] - (datework[i]-datework[i-1])
        } else {
           work[i] <- 0
        }
        if(work[i]<1e-15) { work[i]<-0 } # Fix floating point precision issue :( 
        datework[i+1] <- datework[i];
        work[i+1] <- work[i] + S[i1];
        
        i1 <- i1+1;
      } else {
        i = 2*(i1+i2-1);
        datework[i] <- t2[i2];
        work[i] <- work[i-1] - (datework[i]-datework[i-1]);
        datework[i+1] <- datework[i];
        work[i+1] <- work[i];

        i2 <- i2+1;
      }
    }

    df$completion - df$arrival
}    

df_fifo <- Response(n=1000, lambda=0.5,"exp",1,0)

df_srpt<-FileSRPT(n=1000,policy="SRPT_pmtn")

df_spt<-FileSRPT(n=1000,policy="SPT_pmtn")



dfr<-data.frame(SRPT_pmtn=df_srpt,SPT_pmtn=df_spt, FIFO=df_fifo) 
dfr$id=1:length(dfr$SRPT_pmtn)
d <- melt(dfr,id=c("id"))

ggplot(data=d[d$variable %in% c("SRPT_pmtn","SPT_pmtn", "FIFO"),],
       aes(x=id,y=value, color=variable)) + 
  geom_line(size=1) + scale_color_brewer(palette="Set1") +  xlab("Job Id") +
  ylab("Response Time") + 
  ggtitle("Response time")

sprintf("Average response time for SRPT_pmtn, SPT_pmtn and FIFO are %s, %s, %s",mean(df_srpt), mean(df_spt), mean(df_fifo) )
## [1] "Average response time for SRPT_pmtn, SPT_pmtn and FIFO are 1.75063251254203, 2.0920669595711, 1.84957006630721"

Q3

sprintf("Max response time for SRPT_pmtn, SPT_pmtn and FIFO are %s, %s, %s",max(df_srpt), max(df_spt), max(df_fifo) )
## [1] "Max response time for SRPT_pmtn, SPT_pmtn and FIFO are 28.2120779462152, 37.2354891224178, 14.3260307890545"