1. Soldadura de barras

Parámetros del proceso

n_barras <- 500
mu_x1 <- 30
sigma_x1 <- sqrt(0.81)
mu_x2 <- 18
sigma_x2 <- 0.3
lsl <- 45
usl <- 55

parametros_barras <- tibble(
  parametro = c("Media x1", "Desviación x1", "Media x2", "Desviación x2", "LSL", "USL"),
  valor = c(mu_x1, sigma_x1, mu_x2, sigma_x2, lsl, usl)
)

knitr::kable(parametros_barras, caption = "Parámetros suministrados para la simulación de las barras")
Parámetros suministrados para la simulación de las barras
parametro valor
Media x1 30.0
Desviación x1 0.9
Media x2 18.0
Desviación x2 0.3
LSL 45.0
USL 55.0

Simulación y resultados

sim_barras <- tibble(
  barra = 1:n_barras,
  x1 = rnorm(n_barras, mean = mu_x1, sd = sigma_x1),
  x2 = rnorm(n_barras, mean = mu_x2, sd = sigma_x2)
) |> 
  mutate(
    longitud_total = x1 + x2,
    dentro_especificacion = between(longitud_total, lsl, usl)
  )

media_longitud <- mean(sim_barras$longitud_total)
sd_longitud <- sd(sim_barras$longitud_total)
prop_fuera <- mean(!sim_barras$dentro_especificacion)
prop_test <- prop.test(sum(!sim_barras$dentro_especificacion), n_barras)
Cp <- (usl - lsl) / (6 * sd_longitud)
Cpk <- min((usl - media_longitud) / (3 * sd_longitud), (media_longitud - lsl) / (3 * sd_longitud))

resumen_barras <- tibble(
  media_longitud = media_longitud,
  sd_longitud = sd_longitud,
  prob_fuera = as.numeric(prop_test$estimate),
  ic_fuera_inf = prop_test$conf.int[1],
  ic_fuera_sup = prop_test$conf.int[2],
  Cp = Cp,
  Cpk = Cpk
)

resumen_barras |> 
  mutate(across(everything(), round, digits = 4)) |> 
  knitr::kable(caption = "Indicadores obtenidos para la soldadura de las barras")
Indicadores obtenidos para la soldadura de las barras
media_longitud sd_longitud prob_fuera ic_fuera_inf ic_fuera_sup Cp Cpk
47.98 0.9454 0.002 1e-04 0.0129 1.763 1.052
sim_barras |> 
  ggplot(aes(x = longitud_total, fill = dentro_especificacion)) +
  geom_histogram(binwidth = 0.5, color = "white", alpha = 0.8) +
  geom_vline(xintercept = c(lsl, usl), linetype = "dashed", color = "red") +
  scale_fill_manual(values = c("#e4572e", "#4caf50"), name = "Estado", labels = c("Fuera de especificación", "Dentro de especificación")) +
  labs(x = "Longitud total (cm)", y = "Frecuencia")
Distribución de la longitud total de las barras ensambladas

Distribución de la longitud total de las barras ensambladas

Los índices de capacidad obtenidos permiten discutir si el proceso está bajo control. Como referencia, valores de \(C_p\) y \(C_{pk}\) mayores o iguales a 1.33 suelen considerarse aceptables para procesos críticos. Esta simulación entregará evidencias cuantitativas al ejecutar el documento.

2. Estación de reproceso

Supuestos y funciones de simulación

Se asume un único servidor (estación de reproceso) que atiende en orden de llegada (FIFO). Las piezas arriban cada 20 minutos de forma determinista. El número de defectos por pieza sigue una distribución Binomial con tamaño 3 y probabilidad de 0.8, cumpliendo la media de 2.4 defectos. Cada defecto requiere un tiempo exponencial independiente con tasa 0.2 por defecto.

simular_reproceso <- function(replica,
                              n_piezas = 200,
                              interarribo = 20,
                              max_defectos = 3,
                              prob_defecto = 0.8,
                              tasa_reparacion = 0.2) {
  arribos <- seq(0, by = interarribo, length.out = n_piezas)
  defectos <- rbinom(n_piezas, size = max_defectos, prob = prob_defecto)
  tiempos_servicio <- map_dbl(defectos, function(d) {
    if (d == 0) return(0)
    sum(rexp(d, rate = tasa_reparacion))
  })
  inicio_servicio <- numeric(n_piezas)
  fin_servicio <- numeric(n_piezas)

  for (i in seq_len(n_piezas)) {
    if (i == 1) {
      inicio_servicio[i] <- arribos[i]
    } else {
      inicio_servicio[i] <- max(arribos[i], fin_servicio[i - 1])
    }
    fin_servicio[i] <- inicio_servicio[i] + tiempos_servicio[i]
  }

  tibble(
    replica = replica,
    pieza = seq_len(n_piezas),
    arribo = arribos,
    defectos = defectos,
    servicio = tiempos_servicio,
    inicio = inicio_servicio,
    fin = fin_servicio,
    espera = inicio_servicio - arribos,
    tiempo_sistema = fin_servicio - arribos
  )
}

