#================================================================
# Inventory simulation model under uncertainty
# based on Montecarlo simulation
#
# This model estimates the total cost and inventory for
# different value of quantity of product order per cycle,
# namely, given by Nq*StepQ.
#
# The model also shows a figure of unsatisfied demand probability.
#================================================================
# Coded and developed by Ebert Brea (c)2021
#===============================================================
rm(list=ls())
require(graphics)
require(latex2exp)
## Loading required package: latex2exp
require(stringi)
## Loading required package: stringi
require(stringr)
## Loading required package: stringr
require(lhs)
## Loading required package: lhs
library(triangle)
if(file.exists("filltxt")){close(filtxt)}
#==============================================================================
# Parameters of the simulation algorithm
#==============================================================================
R=1000 # Number of simulation replications
n0<-14 # Number of days per replacement cycle of product
Nq<-12 # Number of product quantity sampling
StepQ<-200 # Step of product quantity sampling
a<-0 # Minimum Demand of product
b<-250 # Maximum Demand of product
md<- 100 # mode of triangular distribution
hi<-10 # Inventory cost per day and per product unit
ho<-20 # Opportunity cost due to missing product, per day and product unit
###############################################################################
# Demand function according to id indicator
###############################################################################
# id=1 Uniform distribution demand
# id=2 Triangular distribution demand
id<-1
demand <-function(id){
if(id==1){return(runif(1,a,b))}
if(id==2){ return(rtriangle(1,a,b,md))}
}
########################################
inventory <-matrix( nrow=n0, ncol = R, byrow=TRUE)
totalcost <-matrix( nrow=R, ncol = 1)
risk <-matrix( nrow=Nq, ncol = 2, byrow=TRUE)
TC <- matrix( nrow=Nq, ncol = R)
TCSummary <- matrix( nrow=Nq, ncol = 6)
INV <- matrix( nrow=Nq, ncol = R)
fil <- tempfile("data")
##############################################################
# "R" simulation replications of "n0" days per cycle
##############################################################
for(iq in 1:Nq){
InvNegTime=0
SamplingTime=0
Tinv=0
TNegInv=0
risk[iq,1] = iq*StepQ
for(r in 1:R){
##############################################################
# Starting simulation replications
##############################################################
totalcost[r]=0
# Daily inventory at the end of the day 1
inventory[1,r] <- risk[iq,1] - demand(id)
# Daily cost
if(inventory[1,r] >= 0){
totalcost[r] <- totalcost[r] + hi*inventory[1,r]}
else{
totalcost[r] <- totalcost[r] - 1*ho*inventory[1,r]
NegInv <- 1
TNegInv <- TNegInv + inventory[1,r]
}
for(i in 2:n0){
NegInv = 0
# Daily inventory at the end of each ith day
inventory[i,r] <- inventory[i-1,r]-demand(id)
# Daily cost at the end of each ith day
if(inventory[i,r] >= 0){
totalcost[r] <- totalcost[r] + hi*inventory[i,r]}
else{
totalcost[r] <- totalcost[r] - 1*ho*inventory[i,r]
NegInv <- 1
TNegInv <- TNegInv + inventory[i,r]
}
}#end for i
InvNegTime <- InvNegTime + NegInv
#============================================================
# Collect Total Inventory Cost by StepQ & r
#============================================================
TC[iq,r] <- totalcost[r]
#============================================================
# Collect Inventory Cost by StepQ & r
#============================================================
INV[iq,r] <- inventory[n0,r]
}#end for r
#============================================================
# Estimation of Pr{inventory < 0} by StepQ
#===========================================================
risk[iq,2] = InvNegTime/R
#============================================================
# Statistic od Total cost by StepQ
#===========================================================
TCSummary[iq,1] <- min(TC[iq,])
TCSummary[iq,2] <- mean(TC[iq,])
TCSummary[iq,3] <- max(TC[iq,])
TCSummary[iq,4] <- quantile(TC[iq,],0.25)
TCSummary[iq,5] <- quantile(TC[iq,],0.50)
TCSummary[iq,6] <- quantile(TC[iq,],0.75)
}#end iq
#============================================================
# Graphic of Pr{inventory < 0} vs. q
#===========================================================
plot(ylim=c(0, 1),risk[,1],risk[,2],main=TeX('$p\\{\\sum_{k=1}^{n_{0}} D_{k}>q\\}$'),xlab=TeX('$q$'),ylab="Probability",type="l",lwd = 2,col="blue")
abline(h = 1, lty = 2, col = "red")
abline(h = 0, lty = 2, col = "blue")

print(risk)
## [,1] [,2]
## [1,] 200 1.000
## [2,] 400 1.000
## [3,] 600 1.000
## [4,] 800 1.000
## [5,] 1000 0.998
## [6,] 1200 0.968
## [7,] 1400 0.894
## [8,] 1600 0.731
## [9,] 1800 0.409
## [10,] 2000 0.185
## [11,] 2200 0.048
## [12,] 2400 0.004
#============================================================
# Graphic of Total Inventory Cost vs. q
#===========================================================
dfCost <- as.data.frame(TCSummary)
MaxLimit <-ceiling(max(TCSummary[,3])/1000)
plot(ylim=c(0, MaxLimit+1),risk[,1],dfCost$V1/1000,main="Total cost",xlab=TeX('$q$'),ylab="MUS$",type="l",lwd = 2,col="blue")
lines(risk[,1],dfCost$V2/1000,col="darkgreen",type="l",lwd = 2)
lines(risk[,1],dfCost$V3/1000,col="red",type="l",lwd = 2)
abline(h = MaxLimit, lty = 2, col = "black")
abline(h = 0, lty = 2, col = "black")
legend("topright",c("Maximum total cost","Average total cost","Minimum total cost"), fill=c("red","darkgreen","blue"))
