El grafo que se presenta a continuación representa la ejecuciòn de una obra elèctrica, en la que se contemplan cada uno de los pasos desde la reuniòn inicial, hasta la entrega del proyecto, inicialmente se plantean 24 días en total, como tiempo máximo de entrega sin contemplar los imprevistos que se puedan presentar.
A continuación se construye el modelo de simulación para el ejemplo del Gantt. En este primer escenario se le permite a la función la asignación de los tiempos para cada actividad.
df_predec <- read_delim("datos_gantt_electrico.csv",delim = ";")
simulacion_gantt <- function(){
df_actividad <- data.frame(id = seq(1,10),time = runif(n = 10,5,10), status = 0,ini_tim = NA, fin_tim = NA)
# identificar las actividades que no tienen presedencia e inician desde el principio
df_actividad$ini_tim[!(df_actividad$id %in% df_predec$actividad)] <- 0
# actualizar los tiempo de terminacion de la salida
df_actividad$fin_tim <- df_actividad$time + df_actividad$ini_tim
# actualizar el estado
df_actividad$status[!(is.na(df_actividad$fin_tim))] <- 1
while(sum(is.na(df_actividad$fin_tim))> 0){
# se actualiza la informacion de los tiempos de presedencia
df_predec_temp <- df_predec %>% left_join(df_actividad %>% dplyr::select(id,status,fin_tim), by =c("predecedor" ="id"))
# se identifican las presentes que todavia faltan por ser ejecutados
df_faltantes <- df_predec_temp %>% filter( status == 0)
# identificar las tareas que se pueden iniciar
vt_habil <- df_actividad$id[df_actividad$status == 0 & !(df_actividad$id %in% df_faltantes$actividad)]
# identificar el tiempo de inicio de cada actividad
df_time_fn <- df_predec_temp %>% filter(status == 1) %>% group_by(actividad) %>% summarise(max_tim = max(fin_tim))
# actualizar el tiempo de los que ya pueden iniciar
df_actividad$status[df_actividad$id %in% vt_habil ] <- 1
# traer el tiempo de inicio
df_actividad <- df_actividad %>% left_join(df_time_fn, by =c("id" = "actividad"))
# actualizar el tiempo de inicio
df_actividad$ini_tim[df_actividad$id %in% vt_habil ] <- df_actividad$max_tim[df_actividad$id %in% vt_habil]
# actualizar el tiempo de final
df_actividad$fin_tim[df_actividad$id %in% vt_habil ] <- df_actividad$ini_tim[df_actividad$id %in% vt_habil] + df_actividad$time[df_actividad$id %in% vt_habil]
# elminiar la columna de ayuda
df_actividad <- df_actividad %>% dplyr::select(-max_tim)
}
tiempo_final <- max(df_actividad$fin_tim)
return(tiempo_final)
}
Aplicación de la función simulacion_gantt
print(simulacion_gantt())
## [1] 52.99
vamos a realizar 4000 simulaciones para identificar
reps <- 1000
df_salidas <- data.frame(id = seq(1,1000), tiempo = NA)
for(k in 1:reps){
df_salidas$tiempo[k] <- simulacion_gantt()
}
library(ggplot2)
# Crear la gráfica con ggplot
D_tiempos <- ggplot(data = df_salidas, aes(x = tiempo)) +
geom_histogram(binwidth = 0.5, fill = "#0D0887", color = "#6BD7AF", alpha = 0.7) + # Ajustar color y transparencia
labs(title = "Distribución de Tiempos de Simulación", x = "Tiempo", y = "Frecuencia") + # Agregar título y etiquetas de ejes
theme_light() + # Seleccionar un tema de fondo claro
theme(plot.title = element_text(hjust = 0.5)) + # Centrar el título
xlim(range(df_salidas$tiempo)) + # Ajustar los límites del eje x
scale_x_continuous(breaks = seq(min(df_salidas$tiempo), max(df_salidas$tiempo), by = 5)) # Definir los intervalos de las marcas en el eje x
D_tiempos
Probabilidades a través del metodo frecuentista
df_salidas %>% filter(tiempo <= 23) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 30) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 40) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 50) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 60) %>% summarise(cant = n(), prob = cant/reps)
Se descarta la posibilidad de permitirle a la función la asignación de los tiempos sin restricción.
ASIGNACIÓN DE TIEMPOS REALES
Al reconocer la variabilidad de los procesos relacionados en el Grafo inicial, se definen los tiempos posibles para cada actividad y sus posibles rangos de variación.
library(readr)
library(dplyr)
df_predec <- read_delim("datos_gantt_electrico.csv",delim = ";")
simulacion_gantt <- function(){
df_actividad <- data.frame(id = seq(1,10),time = c(runif(1,1,2),
runif(1,4,6),
runif(1,2,4),
runif(1,1,3),
runif(1,3,5),
runif(1,4,6),
runif(1,3,5),
runif(1,1,3),
runif(1,1,5),
runif(1,1,2)),
status = 0,ini_tim = NA, fin_tim = NA)
# identificar las actividades que no tienen presedencia e inician desde el principio
df_actividad$ini_tim[!(df_actividad$id %in% df_predec$actividad)] <- 0
# actualizar los tiempo de terminacion de la salida
df_actividad$fin_tim <- df_actividad$time + df_actividad$ini_tim
# actualizar el estado
df_actividad$status[!(is.na(df_actividad$fin_tim))] <- 1
while(sum(is.na(df_actividad$fin_tim))> 0){
# se actualiza la informacion de los tiempos de presedencia
df_predec_temp <- df_predec %>% left_join(df_actividad %>% dplyr::select(id,status,fin_tim), by =c("predecedor" ="id"))
# se identifican las presentes que todavia faltan por ser ejecutados
df_faltantes <- df_predec_temp %>% filter( status == 0)
# identificar las tareas que se pueden iniciar
vt_habil <- df_actividad$id[df_actividad$status == 0 & !(df_actividad$id %in% df_faltantes$actividad)]
# identificar el tiempo de inicio de cada actividad
df_time_fn <- df_predec_temp %>% filter(status == 1) %>% group_by(actividad) %>% summarise(max_tim = max(fin_tim))
# actualizar el tiempo de los que ya pueden iniciar
df_actividad$status[df_actividad$id %in% vt_habil ] <- 1
# traer el tiempo de inicio
df_actividad <- df_actividad %>% left_join(df_time_fn, by =c("id" = "actividad"))
# actualizar el tiempo de inicio
df_actividad$ini_tim[df_actividad$id %in% vt_habil ] <- df_actividad$max_tim[df_actividad$id %in% vt_habil]
# actualizar el tiempo de final
df_actividad$fin_tim[df_actividad$id %in% vt_habil ] <- df_actividad$ini_tim[df_actividad$id %in% vt_habil] + df_actividad$time[df_actividad$id %in% vt_habil]
# elminiar la columna de ayuda
df_actividad <- df_actividad %>% dplyr::select(-max_tim)
}
tiempo_final <- max(df_actividad$fin_tim)
return(tiempo_final)
}
Aplicación de la función simulacion_gantt
El tiempo medio coincide con lo estimado inicialmente en la planeación de obra.
print(simulacion_gantt())
## [1] 25.09761
Se realizan 1000 simulaciones para identificar los diferentes escenarios posibles
reps <- 1000
df_salidas <- data.frame(id = seq(1,1000), tiempo = NA)
for(k in 1:reps){
df_salidas$tiempo[k] <- simulacion_gantt()
}
library(ggplot2)
# Crear la gráfica con ggplot
D_tiempos <- ggplot(data = df_salidas, aes(x = tiempo)) +
geom_histogram(binwidth = 0.5, fill = "#0D0887", color = "#6BD7AF", alpha = 0.7) + # Ajustar color y transparencia
labs(title = "Distribución de Tiempos de Simulación", x = "Tiempo", y = "Frecuencia") + # Agregar título y etiquetas de ejes
theme_light() + # Seleccionar un tema de fondo claro
theme(plot.title = element_text(hjust = 0.5)) + # Centrar el título
xlim(range(df_salidas$tiempo)) + # Ajustar los límites del eje x
scale_x_continuous(breaks = seq(min(df_salidas$tiempo), max(df_salidas$tiempo), by = 5)) # Definir los intervalos de las marcas en el eje x
D_tiempos
df_salidas %>% filter(tiempo <= 15) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo <= 19) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 20) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 24) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 30) %>% summarise(cant = n(), prob = cant/reps)
se define como un tiempo factible los 24 días planteados al inicio del proyecto toda vez que se puede asegurar con una probabilidad de 0.845 la ejecución del proyecto.
Habitualmente durante la ejecución de una obra eléctrica se presentan dos escenarios que pueden marcar la diferencia en la entrega oportuna y la solucitud de ampliación en tiempo y recurso del proyecto, en este escenario se contempla que la compra de materiales y la entrega en sitio puede variar razones de ello pueden ser la importación de materiales y la puesta en el lugar de ejecución de la obra, así mismo la instalación de los paneles solares dependerá del clima, en este escenario, las demás variables se mantendran fijas y sólo se variarán la compra de materiales y la instalación de los paneles solares, esta variación se llevará a un extremo y posteriormente de evaluará si se puede mantener el tiempo inicialmente proyectado de 24 días.
library(readr)
library(dplyr)
df_predec <- read_delim("datos_gantt_electrico.csv",delim = ";")
simulacion_gantt <- function(){
df_actividad <- data.frame(id = seq(1,10),time = c(runif(1,1,1),
runif(1,5,5),
runif(1,2,12),
runif(1,1,1),
runif(1,3,3),
runif(1,5,5),
runif(1,3,10),
runif(1,2,2),
runif(1,1,1),
runif(1,2,2)),
status = 0,ini_tim = NA, fin_tim = NA)
# identificar las actividades que no tienen presedencia e inician desde el principio
df_actividad$ini_tim[!(df_actividad$id %in% df_predec$actividad)] <- 0
# actualizar los tiempo de terminacion de la salida
df_actividad$fin_tim <- df_actividad$time + df_actividad$ini_tim
# actualizar el estado
df_actividad$status[!(is.na(df_actividad$fin_tim))] <- 1
while(sum(is.na(df_actividad$fin_tim))> 0){
# se actualiza la informacion de los tiempos de presedencia
df_predec_temp <- df_predec %>% left_join(df_actividad %>% dplyr::select(id,status,fin_tim), by =c("predecedor" ="id"))
# se identifican las presentes que todavia faltan por ser ejecutados
df_faltantes <- df_predec_temp %>% filter( status == 0)
# identificar las tareas que se pueden iniciar
vt_habil <- df_actividad$id[df_actividad$status == 0 & !(df_actividad$id %in% df_faltantes$actividad)]
# identificar el tiempo de inicio de cada actividad
df_time_fn <- df_predec_temp %>% filter(status == 1) %>% group_by(actividad) %>% summarise(max_tim = max(fin_tim))
# actualizar el tiempo de los que ya pueden iniciar
df_actividad$status[df_actividad$id %in% vt_habil ] <- 1
# traer el tiempo de inicio
df_actividad <- df_actividad %>% left_join(df_time_fn, by =c("id" = "actividad"))
# actualizar el tiempo de inicio
df_actividad$ini_tim[df_actividad$id %in% vt_habil ] <- df_actividad$max_tim[df_actividad$id %in% vt_habil]
# actualizar el tiempo de final
df_actividad$fin_tim[df_actividad$id %in% vt_habil ] <- df_actividad$ini_tim[df_actividad$id %in% vt_habil] + df_actividad$time[df_actividad$id %in% vt_habil]
# elminiar la columna de ayuda
df_actividad <- df_actividad %>% dplyr::select(-max_tim)
}
tiempo_final <- max(df_actividad$fin_tim)
return(tiempo_final)
}
Aplicación de la función simulacion_gantt
El tiempo medio coincide con lo estimado inicialmente en la planeación de obra.
print(simulacion_gantt())
## [1] 32.6295
Se realizan 1000 simulaciones para identificar los diferentes escenarios posibles
reps <- 1000
df_salidas <- data.frame(id = seq(1,1000), tiempo = NA)
for(k in 1:reps){
df_salidas$tiempo[k] <- simulacion_gantt()
}
library(ggplot2)
# Crear la gráfica con ggplot
D_tiempos <- ggplot(data = df_salidas, aes(x = tiempo)) +
geom_histogram(binwidth = 0.5, fill = "#0D0887", color = "#6BD7AF", alpha = 0.7) + # Ajustar color y transparencia
labs(title = "Distribución de Tiempos de Simulación", x = "Tiempo", y = "Frecuencia") + # Agregar título y etiquetas de ejes
theme_light() + # Seleccionar un tema de fondo claro
theme(plot.title = element_text(hjust = 0.5)) + # Centrar el título
xlim(range(df_salidas$tiempo)) + # Ajustar los límites del eje x
scale_x_continuous(breaks = seq(min(df_salidas$tiempo), max(df_salidas$tiempo), by = 5)) # Definir los intervalos de las marcas en el eje x
D_tiempos
df_salidas %>% filter(tiempo <= 15) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo <= 19) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 20) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 24) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 30) %>% summarise(cant = n(), prob = cant/reps)
df_salidas %>% filter(tiempo < 45) %>% summarise(cant = n(), prob = cant/reps)
La variación en los tiempos asociados a la compra de materiales y la instalación de los paneles solares pueden hacer que el tiempo de entrega supere el tiempo inicialmente proyectadeo, por lo que se sugiere la revisión de estos tiempos antes de la presentación formal de la propuesta ante el grupo directivo.