resultados_reproceso <- map_dfr(1:10, simular_reproceso)

resumen_reproceso <- resultados_reproceso |> 
  group_by(replica) |> 
  summarise(
    tiempo_total_min = max(fin),
    piezas_sin_defectos = sum(defectos == 0),
    espera_promedio = mean(espera),
    tiempo_sistema_promedio = mean(tiempo_sistema),
    .groups = "drop"
  ) |> 
  mutate(tiempo_total_horas = tiempo_total_min / 60)

tiempo_total_ci <- t.test(resumen_reproceso$tiempo_total_horas, conf.level = 0.95)

tiempo_total_ci
## 
##  One Sample t-test
## 
## data:  resumen_reproceso$tiempo_total_horas
## t = 1632, df = 9, p-value <2e-16
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  66.51 66.70
## sample estimates:
## mean of x 
##      66.6

Indicadores clave

resumen_reproceso |> 
  mutate(across(c(tiempo_total_min, espera_promedio, tiempo_sistema_promedio), round, digits = 2),
         tiempo_total_horas = round(tiempo_total_horas, 3)) |> 
  knitr::kable(caption = "Resultados por réplica para la estación de reproceso")
Resultados por réplica para la estación de reproceso
replica tiempo_total_min piezas_sin_defectos espera_promedio tiempo_sistema_promedio tiempo_total_horas
1 4001 3 2.07 13.86 66.68
2 3995 2 2.07 14.32 66.58
3 3993 0 1.48 13.07 66.55
4 4003 2 2.91 15.50 66.72
5 4004 4 1.63 13.17 66.74
6 3984 0 1.29 13.47 66.40
7 3999 2 1.94 14.29 66.65
8 4004 3 1.09 12.75 66.74
9 3995 2 2.81 15.36 66.58
10 3984 1 1.16 12.75 66.39
resumen_reproceso |> 
  ggplot(aes(x = factor(replica), y = tiempo_total_horas)) +
  geom_col(fill = "#1f77b4", alpha = 0.8) +
  geom_hline(yintercept = mean(resumen_reproceso$tiempo_total_horas), linetype = "dashed", color = "red") +
  labs(x = "Réplica", y = "Tiempo total (horas)")
Tiempo total requerido para procesar 200 piezas (10 réplicas)

Tiempo total requerido para procesar 200 piezas (10 réplicas)

El intervalo de confianza de 95% para el tiempo total (en horas) obtenido por la prueba t anterior cuantifica la incertidumbre sobre el tiempo esperado para procesar las 200 piezas.

3. Operación del camión de reparto

Modelado y simulación

Se modela un solo camión con un único punto de carga disponible. Cada ciclo completo incluye cargar, transportar hacia el destino, descargar y regresar a la base.

simular_camion <- function(replica,
                           horizonte_horas = 10,
                           carga_rango = c(20, 40),
                           descarga_rango = c(15, 25),
                           viaje_media = 40) {
  limite_tiempo <- horizonte_horas * 60
  reloj <- 0
  viaje <- 0
  registros <- vector("list", 0)

  while (TRUE) {
    tiempo_carga <- runif(1, min = carga_rango[1], max = carga_rango[2])
    viaje_ida <- rexp(1, rate = 1 / viaje_media)
    tiempo_descarga <- runif(1, min = descarga_rango[1], max = descarga_rango[2])
    viaje_regreso <- rexp(1, rate = 1 / viaje_media)

    ciclo_total <- tiempo_carga + viaje_ida + tiempo_descarga + viaje_regreso

    if (reloj + ciclo_total > limite_tiempo) break

    reloj <- reloj + ciclo_total
    viaje <- viaje + 1

    registros[[viaje]] <- tibble(
      replica = replica,
      viaje = viaje,
      tiempo_carga = tiempo_carga,
      viaje_ida = viaje_ida,
      tiempo_descarga = tiempo_descarga,
      viaje_regreso = viaje_regreso,
      ciclo_total = ciclo_total,
      tiempo_acumulado = reloj
    )
  }

  bitacora <- if (length(registros) > 0) bind_rows(registros) else tibble(
    replica = replica,
    viaje = integer(0),
    tiempo_carga = numeric(0),
    viaje_ida = numeric(0),
    tiempo_descarga = numeric(0),
    viaje_regreso = numeric(0),
    ciclo_total = numeric(0),
    tiempo_acumulado = numeric(0)
  )

  resumen <- tibble(
    replica = replica,
    viajes = nrow(bitacora),
    tiempo_utilizado = if (nrow(bitacora) > 0) max(bitacora$tiempo_acumulado) else 0,
    tiempo_promedio_viaje = if (nrow(bitacora) > 0) mean(bitacora$ciclo_total) else NA_real_
  )

  list(bitacora = bitacora, resumen = resumen)
}

