Se modelará un proceso de soldadura donde la longitud final (\(L\)) es la suma de dos componentes (\(x_1\) y \(x_2\)). Se busca evaluar la capacidad de este proceso para cumplir con las especificaciones de diseño.
Se generan 500 muestras aleatorias para \(x_1\) y \(x_2\) y se suman para obtener 500 valores de \(L\).
# Semilla
set.seed(999)
N_sim <- 500 # Número de ensamblajes
# Parámetros de las distribuciones
media_x1 <- 30
sd_x1 <- sqrt(0.81) # Varianza 0.81 -> SD 0.9
media_x2 <- 18
sd_x2 <- 0.3
# Límites de especificación
LSL <- 45
USL <- 55
# 1. Generación de las muestras aleatorias
x1_sim <- rnorm(N_sim, mean = media_x1, sd = sd_x1)
x2_sim <- rnorm(N_sim, mean = media_x2, sd = sd_x2)
L_sim <- x1_sim + x2_sim # Longitud total
# 2. Almacenamiento en un data.frame
df_barras <- data.frame(
X1 = x1_sim,
X2 = x2_sim,
L_Total = L_sim
)
# 3. Visualización de los primeros resultados
cat("Primeras 6 simulaciones de ensamblaje:\n")
## Primeras 6 simulaciones de ensamblaje:
kable(head(df_barras), caption = "Muestra de los primeros 6 ensamblajes")
| X1 | X2 | L_Total |
|---|---|---|
| 29.74643 | 17.89849 | 47.64492 |
| 28.81870 | 18.06039 | 46.87908 |
| 30.71567 | 18.18081 | 48.89648 |
| 30.24306 | 17.93249 | 48.17556 |
| 29.75042 | 17.99697 | 47.74739 |
| 29.49058 | 17.94192 | 47.43250 |
Con los 500 resultados de L_Total, calculamos las
métricas solicitadas.
# 1. Estimación de Probabilidad de Falla
# Contamos cuántas barras están OOS (Fuera de Especificación)
fallas <- sum(L_sim < LSL | L_sim > USL)
prob_falla <- fallas / N_sim
cat(paste("Total de simulaciones:", N_sim, "\n"))
## Total de simulaciones: 500
cat(paste("Barras fuera de especificación:", fallas, "\n"))
## Barras fuera de especificación: 0
cat(paste("Estimador de Probabilidad de Falla:", round(prob_falla * 100, 2), "%\n\n"))
## Estimador de Probabilidad de Falla: 0 %
# 2. Cálculo de Índices de Capacidad
# Necesitamos la media y sd de NUESTRO PROCESO simulado
media_proceso <- mean(L_sim)
sd_proceso <- sd(L_sim)
# Cp (Capacidad Potencial): Compara la variabilidad permitida vs la real
Cp <- (USL - LSL) / (6 * sd_proceso)
# Cpk (Capacidad Real): Ajusta el Cp por el centrado del proceso
Cpu <- (USL - media_proceso) / (3 * sd_proceso) # Capacidad vs Límite Superior
Cpl <- (media_proceso - LSL) / (3 * sd_proceso) # Capacidad vs Límite Inferior
Cpk <- min(Cpu, Cpl) # El Cpk siempre es el "peor lado"
# Imprimimos resultados
cat(paste("Media del Proceso (L_Total):", round(media_proceso, 4), "\n"))
## Media del Proceso (L_Total): 47.9446
cat(paste("Desv. Estándar del Proceso (L_Total):", round(sd_proceso, 4), "\n\n"))
## Desv. Estándar del Proceso (L_Total): 0.9216
cat(paste("Índice Cp (Potencial):", round(Cp, 4), "\n"))
## Índice Cp (Potencial): 1.8084
cat(paste("Índice Cpk (Real):", round(Cpk, 4), "\n"))
## Índice Cpk (Real): 1.065
Un histograma nos permite ver la distribución de nuestros 500 resultados contra los límites de diseño (LSL y USL).
# Media teórica (Target)
media_teorica_proceso <- media_x1 + media_x2
# Centro de las especificaciones (Target del Diseño)
target_diseno <- (LSL + USL) / 2
ggplot(df_barras, aes(x = L_Total)) +
geom_histogram(aes(y = ..density..), binwidth = 0.2, fill = "lightblue", color = "black") +
# Curva de densidad de los datos
geom_density(color = "blue", size = 1) +
# Límites de especificación (Rojos)
geom_vline(xintercept = c(LSL, USL), color = "red", linetype = "dashed", size = 1.2) +
# Media de nuestro proceso (Azul)
geom_vline(xintercept = media_proceso, color = "blue", linetype = "dotted", size = 1) +
# Target de diseño (Verde)
geom_vline(xintercept = target_diseno, color = "darkgreen", linetype = "solid", size = 1) +
labs(title = "Distribución del Proceso vs Especificaciones",
x = "Longitud Total (cm)",
y = "Densidad",
caption = "Rojo = Límites (45-55) | Verde = Target (50) | Azul = Media Proceso (48)") +
theme_bw()
El problema pregunta si el proceso “está bajo control”. Esta pregunta puede confundir dos conceptos: “control estadístico” (predecible en el tiempo, sin causas especiales de variación) y “capacidad” (cumplir especificaciones). Asumiremos que se refiere a Capacidad.
Conclusión: El proceso NO es capaz.
Justificación: El problema no es la variabilidad (el \(C_p\) es bueno), sino el centrado.
La gráfica es clara: tenemos una campana muy fina (buena variabilidad), pero está peligrosamente cerca del límite inferior (LSL).
Recomendación: Este es un problema de diseño, no de operación. Se debe ajustar la media de \(x_1\) o \(x_2\) (ej. \(x_1\) de 30 a 32) para recentrar el proceso en 50 cm. Si se hiciera eso, el \(C_{pk}\) se dispararía y la tasa de fallos sería cero.
Este es un modelo de colas de un solo servidor (G/G/1), aunque las llegadas son determinísticas (D/G/1).
Se simula la lógica de colas: una pieza no puede ser atendida hasta que haya llegado Y el servidor esté libre.
set.seed(101)
N_REPLICAS <- 10
N_PIEZAS <- 200
T_ENTRE_LLEGADAS <- 20 # min
MEDIA_T_DEFECTO <- 1 / 0.2 # 5 min
N_MAX_DEFECTOS <- 3
PROB_DEFECTO <- 2.4 / N_MAX_DEFECTOS # p = 0.8
# Vector para guardar el resultado (Makespan) de cada réplica
v_makespan <- numeric(N_REPLICAS)
# Bucle de Réplicas (i)
for (i in 1:N_REPLICAS) {
# Relojes: 'reloj_salida_servidor' es la variable clave.
# Indica cuándo el servidor estará disponible para la *siguiente* pieza.
reloj_salida_servidor <- 0
# Bucle de Piezas (j)
for (j in 1:N_PIEZAS) {
# 1. ¿Cuándo llega esta pieza?
t_llegada_pieza_j <- j * T_ENTRE_LLEGADAS
# 2. ¿Cuántos defectos trae?
n_defectos <- rbinom(1, size = N_MAX_DEFECTOS, prob = PROB_DEFECTO)
# 3. ¿Cuánto tiempo de servicio necesita?
t_servicio_pieza_j <- 0 # Si n_defectos = 0, tarda 0
if (n_defectos > 0) {
media_total_reparacion <- n_defectos * MEDIA_T_DEFECTO
tasa_total_reparacion <- 1 / media_total_reparacion
t_servicio_pieza_j <- rexp(1, rate = tasa_total_reparacion)
}
# 4. Lógica de Cola: ¿Cuándo EMPIEZA el servicio?
# No puede empezar antes de que LLEGUE y antes de que el SERVIDOR ESTÉ LIBRE.
t_inicio_servicio_j <- max(t_llegada_pieza_j, reloj_salida_servidor)
# 5. ¿Cuándo TERMINA el servicio?
t_fin_servicio_j <- t_inicio_servicio_j + t_servicio_pieza_j
# 6. Actualizamos el reloj del servidor para la pieza (j+1)
reloj_salida_servidor <- t_fin_servicio_j
}
# Guardamos el tiempo final de la última pieza (el Makespan)
v_makespan[i] <- reloj_salida_servidor
}
Se analizan los 10 resultados del tiempo total.
# Creamos una tabla de resultados
df_resultados_p2 <- data.frame(
Replica = 1:N_REPLICAS,
Tiempo_Total_Min = v_makespan,
Tiempo_Total_Horas = v_makespan / 60
)
kable(df_resultados_p2,
caption = "Tiempo Total (Makespan) para procesar 200 piezas",
digits = 2)
| Replica | Tiempo_Total_Min | Tiempo_Total_Horas |
|---|---|---|
| 1 | 4036.54 | 67.28 |
| 2 | 4005.62 | 66.76 |
| 3 | 4055.86 | 67.60 |
| 4 | 4005.84 | 66.76 |
| 5 | 4011.86 | 66.86 |
| 6 | 4004.18 | 66.74 |
| 7 | 4033.57 | 67.23 |
| 8 | 4075.40 | 67.92 |
| 9 | 4019.65 | 66.99 |
| 10 | 4081.92 | 68.03 |
# Calculamos el promedio
media_p2 <- mean(v_makespan)
cat(paste("\n\nRespuesta:",
"El tiempo promedio (basado en 10 réplicas) para procesar 200 piezas es de",
round(media_p2, 2), "minutos."))
##
##
## Respuesta: El tiempo promedio (basado en 10 réplicas) para procesar 200 piezas es de 4033.04 minutos.
Se simula un solo camión en un ciclo de 4 etapas.
Supuestos y Restricciones:
Simulamos 5 jornadas de 600 minutos. Un “viaje” se cuenta cuando el camión termina la descarga.
set.seed(404)
N_REPLICAS_P3 <- 5
T_JORNADA <- 600 # 10 horas
# Vector para guardar el # de viajes (entregas) completados
v_viajes_completos <- numeric(N_REPLICAS_P3)
# Data.frame para guardar el log de absolutamente todo (trazabilidad)
df_log_viajes <- data.frame()
# Bucle de Días (Réplicas)
for (i in 1:N_REPLICAS_P3) {
reloj_dia <- 0
contador_viajes <- 0
# Bucle de Ciclos (mientras haya tiempo en la jornada)
while (TRUE) {
# 1. 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)
# 2. ¿Alcanza a cargar e ir a descargar?
t_hasta_descarga <- t_carga + t_ida + t_descarga
if (reloj_dia + t_hasta_descarga > T_JORNADA) {
# No alcanza a completar la entrega. Se acaba el día.
break
}
# 3. Si alcanzó, se actualiza el reloj y se cuenta la entrega
reloj_dia <- reloj_dia + t_hasta_descarga
contador_viajes <- contador_viajes + 1
# 4. Simular la vuelta
t_vuelta <- rexp(1, rate = 1/40)
# 5. ¿Alcanza a volver a la base?
if (reloj_dia + t_vuelta > T_JORNADA) {
# Quedó en la calle, no puede iniciar otro ciclo.
break
}
# 6. Si alcanzó a volver, actualiza el reloj y el ciclo 'while' reinicia
reloj_dia <- reloj_dia + t_vuelta
# (Opcional) Guardar log
df_log_viajes <- rbind(df_log_viajes, data.frame(
Replica = i,
Viaje = contador_viajes,
T_Carga = t_carga, T_Ida = t_ida, T_Descarga = t_descarga, T_Vuelta = t_vuelta,
T_Ciclo_Total = t_carga+t_ida+t_descarga+t_vuelta,
Reloj_Fin_Vuelta = reloj_dia
))
}
# Guardamos el total de viajes de este día
v_viajes_completos[i] <- contador_viajes
}
cat("--- Resultados (Preguntas A y B) ---\n\n")
## --- Resultados (Preguntas A y B) ---
# a) Tabla de viajes por réplica
tabla_p3 <- data.frame(Replica = 1:N_REPLICAS_P3, Viajes_Completados = v_viajes_completos)
kable(tabla_p3, caption = "Viajes Completados en 10 Horas (600 min)")
| Replica | Viajes_Completados |
|---|---|
| 1 | 4 |
| 2 | 5 |
| 3 | 4 |
| 4 | 4 |
| 5 | 4 |
# b) Intervalo de Confianza del 95%
# Usamos t.test() que nos da la media y el IC
ic_test <- t.test(v_viajes_completos, conf.level = 0.95)
media_viajes <- ic_test$estimate
ic_inf <- ic_test$conf.int[1]
ic_sup <- ic_test$conf.int[2]
cat(paste("\nMedia de viajes (de 5 réplicas):", round(media_viajes, 2), "\n"))
##
## Media de viajes (de 5 réplicas): 4.2
cat(paste("Intervalo de Confianza 95% para la media de viajes:",
"[", round(ic_inf, 3), ",", round(ic_sup, 3), "]\n"))
## Intervalo de Confianza 95% para la media de viajes: [ 3.645 , 4.755 ]
Diagnóstico (Análisis Teórico): El objetivo es 10 entregas, pero nuestro IC está cerca de 4. Estamos muy lejos. ¿Por qué? Calculemos el tiempo esperado (promedio) de un ciclo completo:
Tiempo Esperado por Ciclo = \(30 + 40 + 20 + 40 = 130\) minutos.
En una jornada de 600 minutos, el número teórico de viajes es: \(600 \text{ min} / 130 \text{ min/viaje} \approx 4.61\) viajes.
La simulación (media de 4.2) confirma perfectamente el cálculo teórico.
Conclusión: Con un solo camión y los tiempos actuales, es matemáticamente imposible alcanzar 10 entregas. El sistema actual está topado en 4-5 viajes.
Recomendaciones para lograr las 10 entregas:
Añadir un segundo camión: Esta es la solución más directa. Si 1 camión hace 4-5 viajes, 2 camiones harían 8-10.
Reducir Tiempos del Ciclo (Optimización):
Recomendación Final: La meta de 10 viajes solo se logrará comprando un segundo camión. Sin embargo, se advierte que esto moverá el cuello de botella a la bahía de carga. Se recomienda invertir también en mejorar la eficiencia de la carga (reducir los 30 min) para que la espera del segundo camión no sea tan larga.
# CSV de los datos del Problema 1 (los 500 ensamblajes)
write.csv(df_barras, "simulacion_del_problema1.csv", row.names = FALSE)
# CSV de viajes del Problema 3 (trazabilidad de todos los viajes)
write.csv(df_log_viajes, "simulacion_del_problema3.csv", row.names = FALSE)