Vamos a simular la unión de dos barras (\(x_1, x_2\)) para formar una longitud total \(L\). El objetivo es ver si el proceso cumple con las especificaciones de \(50 \pm 5\) cm.
Generamos los 500 valores aleatorios para cada barra y los sumamos.
# 1. Parámetros
set.seed(153) # Semilla
n_barras <- 500
# Datos Barra 1
media_b1 <- 30
sd_b1 <- sqrt(0.81)
# Datos Barra 2
media_b2 <- 18
sd_b2 <- 0.3
# Especificaciones
LSL <- 45
USL <- 55
# 2. Generación de Vectores
b1_sim <- rnorm(n_barras, mean = media_b1, sd = sd_b1)
b2_sim <- rnorm(n_barras, mean = media_b2, sd = sd_b2)
largo_total_sim <- b1_sim + b2_sim # Vector de 500 longitudes finales
# 3. Guardar en un data.frame
datos_barras <- data.frame(
Barra1 = b1_sim,
Barra2 = b2_sim,
Largo_Total = largo_total_sim
)
# 4. Mostrar encabezado
cat("Primeros 6 resultados de la simulación:\n")
## Primeros 6 resultados de la simulación:
kable(head(datos_barras), caption = "Muestra de ensamblajes")
| Barra1 | Barra2 | Largo_Total |
|---|---|---|
| 32.53719 | 17.69284 | 50.23003 |
| 29.52825 | 17.52571 | 47.05396 |
| 31.07529 | 18.26569 | 49.34097 |
| 28.43308 | 17.71388 | 46.14697 |
| 29.59505 | 18.25342 | 47.84847 |
| 29.71280 | 18.17529 | 47.88809 |
Calculamos la tasa de falla y los índices de capacidad con los 500 largos totales.
# 1. Probabilidad de Falla (OOS - Fuera de Especificación)
piezas_malas <- sum(largo_total_sim < LSL | largo_total_sim > USL)
prob_malas <- piezas_malas / n_barras
cat(paste("Simulaciones totales:", n_barras, "\n"))
## Simulaciones totales: 500
cat(paste("Piezas defectuosas (OOS):", piezas_malas, "\n"))
## Piezas defectuosas (OOS): 0
cat(paste("Probabilidad de defecto estimada:", round(prob_malas * 100, 2), "%\n\n"))
## Probabilidad de defecto estimada: 0 %
# 2. Índices de Capacidad (Cp y Cpk)
# Usamos la media y sd de los 500 resultados simulados
media_real <- mean(largo_total_sim)
sd_real <- sd(largo_total_sim)
# Cp (Potencial)
Cp <- (USL - LSL) / (6 * sd_real)
# Cpk (Real - ajustado por centrado)
Cpk_sup <- (USL - media_real) / (3 * sd_real)
Cpk_inf <- (media_real - LSL) / (3 * sd_real)
Cpk <- min(Cpk_sup, Cpk_inf)
# 3. Imprimir métricas
cat(paste("Media Real del Proceso:", round(media_real, 4), "\n"))
## Media Real del Proceso: 47.8918
cat(paste("SD Real del Proceso:", round(sd_real, 4), "\n\n"))
## SD Real del Proceso: 0.9326
cat(paste("Índice Cp (Potencial):", round(Cp, 4), "\n"))
## Índice Cp (Potencial): 1.7872
cat(paste("Índice Cpk (Real):", round(Cpk, 4), "\n"))
## Índice Cpk (Real): 1.0337
Aquí usamos un histograma de Frecuencia para ver el conteo directo de barras y compararlo con los límites.
# Objetivo de diseño (Centro de las especificaciones)
objetivo_diseno <- (LSL + USL) / 2
# Media teórica del proceso (30 + 18)
media_teorica <- media_b1 + media_b2
ggplot(datos_barras, aes(x = Largo_Total)) +
# Histograma de Frecuencia (conteo)
geom_histogram(binwidth = 0.2, fill = "skyblue", color = "black", alpha = 0.9) +
# Líneas de Especificación (Rojas)
geom_vline(xintercept = LSL, color = "red", linetype = "dashed", size = 1) +
geom_vline(xintercept = USL, color = "red", linetype = "dashed", size = 1) +
# Línea de la Media Real (Azul punteado)
geom_vline(xintercept = media_real, color = "blue", linetype = "dotted", size = 1.2) +
# Línea del Objetivo de Diseño (Verde)
geom_vline(xintercept = objetivo_diseno, color = "darkgreen", linetype = "solid", size = 1) +
labs(title = "Distribución de Frecuencia del Proceso vs Límites",
x = "Largo Total (cm)",
y = "Frecuencia (Conteo de 500 barras)",
caption = "Rojo = Límites (45-55) | Verde = Objetivo (50) | Azul = Media Proceso (48)") +
theme_light()
Asumiendo que “bajo control” se refiere a “capacidad de cumplir especificaciones”:
Diagnóstico: El proceso NO es capaz.
Justificación: La gráfica lo dice todo. La campana (azul) es estrecha, lo cual es bueno (Cp alto), pero está centrada en 48 cm en lugar de estar centrada en el objetivo de 50 cm (verde). El problema es de centrado, no de variabilidad (o ruido).
Recomendación: Se debe re-diseñar el proceso. Por ejemplo, aumentar la media de la barra \(x_1\) a 32 cm (para que 32+18 = 50). Esto centraría el proceso y, como la variabilidad ya es baja, la tasa de fallos caería a cero.
Analizamos una cola con 1 servidor (la estación de reproceso).
Implementamos la lógica de cola
inicio = max(llegada, fin_servicio_anterior).
set.seed(456) # Semilla
n_replicas <- 10
n_piezas <- 200
llegada_cada_min <- 20
media_t_defecto <- 1 / 0.2 # 5 min
max_defectos <- 3
prob_defecto <- 2.4 / max_defectos # 0.8
# Vector para guardar el tiempo final de cada réplica
resultados_p2 <- numeric(n_replicas)
# Bucle (i) de Réplicas
for (i in 1:n_replicas) {
# El 'reloj_taller' guarda la hora en que el taller se desocupa
reloj_taller <- 0
# Bucle (j) de Piezas
for (j in 1:n_piezas) {
# 1. Tiempo de llegada de la pieza 'j'
t_llegada <- j * llegada_cada_min
# 2. Defectos de la pieza 'j'
k_defectos <- rbinom(1, size = max_defectos, prob = prob_defecto)
# 3. Tiempo de servicio para la pieza 'j'
t_servicio <- 0
if (k_defectos > 0) {
media_total <- k_defectos * media_t_defecto
tasa_total <- 1 / media_total
t_servicio <- rexp(1, rate = tasa_total)
}
# 4. Lógica de cola
t_inicio_servicio <- max(t_llegada, reloj_taller)
t_fin_servicio <- t_inicio_servicio + t_servicio
# 5. Actualizar el reloj del taller para la pieza 'j+1'
reloj_taller <- t_fin_servicio
}
# Guardar el tiempo final de la pieza 200 de esta réplica
resultados_p2[i] <- reloj_taller
}
Mostramos los 10 Makespan y su promedio.
# Tabla de resultados
tabla_p2 <- data.frame(
Replica = 1:n_replicas,
Tiempo_Final_Min = resultados_p2,
Tiempo_Final_Horas = resultados_p2 / 60
)
kable(tabla_p2,
caption = "Tiempo Total (Makespan) de 10 Réplicas",
digits = 2)
| Replica | Tiempo_Final_Min | 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 |
# Promedio
media_makespan <- mean(resultados_p2)
cat(paste("\n\nRespuesta:",
"El tiempo promedio (de 10 réplicas) para finalizar las 200 piezas es de",
round(media_makespan, 2), "minutos."))
##
##
## Respuesta: El tiempo promedio (de 10 réplicas) para finalizar las 200 piezas es de 4020.55 minutos.
Simulamos un camión en un ciclo de 4 pasos.
Usamos un bucle while que se rompe (break)
si el camión no alcanza a terminar la entrega o a volver a la base antes
de los 600 min.
set.seed(789) # Semilla
replicas_p3 <- 5
jornada_min <- 600
# Vector para guardar el # de viajes por réplica
total_viajes <- numeric(replicas_p3)
# Data.frame para guardar el log detallado
log_ciclos <- data.frame()
# Bucle (i) de Días (Réplicas)
for (i in 1:replicas_p3) {
reloj <- 0
viajes_dia <- 0
# Bucle (while) de Ciclos
while (TRUE) {
# 1. Simular tiempos de Carga, Ida y Descarga
t_carga <- runif(1, 20, 40)
t_ida <- rexp(1, 1/40)
t_descarga <- runif(1, 15, 25)
# 2. Condición de parada 1: ¿Alcanza a descargar?
t_hasta_entrega <- t_carga + t_ida + t_descarga
if (reloj + t_hasta_entrega > jornada_min) {
break # Se acaba el día, no alcanza a entregar
}
# 3. Si alcanzó: actualiza reloj y cuenta el viaje
reloj <- reloj + t_hasta_entrega
viajes_dia <- viajes_dia + 1
# 4. Simular la vuelta
t_vuelta <- rexp(1, 1/40)
# 5. Guardar log (opcional pero bueno para trazar)
log_ciclos <- rbind(log_ciclos, data.frame(
Replica = i, Viaje_N = viajes_dia,
T_Carga = t_carga, T_Ida = t_ida, T_Descarga = t_descarga, T_Vuelta = t_vuelta
))
# 6. Condición de parada 2: ¿Alcanza a volver?
if (reloj + t_vuelta > jornada_min) {
break # Terminó la entrega, pero no alcanza a volver a base
}
# 7. Si alcanzó a volver, actualiza el reloj y el 'while' sigue
reloj <- reloj + t_vuelta
}
# Guardar el total de viajes de este día (réplica i)
total_viajes[i] <- viajes_dia
}
cat("--- Resultados (Preguntas A y B) ---\n\n")
## --- Resultados (Preguntas A y B) ---
# a) Tabla de viajes
tabla_p3 <- data.frame(Replica = 1:replicas_p3, Viajes_Completados = total_viajes)
kable(tabla_p3, caption = "Viajes Completados en 10 Horas (600 min)")
| Replica | Viajes_Completados |
|---|---|
| 1 | 4 |
| 2 | 5 |
| 3 | 4 |
| 4 | 4 |
| 5 | 6 |
# b) Intervalo de Confianza
ic_95 <- t.test(total_viajes, conf.level = 0.95)
cat(paste("\nMedia de viajes (5 réplicas):", round(ic_95$estimate, 2), "\n"))
##
## Media de viajes (5 réplicas): 4.6
cat(paste("IC 95% para la media de viajes:",
"[", round(ic_95$conf.int[1], 3), ",", round(ic_95$conf.int[2], 3), "]\n"))
## IC 95% para la media de viajes: [ 3.489 , 5.711 ]
Diagnóstico (Análisis de Cuello de Botella): La meta son 10 entregas. La simulación nos da una media de 4.6 viajes. Es imposible.
Vamos al análisis teórico del ciclo:
En una jornada de 600 minutos, el máximo teórico de viajes es \(600 / 130 \approx 4.6\) viajes. La simulación lo confirma.
Conclusión: El sistema está topado (capacity constrained) a 4-5 viajes por día.
Recomendaciones (Estrategias para duplicar capacidad):
Añadir Recursos (Comprar otro Camión): Esta es la solución obvia. 2 camiones harían 8-10 viajes.
Optimizar el Proceso Actual (Reducir Tiempos):
Recomendación Final: La única forma de llegar a 10 es con un segundo camión. Sin embargo, para que esa inversión funcione, se debe atacar también el tiempo de carga (Acción 2), de lo contrario, el segundo camión pasará mucho tiempo detenido esperando en la base.