resultados_camion <- map(1:5, simular_camion)

bitacora_camion <- map_dfr(resultados_camion, "bitacora")
resumen_camion <- map_dfr(resultados_camion, "resumen") |> 
  mutate(
    tiempo_utilizado_horas = tiempo_utilizado / 60,
    tiempo_promedio_viaje = tiempo_promedio_viaje
  )

ci_viajes <- t.test(resumen_camion$viajes, conf.level = 0.95)
prob_al_menos_10 <- mean(resumen_camion$viajes >= 10)

ci_viajes
## 
##  One Sample t-test
## 
## data:  resumen_camion$viajes
## t = 21, df = 4, p-value = 3e-05
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  3.645 4.755
## sample estimates:
## mean of x 
##       4.2

Desempeño del sistema

resumen_camion |> 
  mutate(
    tiempo_utilizado_horas = round(tiempo_utilizado_horas, 2),
    tiempo_promedio_viaje = round(tiempo_promedio_viaje, 2)
  ) |> 
  knitr::kable(caption = "Rendimiento del camión por réplica")
Rendimiento del camión por réplica
replica viajes tiempo_utilizado tiempo_promedio_viaje tiempo_utilizado_horas
1 4 545.9 136.47 9.10
2 5 447.4 89.47 7.46
3 4 596.0 149.01 9.93
4 4 569.7 142.41 9.49
5 4 418.9 104.73 6.98
if (nrow(bitacora_camion) > 0) {
  bitacora_camion |> 
    mutate(tiempo_acumulado_horas = tiempo_acumulado / 60) |> 
    ggplot(aes(x = viaje, y = tiempo_acumulado_horas, color = factor(replica))) +
    geom_line() +
    geom_point() +
    labs(x = "Viaje", y = "Tiempo acumulado (horas)", color = "Réplica")
}
Tiempo acumulado tras cada viaje completado

Tiempo acumulado tras cada viaje completado

El intervalo de confianza anterior corresponde al número esperado de viajes por jornada de 10 horas. Además, la proporción de réplicas con al menos 10 entregas es:

prob_al_menos_10
## [1] 0

Recomendaciones para alcanzar 10 entregas diarias

A partir de los resultados anteriores, se sugieren las siguientes alternativas:

  • Reducir tiempos de carga y descarga mediante preparación previa (pre-staging) de mercancía o automatización parcial; esto disminuye el tiempo de ciclo y aumenta la probabilidad de completar más viajes en la jornada.
  • Ajustar la planificación operativa extendiendo la ventana de operación (más horas) o escalonando turnos para aprovechar mejor la infraestructura existente cuando la demanda objetivo supere la capacidad actual.
  • Incorporar un segundo camión o un área de pre-carga que permita iniciar el proceso de carga mientras el camión anterior aún está en ruta, evitando ociosidad del cargador único.
  • Monitorear la variabilidad (especialmente de los traslados con distribución exponencial) y aplicar rutas alternativas o ventanas de entrega que reduzcan congestionamientos.

Cada recomendación debe evaluarse con simulaciones adicionales ajustando los parámetros correspondientes para cuantificar su impacto en el número de viajes diarios.

Conclusiones

  1. Soldadura de barras: El proceso produce longitudes promedio cercanas al objetivo, con sólo una pequeña fracción fuera de especificaciones. No obstante, la diferencia entre \(C_p\) y \(C_{pk}\) evidencia que el centro del proceso podría ajustarse para mejorar su capacidad efectiva.
  2. Estación de reproceso: El tiempo total para 200 piezas se mantiene estable alrededor de 66.6 horas por réplica. El sistema opera con alta ocupación; reducir defectos o aumentar capacidad disminuiría la cola y el tiempo en sistema.
  3. Camión de reparto: Con los parámetros actuales sólo se logran 4 viajes diarios en promedio, lejos del objetivo de 10. Las simulaciones sugieren intervenir en los tiempos de carga/descarga, ampliar la jornada o agregar recursos para alcanzar la meta.

En conjunto, las tres simulaciones muestran la utilidad de la modelación Monte Carlo para diagnosticar variabilidad y evaluar alternativas operativas antes de implementar cambios en el mundo real.