Se nos pide simular la suma de dos barras que se van a soldar, \(x_1\) y \(x_2\). Tenemos que simular esto 500 veces.
Los datos que nos dan son:
Barra 1 (\(x_1\)): Se distribuye Normal.
Barra 2 (\(x_2\)): Se distribuye Normal.
Longitud Total (\(L\)): \(L = x_1 + x_2\)
Límites (Especificaciones): \(50 \pm 5\) cm.
Nos piden:
Vamos a generar los 500 números aleatorios para \(x_1\) y \(x_2\) y luego los sumamos.
set.seed(133) # Semilla
n <- 500 # Número de barras a simular
# Parámetros del problema
media_x1 <- 30
sd_x1 <- sqrt(0.81) # ¡No olvidar la raíz cuadrada!
media_x2 <- 18
sd_x2 <- 0.3
LSL <- 45
USL <- 55
# 1. Simulación
x1 <- rnorm(n, mean = media_x1, sd = sd_x1)
x2 <- rnorm(n, mean = media_x2, sd = sd_x2)
L_total <- x1 + x2 # Sumamos las longitudes
# 2. Guardamos en una tabla (data.frame)
datos_barras <- data.frame(
Barra_x1 = x1,
Barra_x2 = x2,
Largo_Total = L_total
)
# 3. Mostramos las primeras 6 para ver cómo quedaron
cat("Primeras 6 barras simuladas:\n")
## Primeras 6 barras simuladas:
kable(head(datos_barras), caption = "Resultados de las primeras 6 barras")
| Barra_x1 | Barra_x2 | Largo_Total |
|---|---|---|
| 30.08135 | 17.97225 | 48.05360 |
| 30.31253 | 18.06857 | 48.38110 |
| 29.28529 | 17.45720 | 46.74249 |
| 30.26515 | 18.66839 | 48.93354 |
| 31.11406 | 17.65687 | 48.77093 |
| 29.95745 | 18.31950 | 48.27695 |
Ahora usamos el vector L_total (que tiene los 500 resultados) para hacer los cálculos.
L <- L_total # Vector de resultados
# 1. Probabilidad de estar fuera (OOS - Out Of Specification)
barras_malas <- sum(L < LSL | L > USL)
prob_malas <- barras_malas / n
cat(paste("Barras simuladas:", n, "\n"))
## Barras simuladas: 500
cat(paste("Barras malas (fuera de 45-55 cm):", barras_malas, "\n"))
## Barras malas (fuera de 45-55 cm): 1
cat(paste("Estimador de la probabilidad de fallo:", round(prob_malas * 100, 2), "%\n\n"))
## Estimador de la probabilidad de fallo: 0.2 %
# 2. Índices de Capacidad (Cp y Cpk)
media_proceso <- mean(L)
sd_proceso <- sd(L)
# Fórmula del Cp (Capacidad potencial)
Cp <- (USL - LSL) / (6 * sd_proceso)
# Fórmulas del Cpk (Capacidad real)
Cpk_arriba <- (USL - media_proceso) / (3 * sd_proceso)
Cpk_abajo <- (media_proceso - LSL) / (3 * sd_proceso)
Cpk <- min(Cpk_arriba, Cpk_abajo) # El Cpk es el peor de los dos
# Imprimimos los resultados
cat(paste("Media del proceso (L_total):", round(media_proceso, 4), "\n"))
## Media del proceso (L_total): 47.9451
cat(paste("Desv. Estándar del proceso (L_total):", round(sd_proceso, 4), "\n\n"))
## Desv. Estándar del proceso (L_total): 0.9756
cat(paste("Índice Cp (Potencial):", round(Cp, 4), "\n"))
## Índice Cp (Potencial): 1.7084
cat(paste("Índice Cpk (Real):", round(Cpk, 4), "\n"))
## Índice Cpk (Real): 1.0063
Con un histograma podemos ver la “campana” de nuestros 500 resultados y compararla con los límites rojos (LSL y USL).
ggplot(data = datos_barras, aes(x = Largo_Total)) +
geom_histogram(binwidth = 0.2, fill = "skyblue", color = "black", alpha = 0.9) +
# Límites de especificación (los rojos)
geom_vline(xintercept = LSL, color = "red", linetype = "dashed", size = 1) +
geom_vline(xintercept = USL, color = "red", linetype = "dashed", size = 1) +
# Media de nuestro proceso (la azul)
geom_vline(xintercept = media_proceso, color = "blue", linetype = "dotted", size = 1.2) +
labs(title = "Distribución de Longitudes Totales vs Límites",
x = "Longitud Total (cm)",
y = "Frecuencia (de 500 barras)",
caption = "Líneas rojas = Límites (45 y 55). Línea azul = Media del proceso.") +
theme_light()
El profe pregunta si el proceso está bajo control (o, mejor dicho, si es capaz).
Respuesta: El proceso NO es capaz.
¿Por qué? La gráfica lo muestra perfecto. La campana es delgada (Cp alto), pero está descentrada. La media esperada del proceso es \(30 + 18 = 48\) cm. El centro de las especificaciones es \(50\) cm. El proceso está diseñado para producir barras de 48 cm, pero se espera que midan 50 cm.
Diagnóstico: El proceso tiene un error de centrado (o bias). No es un problema de variabilidad (ruido), sino de diseño. La media está muy pegada al límite inferior (45).
Aquí tenemos una cola. Llegan piezas a una estación de reparación.
Llegadas: 1 pieza cada 20 minutos (fijo, o sea, Determinístico).
Entidad (Pieza):
Servicio (Reparación):
Objetivo: ¿Cuánto tiempo (en minutos) se tarda en procesar 200 piezas?
Réplicas: 10.
Necesitamos un bucle para las 10 réplicas. Dentro, un bucle para las 200 piezas.
Tenemos que llevar dos variables de tiempo (relojes):
tiempo_llegada_pieza: A qué hora llega la pieza j.reloj_salida_taller: A qué hora se desocupa el taller
(esta es la clave).La pieza j no puede empezar a ser reparada hasta que
HAYA LLEGADO y hasta que el TALLER ESTÉ LIBRE. Por eso usamos
max(tiempo_llegada_pieza, reloj_salida_taller).
set.seed(456) # Semilla
n_replicas <- 10
n_piezas <- 200
llegada_cada <- 20 # min
lambda_defecto <- 0.2
media_t_defecto <- 1 / lambda_defecto # 5 min por defecto
prob_defecto <- 0.8 # p = 2.4 / 3
n_max_defectos <- 3
# Vector para guardar el tiempo final (el "Makespan") de cada réplica
tiempos_finales <- numeric(n_replicas)
# Bucle de Réplicas (i)
for (i in 1:n_replicas) {
# Inicializamos el reloj del taller en 0 para esta réplica
reloj_salida_taller <- 0
# Bucle de Piezas (j)
for (j in 1:n_piezas) {
# 1. ¿A qué hora llega esta pieza? (Determinístico)
tiempo_llegada_pieza <- j * llegada_cada
# 2. ¿Cuántos defectos trae? (Binomial)
n_defectos <- rbinom(1, size = n_max_defectos, prob = prob_defecto)
# 3. ¿Cuánto tiempo de servicio necesita? (Exponencial)
t_reparacion <- 0 # Si tiene 0 defectos, tarda 0
if (n_defectos > 0) {
# La media total de reparación es N_defectos * 5 min
media_total_reparacion <- n_defectos * media_t_defecto
# La tasa (lambda) es 1 / media
tasa_total_reparacion <- 1 / media_total_reparacion
# Sacamos el tiempo de servicio de una exponencial con esa tasa
t_reparacion <- rexp(1, rate = tasa_total_reparacion)
}
# 4. Lógica de cola: ¿Cuándo empieza la reparación?
tiempo_inicio_reparacion <- max(tiempo_llegada_pieza, reloj_salida_taller)
# 5. ¿A qué hora termina?
tiempo_fin_reparacion <- tiempo_inicio_reparacion + t_reparacion
# 6. Actualizamos el reloj del taller. Estará libre en este tiempo para la pieza (j+1)
reloj_salida_taller <- tiempo_fin_reparacion
}
# Guardamos el tiempo final de la última pieza (la 200) de esta réplica
tiempos_finales[i] <- reloj_salida_taller
}
Ahora vemos los 10 resultados (el tiempo total de la pieza 200) y sacamos el promedio.
# Hacemos una tabla con los resultados
tabla_resultados_p2 <- data.frame(
Replica = 1:n_replicas,
Tiempo_Final_Minutos = tiempos_finales,
Tiempo_Final_Horas = tiempos_finales / 60 # Para tener una idea
)
kable(tabla_resultados_p2,
caption = "Tiempo total (Makespan) para procesar 200 piezas",
digits = 2)
| Replica | Tiempo_Final_Minutos | Tiempo_Final_Horas |
|---|---|---|
| 1 | 4004.39 | 66.74 |
| 2 | 4010.40 | 66.84 |
| 3 | 4012.28 | 66.87 |
| 4 | 4045.99 | 67.43 |
| 5 | 4022.84 | 67.05 |
| 6 | 4039.27 | 67.32 |
| 7 | 4012.96 | 66.88 |
| 8 | 4010.39 | 66.84 |
| 9 | 4013.78 | 66.90 |
| 10 | 4033.18 | 67.22 |
# Calculamos el promedio
tiempo_promedio_p2 <- mean(tiempos_finales)
cat(paste("\n\nRespuesta:",
"El tiempo promedio (de 10 réplicas) para procesar las 200 piezas es de",
round(tiempo_promedio_p2, 2), "minutos."))
##
##
## Respuesta: El tiempo promedio (de 10 réplicas) para procesar las 200 piezas es de 4020.55 minutos.
graf_p2_puntos <- data.frame(
Replica = 1:n_replicas,
Tiempo_Final_Minutos = tiempos_finales,
Tiempo_Final_Horas = tiempos_finales / 60
)
## Visualización
ggplot(graf_p2_puntos, aes(x = factor(Replica), y = Tiempo_Final_Minutos)) +
geom_point(size = 3, color = "steelblue") +
geom_line(aes(group = 1), color = "gray40", linewidth = 1) +
labs(
title = "Tiempo total de procesamiento por réplica",
x = "Réplica",
y = "Tiempo total (minutos)",
caption = "Cada punto representa el tiempo total para procesar 200 piezas"
) +
theme_minimal(base_size = 13)
Este es un proceso cíclico con un solo camión. El ciclo es:
runif(1, 20, 40)rexp(1, 1/40)runif(1, 15, 25)rexp(1, 1/40)Nos piden:
Usamos un bucle for para las 5 réplicas. Dentro, usamos
un bucle while (reloj < 600) para simular los ciclos. Un
“viaje” se cuenta como completado después de la descarga.
Hay que tener cuidado con las condiciones de parada: * El camión debe poder terminar la descarga antes de los 600 min para que cuente como viaje. * El camión debe poder volver a la base antes de los 600 min para poder iniciar el siguiente ciclo.
set.seed(789)
n_replicas_p3 <- 5
t_simulacion <- 600 # 10 horas * 60 minutos
# Vector para guardar cuántos viajes hizo en cada réplica
viajes_por_replica <- numeric(n_replicas_p3)
# Data.frame para guardar el log de todos los viajes (trazabilidad)
log_todos_los_viajes <- data.frame()
# Bucle de las 5 réplicas
for (i in 1:n_replicas_p3) {
reloj <- 0
viajes_completos <- 0
# Bucle del Ciclo (mientras haya tiempo en el día)
while (TRUE) {
# Simular tiempos del ciclo
t_carga <- runif(1, min = 20, max = 40)
t_ida <- rexp(1, rate = 1/40)
t_descarga <- runif(1, min = 15, max = 25)
# Tiempo que gasta hasta la entrega
tiempo_hasta_entrega <- t_carga + t_ida + t_descarga
# Condición de parada 1: ¿Alcanza a hacer la entrega?
if (reloj + tiempo_hasta_entrega > t_simulacion) {
break # No alcanza, se acaba el día.
}
# Si alcanzó, actualizamos el reloj y contamos el viaje
reloj <- reloj + tiempo_hasta_entrega
viajes_completos <- viajes_completos + 1
# Ahora simulamos la vuelta
t_vuelta <- rexp(1, rate = 1/40)
# Guardamos el log de este viaje (antes de ver si puede volver)
log_todos_los_viajes <- rbind(log_todos_los_viajes, data.frame(
Replica = i,
Viaje_N = viajes_completos,
T_Carga = t_carga,
T_Ida = t_ida,
T_Descarga = t_descarga,
T_Vuelta = t_vuelta,
Tiempo_Acum_Fin_Ciclo = reloj + t_vuelta
))
# Condición de parada 2: ¿Alcanza a volver a la base para (potencialmente) otro viaje?
if (reloj + t_vuelta > t_simulacion) {
break # Quedó en la calle, no puede empezar otro ciclo.
}
# Si alcanzó a volver, actualizamos el reloj y el bucle while empieza de nuevo
reloj <- reloj + t_vuelta
}
# Guardamos el total de viajes de esta réplica
viajes_por_replica[i] <- viajes_completos
}
Estos son los viajes completados (descargas hechas) en las 10 horas de cada réplica.
tabla_resultados_p3 <- data.frame(
Replica = 1:n_replicas_p3,
Viajes_Completados = viajes_por_replica
)
kable(tabla_resultados_p3, caption = "Viajes Completados en 10 Horas")
| Replica | Viajes_Completados |
|---|---|
| 1 | 4 |
| 2 | 5 |
| 3 | 4 |
| 4 | 4 |
| 5 | 6 |
Usamos t.test() sobre los 5 resultados para estimar el
rango de la media real de viajes.
ic_p3 <- t.test(viajes_por_replica, conf.level = 0.95)
cat(paste("Media de viajes (de 5 réplicas):", round(ic_p3$estimate, 2), "\n"))
## Media de viajes (de 5 réplicas): 4.6
cat(paste("Intervalo de Confianza 95% para los viajes:",
"[", round(ic_p3$conf.int[1], 4),
",",
round(ic_p3$conf.int[2], 4),
"]\n"))
## Intervalo de Confianza 95% para los viajes: [ 3.4894 , 5.7106 ]
El objetivo es 10 entregas/día.
Análisis del problema: La simulación y el IC del 95% (que va de 3.5 a 5.7 viajes) nos dicen que con el sistema actual es imposible llegar a 10. Estamos haciendo 4 o 5.
¿Por qué? Calculemos el tiempo promedio de un ciclo:
Total Ciclo Esperado: \(30 + 40 + 20 + 40 = \mathbf{130 \text{ minutos}}\)
En un día de 10 horas (600 min), el número máximo teórico de viajes es: \(600 \text{ min} / 130 \text{ min/viaje} \approx 4.6\) viajes. La simulación confirma este cálculo teórico.
Recomendaciones:
Recomendación Final: Se debe comprar un segundo camión, pero se advierte que esto creará una cola en la bahía de carga. Se necesitaría un nuevo modelo de simulación (de colas G/G/1) para validar si el tiempo de espera en la carga anula la ganancia de tener el segundo camión.
Esta tabla muestra todos los viajes simulados en las 5 réplicas (los tiempos están en minutos).
| Replica | Viaje_N | T_Carga | T_Ida | T_Descarga | T_Vuelta | Tiempo_Acum_Fin_Ciclo |
|---|---|---|---|---|---|---|
| 1 | 1 | 34.00 | 103.02 | 15.12 | 7.33 | 159.46 |
| 1 | 2 | 29.84 | 150.25 | 20.73 | 68.50 | 428.78 |
| 1 | 3 | 27.18 | 43.13 | 18.14 | 0.60 | 517.82 |
| 1 | 4 | 25.05 | 28.24 | 16.56 | 11.62 | 599.29 |
| 2 | 1 | 26.06 | 36.40 | 19.96 | 25.86 | 108.29 |
| 2 | 2 | 30.06 | 63.15 | 19.90 | 31.24 | 252.63 |
| 2 | 3 | 28.73 | 6.63 | 17.83 | 62.14 | 367.96 |
| 2 | 4 | 35.75 | 20.23 | 24.98 | 78.02 | 526.94 |
| 2 | 5 | 23.29 | 11.48 | 24.21 | 92.08 | 678.00 |
| 3 | 1 | 34.91 | 36.40 | 15.36 | 50.82 | 137.49 |
| 3 | 2 | 38.57 | 55.09 | 24.20 | 24.33 | 279.68 |
| 3 | 3 | 30.99 | 35.90 | 22.04 | 56.47 | 425.09 |
| 3 | 4 | 33.35 | 18.31 | 22.50 | 17.14 | 516.39 |
| 4 | 1 | 21.88 | 73.21 | 19.19 | 51.55 | 165.83 |
| 4 | 2 | 25.48 | 0.48 | 22.46 | 12.05 | 226.29 |
| 4 | 3 | 39.22 | 24.85 | 24.47 | 40.31 | 355.14 |
| 4 | 4 | 35.78 | 26.39 | 23.97 | 94.65 | 535.93 |
| 5 | 1 | 25.22 | 18.74 | 20.67 | 26.94 | 91.57 |
| 5 | 2 | 25.42 | 29.51 | 23.90 | 22.93 | 193.34 |
| 5 | 3 | 23.27 | 34.38 | 19.81 | 18.34 | 289.14 |
| 5 | 4 | 32.55 | 6.61 | 16.16 | 10.47 | 354.93 |
| 5 | 5 | 32.93 | 47.49 | 24.88 | 21.45 | 481.69 |
| 5 | 6 | 34.20 | 49.62 | 23.34 | 4.57 | 593.42 |