Objetivos de la asignación

  1. Analizar y modelar sistemas complejos como colas e inventarios, explorando tanto las bases teóricas como su implementación práctica.

  2. Desarrollar simulaciones basadas en Montecarlo y en agentes, fortaleciendo sus habilidades de programación y análisis.

  3. Identicar cómo los cambios en las condiciones iniciales afectan los resultados y generar conclusiones para la toma de decisiones.

TEORÌA DE COLAS

1. Definición de conceptos y ejemplos

a) Modelo M/M/1

El modelo M/M/1 es un sistema de colas con un solo servidor, donde las llegadas siguen un proceso de Poisson (M) y los tiempos de servicio siguen una distribución exponencial (M). El “1” indica que hay un solo servidor.

Ejemplo: Una cafetería con un solo cajero donde los clientes llegan aleatoriamente y son atendidos uno a uno.

b) Modelo M/M/c

El modelo M/M/c es similar al M/M/1, pero con múltiples servidores (c servidores). Las llegadas siguen un proceso de Poisson y los tiempos de servicio son exponenciales.

Ejemplo: Un banco con varios cajeros atendiendo a los clientes que llegan aleatoriamente.

c) Factor de utilización (ρ)

El factor de utilización (ρ) es la proporción de tiempo que el servidor está ocupado. Se calcula como la relación entre la tasa de llegada (λ) y la tasa de servicio (µ) multiplicada por el número de servidores (c).

Ejemplo: Si λ = 6 clientes/hora y µ = 10 clientes/hora en un sistema M/M/1, entonces ρ = 6/10 = 0.6, lo que significa que el servidor está ocupado el 60% del tiempo.

d) Tiempo promedio en el sistema (W)

Es el tiempo promedio que un cliente pasa en el sistema, incluyendo el tiempo de espera en la cola y el tiempo de servicio.

Ejemplo: En un sistema M/M/1, si W = 0.25 horas, significa que en promedio un cliente pasa 15 minutos en el sistema.

e) Número promedio en la cola (Lq)

Es el número promedio de clientes que están esperando en la cola para ser atendidos.

Ejemplo: Si Lq = 1.5, significa que en promedio hay 1.5 clientes esperando en la cola.


2. Efecto del incremento de la tasa de llegada (λ) en un sistema M/M/1

En un sistema M/M/1, el tiempo de espera en la cola (Wq) y el tiempo promedio en el sistema (W) aumentan a medida que la tasa de llegada (λ) se acerca a la tasa de servicio (µ). Esto se debe a que el servidor se satura más rápidamente, lo que genera una cola más larga y tiempos de espera más prolongados.

Fórmula para W en un sistema M/M/1: \[ W = \frac{1}{\mu - \lambda} \]

Si λ aumenta, el denominador (µ - λ) disminuye, lo que aumenta W.


3. Simulación de un sistema M/M/1

Parámetros: - Tasa de llegada (λ): 6 clientes/hora - Tasa de servicio (µ): 10 clientes/hora

a) Probabilidad de que el sistema esté vacío (P0)

lambda <- 6  # Tasa de llegada (clientes/hora)
mu <- 10     # Tasa de servicio (clientes/hora)
rho <- lambda / mu  # Factor de utilización
P0 <- 1 - rho  # Probabilidad de que el sistema esté vacío
P0
## [1] 0.4

Resultado: La probabilidad de que el sistema esté vacío es del 0,4* 100%.

b) Tiempo promedio en el sistema (W)

W <- 1 / (mu - lambda)  # Tiempo promedio en el sistema (horas)
W
## [1] 0.25

Resultado: El tiempo promedio en el sistema es de 0.25 horas.

c) Número promedio de clientes en la cola (Lq)

Lq <- (lambda^2) / (mu * (mu - lambda))  # Número promedio en la cola
Lq
## [1] 0.9

Resultado: El número promedio de clientes en la cola es 0,9.

4. Análisis de un sistema M/M/2

Parámetros:

Tasa de llegada (λ): 6 clientes/hora

Tasa de servicio (µ): 10 clientes/hora

Número de servidores (c): 2

###a) Probabilidad de que el sistema esté vacío (P0)

c <- 2  # Número de servidores
rho_mmc <- lambda / (c * mu)  # Factor de utilización para M/M/c

# Cálculo de P0
sum_term <- 0
for (n in 0:(c-1)) {
  sum_term <- sum_term + (lambda / mu)^n / factorial(n)
}
P0_mmc <- 1 / (sum_term + ((lambda / mu)^c / (factorial(c) * (1 - rho_mmc))))
P0_mmc
## [1] 0.5384615

Resultado: La probabilidad de que el sistema esté vacío es del 0.5384615.

###b) Tiempo promedio en el sistema (W)

Lq_mmc <- ((lambda / mu)^c * rho_mmc) / (factorial(c) * (1 - rho_mmc)^2) * P0_mmc
Wq_mmc <- Lq_mmc / lambda  # Tiempo promedio en la cola
W_mmc <- Wq_mmc + (1 / mu)  # Tiempo promedio en el sistema
W_mmc
## [1] 0.1098901

Resultado: El tiempo promedio en el sistema es de 0.1098901 horas

###c) Número promedio de clientes en la cola (Lq)

Lq_mmc
## [1] 0.05934066

Resultado: El número promedio de clientes en la cola es 0.05934066

Conclusiones

Sistema M/M/1 vs M/M/2:

En el sistema M/M/1, el tiempo promedio en el sistema (W) y el número promedio de clientes en la cola (Lq) son mayores debido a la presencia de un solo servidor.

En el sistema M/M/2, al tener dos servidores, el tiempo de espera y la longitud de la cola se reducen significativamente, mejorando la eficiencia del sistema.

Factor de utilización (ρ):

En ambos sistemas, el factor de utilización (ρ) indica la carga del servidor. Un ρ cercano a 1 implica que el sistema está cerca de su capacidad máxima, lo que puede generar congestión.

Impacto de la tasa de llegada (λ):

A medida que λ se acerca a µ en un sistema M/M/1, el tiempo de espera y la longitud de la cola aumentan exponencialmente. Esto resalta la importancia de dimensionar adecuadamente la capacidad del sistema para evitar congestiones.

Simulación en R:

El uso de R para simular sistemas de colas permite analizar rápidamente diferentes escenarios y tomar decisiones basadas en datos para optimizar recursos.

TEORÌA DE INVENTARIOS

1. Diferencia entre modelos de inventarios de revisión continua y revisión periódica

Revisión Continua

En este modelo, el nivel de inventario se monitorea constantemente, y se realiza un pedido cuando el inventario alcanza un nivel específico llamado punto de reorden (R). Es útil para productos de alto valor o con demanda irregular.

Ejemplo: Un supermercado que monitorea constantemente el inventario de productos perecederos y realiza pedidos cuando el stock baja a un nivel crítico.

Revisión Periódica

En este modelo, el inventario se revisa en intervalos de tiempo fijos (por ejemplo, semanal o mensual), y se realiza un pedido para llevar el inventario a un nivel máximo predeterminado. Es útil para productos con demanda estable.

Ejemplo: Una tienda de ropa que revisa su inventario cada dos semanas y realiza pedidos para reponer las prendas vendidas.

2. Definición de conceptos y ejemplos

a) Punto de reorden (R)

Es el nivel de inventario en el cual se debe realizar un nuevo pedido para evitar el desabasto. Se calcula considerando la demanda durante el tiempo de entrega y un stock de seguridad.

Ejemplo: Si la demanda diaria es de 20 unidades y el tiempo de entrega es de 3 días, el punto de reorden sería \(R = 20 \times 3 = 60\) unidades.

b) Nivel de servicio

Es la probabilidad de no quedarse sin stock durante el tiempo de entrega. Un nivel de servicio del 95% significa que hay un 5% de probabilidad de desabasto.

Ejemplo: Un nivel de servicio del 90% en un hospital implica que hay un 10% de riesgo de quedarse sin medicamentos críticos.

c) Costo total de inventario

Es la suma de los costos de mantener inventario, los costos de ordenar y los costos de desabasto. El objetivo es minimizar este costo.

Ejemplo: Si el costo de mantener inventario es $100, el costo de ordenar es $50 y no hay desabasto, el costo total sería $150.

3. Modelo de inventario de revisión continua

Datos: - Demanda promedio diaria (\(D\)): 50 unidades - Desviación estándar de la demanda diaria (\(\sigma_D\)): 10 unidades - Tiempo de entrega (\(L\)): 5 días - Costo de mantener inventario (\(H\)): $2 por unidad por día - Costo de ordenar (\(S\)): $50 por pedido

a) Punto de reorden (R)

El punto de reorden se calcula como: \[ R = D \times L + Z \times \sigma_D \times \sqrt{L} \] Donde \(Z\) es el valor de la distribución normal para un nivel de servicio dado. Supongamos un nivel de servicio del 95% (\(Z = 1.645\)).

D <- 50  # Demanda promedio diaria
sigma_D <- 10  # Desviación estándar de la demanda diaria
L <- 5  # Tiempo de entrega en días
Z <- 1.645  # Valor Z para un nivel de servicio del 95%

R <- D * L + Z * sigma_D * sqrt(L)
R
## [1] 286.7833

Resultado: El punto de reorden es286.7833 unidades

###b) Tamaño del lote óptimo (Q) usando el modelo EOQ

El modelo EOQ (Economic Order Quantity) calcula el tamaño óptimo del pedido para minimizar los costos totales:

S <- 50  # Costo de ordenar por pedido
H <- 2   # Costo de mantener inventario por unidad por día

Q <- sqrt((2 * D * S) / H)
Q
## [1] 50

Resultado: El tamaño del lote óptimo es 50 unidades

4. Simulación del comportamiento del inventario durante 30 días Simularemos el nivel de inventario diario considerando la demanda aleatoria y el punto de reorden.

set.seed(123)  # Fijar semilla para reproducibilidad
dias <- 30  # Número de días a simular
inventario_inicial <- Q  # Inventario inicial igual al lote óptimo
inventario <- numeric(dias)
inventario[1] <- inventario_inicial

# Simulación de la demanda diaria
demanda <- rnorm(dias, mean = D, sd = sigma_D)
demanda <- pmax(demanda, 0)  # Asegurar que la demanda no sea negativa

# Simulación del inventario
for (i in 2:dias) {
  inventario[i] <- inventario[i-1] - demanda[i-1]
  if (inventario[i] < R) {
    inventario[i] <- inventario[i] + Q  # Realizar un pedido
  }
}

# Gráfico del nivel de inventario diario
plot(1:dias, inventario, type = "o", col = "blue", xlab = "Día", ylab = "Nivel de Inventario",
     main = "Simulación de Nivel de Inventario (30 días)")
abline(h = R, col = "red", lty = 2)
legend("topright", legend = c("Inventario", "Punto de Reorden (R)"), col = c("blue", "red"), lty = 1:2)

Conclusiones

Revisión Continua vs Revisión Periódica:

La revisión continua es más adecuada para productos de alto valor o demanda irregular, ya que permite reaccionar rápidamente a cambios en la demanda.

La revisión periódica es más simple y adecuada para productos con demanda estable, pero puede resultar en mayores niveles de inventario.

Punto de Reorden (R):

El punto de reorden asegura que se realicen pedidos a tiempo para evitar desabastos. En este caso, se calculó en r R unidades.

Tamaño del Lote Óptimo (Q):

El modelo EOQ ayuda a minimizar los costos totales de inventario. En este caso, el tamaño óptimo del pedido es r Q unidades.

Simulación de Inventario:

La simulación muestra cómo el nivel de inventario fluctúa diariamente y cómo se realizan pedidos cuando se alcanza el punto de reorden. Esto permite planificar mejor las compras y evitar desabastos.

Importancia del Nivel de Servicio:

Un nivel de servicio alto (95% en este caso) reduce el riesgo de desabasto, pero puede aumentar los costos de mantener inventario. Es crucial encontrar un equilibrio entre costos y nivel de servicio.

TIPOS DE DEMANDAS

1. Principales tipos de demanda

a) Demanda determinista

La demanda determinista es aquella que se conoce con certeza y no varía con el tiempo. Es predecible y no tiene incertidumbre asociada.

Ejemplo: Una empresa que produce 100 unidades de un producto cada mes para cumplir con un contrato fijo.

b) Demanda probabilística

La demanda probabilística es aquella que tiene un componente aleatorio y no se puede predecir con certeza. Se modela utilizando distribuciones de probabilidad.

Ejemplo: La demanda diaria de un producto en una tienda, que puede variar debido a factores como el clima, promociones, etc.


2. Impacto del tipo de demanda en la planificación de inventarios y simulaciones

  • Demanda determinista: Facilita la planificación, ya que no hay incertidumbre. Los modelos de inventario pueden ser más simples, como el modelo EOQ (Economic Order Quantity).
  • Demanda probabilística: Requiere modelos más complejos, como el modelo de revisión continua con punto de reorden (R, Q) o revisión periódica. Además, es necesario considerar un stock de seguridad para manejar la variabilidad de la demanda.

En simulaciones, la demanda probabilística permite evaluar escenarios más realistas, considerando la variabilidad y el riesgo de desabasto.


3. Generación de series de tiempo con demanda probabilística

Distribución normal (µ = 100, σ = 15)

Generamos una serie de tiempo con demanda que sigue una distribución normal con media \(\mu = 100\) y desviación estándar \(\sigma = 15\).

set.seed(123)  # Fijar semilla para reproducibilidad
n <- 100  # Número de periodos
demanda_normal <- rnorm(n, mean = 100, sd = 15)
demanda_normal <- pmax(demanda_normal, 0)  # Asegurar que la demanda no sea negativa

Distribución de Poisson (λ = 80) Generamos una serie de tiempo con demanda que sigue una distribución de Poisson con parámetro λ=80

demanda_poisson <- rpois(n, lambda = 80)

Gráficos comparativos

# Gráfico de la demanda normal
plot(1:n, demanda_normal, type = "o", col = "blue", xlab = "Periodo", ylab = "Demanda",
     main = "Demanda Probabilística - Distribución Normal (µ = 100, σ = 15)")
abline(h = 100, col = "red", lty = 2)
legend("topright", legend = c("Demanda", "Media (µ = 100)"), col = c("blue", "red"), lty = 1:2)

# Gráfico de la demanda de Poisson
plot(1:n, demanda_poisson, type = "o", col = "green", xlab = "Periodo", ylab = "Demanda",
     main = "Demanda Probabilística - Distribución de Poisson (λ = 80)")
abline(h = 80, col = "red", lty = 2)
legend("topright", legend = c("Demanda", "Media (λ = 80)"), col = c("green", "red"), lty = 1:2)

##Conclusiones

Tipos de demanda:

La demanda determinista es predecible y facilita la planificación, mientras que la demanda probabilística introduce incertidumbre y requiere modelos más complejos.

Impacto en la planificación:

En sistemas de inventarios, la demanda probabilística obliga a considerar un stock de seguridad para evitar desabastos, lo que aumenta los costos de inventario.

En simulaciones, la demanda probabilística permite evaluar escenarios más realistas y tomar decisiones basadas en el riesgo.

Simulación de demandas:

La distribución normal es útil para modelar demandas con variabilidad simétrica alrededor de una media.

La distribución de Poisson es adecuada para modelar demandas discretas y eventos raros.

Gráficos comparativos:

Los gráficos muestran cómo la demanda varía en el tiempo para ambas distribuciones. La distribución normal tiene una variabilidad continua, mientras que la distribución de Poisson tiene valores discretos.

#SIMULACIÓN DE MONTECARLO

1. Proceso de Simulación de Montecarlo

La simulación de Montecarlo es un método estadístico que utiliza la aleatoriedad para resolver problemas que pueden ser deterministas en principio. Este proceso implica generar muchas simulaciones (o muestras aleatorias) de diferentes variables de entrada y luego analizar los resultados para obtener una estimación del comportamiento del sistema.

La técnica se usa ampliamente en una variedad de campos, desde la gestión de riesgos financieros hasta la ingeniería y la gestión de inventarios.

Ejemplo en la Gestión de Inventarios

En la gestión de inventarios, la simulación de Montecarlo se puede usar para estimar el costo total de mantener inventarios en función de la demanda aleatoria, el tiempo de entrega y los costos asociados.

Por ejemplo, podemos simular el proceso de abastecimiento de un producto con demanda diaria variable y costos asociados al mantenimiento del inventario, el costo de cada unidad y la penalización por falta de inventario.

2. Ventajas y Limitaciones de la Simulación de Montecarlo

Ventajas:

  1. Flexibilidad: Puede aplicarse a una amplia variedad de problemas y sistemas complejos, incluso aquellos que no tienen soluciones analíticas simples.
  2. Estimación de Riesgos: Permite la evaluación de diferentes escenarios bajo incertidumbre, lo que ayuda en la toma de decisiones bajo condiciones de riesgo.

Limitaciones:

  1. Dependencia de Datos de Entrada: La precisión de los resultados depende de la calidad y exactitud de las distribuciones y parámetros de entrada utilizados en la simulación.
  2. Requiere Cálculos Intensivos: Si bien es útil para sistemas complejos, las simulaciones pueden ser computacionalmente costosas, especialmente con un gran número de muestras.

3. Simulación de Montecarlo para Estimar el Costo Total de Inventario

A continuación, simulamos el costo total de inventario para un producto con los siguientes datos:

  • Demanda diaria: Distribución normal con \(\mu = 50\) y \(\sigma = 10\).
  • Tiempo de entrega: 3 días.
  • Costo por unidad: $5.
  • Costo de mantener inventario: $0.50 por unidad por día.
  • Penalización por falta de inventario: $10 por unidad faltante.

Simulamos 1000 días y calculamos el costo promedio total de inventario.

Código de Simulación

set.seed(123)  # Fijar semilla para reproducibilidad

# Parámetros
demanda_media <- 50
demanda_sd <- 10
tiempo_entrega <- 3
costo_unitario <- 5
costo_almacenamiento <- 0.50
penalizacion_falta <- 10
dias_simulacion <- 1000

# Variables para almacenar resultados
costo_total <- numeric(dias_simulacion)

# Simulaciones
for (i in 1:dias_simulacion) {
  # Demanda diaria para los 3 días
  demanda <- rnorm(tiempo_entrega, mean = demanda_media, sd = demanda_sd)
  demanda_total <- sum(demanda)  # Demanda total para el periodo
  
  # Inventario y costos
  inventario_inicial <- max(0, demanda_total)  # Inventario inicial no negativo
  costo_mantenimiento <- inventario_inicial * costo_almacenamiento * tiempo_entrega
  costo_penalizacion <- ifelse(inventario_inicial < demanda_total, (demanda_total - inventario_inicial) * penalizacion_falta, 0)
  costo_simulacion <- costo_mantenimiento + costo_penalizacion + (demanda_total * costo_unitario)
  
  # Almacenar el costo total
  costo_total[i] <- costo_simulacion
}

# Costo promedio total
costo_promedio <- mean(costo_total)
costo_promedio
## [1] 977.5012

El resultado 977.5012 es el costo promedio total de inventario para los 1000 días simulados

##4. Análisis de Sensibilidad σ a 5, 10 y 15, para ver cómo afectan los resultados.

# Sensibilidad a diferentes desviaciones estándar
resultados_sensibilidad <- data.frame()

for (sd in c(5, 10, 15)) {
  # Simulación para cada valor de desviación estándar
  costo_total <- numeric(dias_simulacion)
  
  for (i in 1:dias_simulacion) {
    # Demanda diaria para los 3 días con nueva desviación estándar
    demanda <- rnorm(tiempo_entrega, mean = demanda_media, sd = sd)
    demanda_total <- sum(demanda)
    
    # Inventario y costos
    inventario_inicial <- max(0, demanda_total)
    costo_mantenimiento <- inventario_inicial * costo_almacenamiento * tiempo_entrega
    costo_penalizacion <- ifelse(inventario_inicial < demanda_total, (demanda_total - inventario_inicial) * penalizacion_falta, 0)
    costo_simulacion <- costo_mantenimiento + costo_penalizacion + (demanda_total * costo_unitario)
    
    # Almacenar el costo total
    costo_total[i] <- costo_simulacion
  }
  
  # Almacenar el costo promedio para cada desviación estándar
  resultados_sensibilidad <- rbind(resultados_sensibilidad, data.frame(Desviacion_Estandar = sd, Costo_Promedio = mean(costo_total)))
}

resultados_sensibilidad

##Conclusiones

Desviación estándar baja σ=5): Cuando la demanda diaria es más predecible (menor desviación estándar), los costos son más bajos debido a menos incertidumbre en el inventario.

Desviación estándar alta (σ=15): Con mayor variabilidad en la demanda, los costos de mantenimiento y penalización por falta de inventario aumentan debido a la incertidumbre en las predicciones de demanda.

#SIMULACIÓN BÁSADA EN AGENTES

1. Simulación Basada en Agentes (ABM)

La simulación basada en agentes (ABM, por sus siglas en inglés) es una metodología computacional para modelar sistemas complejos en los que los componentes (agentes) interactúan entre sí y con su entorno. Cada agente tiene sus propios comportamientos y toma decisiones en función de las reglas que definen su interacción. Los agentes pueden ser individuos, grupos, o entidades, y sus interacciones pueden dar lugar a dinámicas emergentes a nivel de sistema.

Diferencias con otros métodos de simulación:

  • Modelos de simulación continua: Los modelos tradicionales (como la simulación de Montecarlo o los sistemas de ecuaciones diferenciales) suelen modelar el comportamiento de un sistema de manera continua o estocástica sin representar explícitamente a los individuos.
  • ABM: En contraste, los modelos basados en agentes simulan de manera explícita a los agentes individuales y sus decisiones, lo que permite observar comportamientos emergentes y dinámicas a nivel de grupo.

2. Áreas de Aplicación de ABM

1. Economía y Mercados

  • Caso práctico: Simulación de un mercado competitivo donde los compradores y vendedores ajustan precios y decisiones de compra/venta. ABM permite modelar las dinámicas de oferta y demanda y observar cómo cambian los precios y las decisiones de consumo a lo largo del tiempo.

2. Ecología

  • Caso práctico: Modelar interacciones entre especies dentro de un ecosistema. Los agentes pueden ser animales, plantas o recursos, y la simulación puede mostrar cómo las especies afectan a otras y cómo cambian las poblaciones con el tiempo.

3. Sistemas Sociales y Urbanos

  • Caso práctico: Modelar el comportamiento de personas en una ciudad, como la movilidad urbana, la propagación de enfermedades o las decisiones de consumo. ABM permite simular cómo las decisiones individuales afectan al sistema social en su conjunto.

3. Diseño de un Modelo Sencillo de Simulación Basada en Agentes

Vamos a crear un modelo sencillo para simular un mercado con los siguientes agentes:

  • Compradores: Buscan maximizar su utilidad en función del precio y la calidad.
  • Vendedores: Ajustan precios según la demanda.

Reglas de Interacción:

  1. Compradores: Eligen al vendedor con el precio más bajo si está dentro de su presupuesto. Si varios vendedores tienen el mismo precio, elegirán el que ofrezca mejor calidad.
  2. Vendedores: Ajustan los precios en función de la demanda. Si hay mucha demanda, suben el precio; si la demanda es baja, bajan el precio.

4. Implementación de la Simulación

Simularemos el mercado con 100 compradores y 10 vendedores durante 50 períodos.

Parámetros del Modelo:

  • Compradores: Cada uno tiene un presupuesto y una preferencia por calidad.
  • Vendedores: Establecen precios de acuerdo con la demanda observada.

Código de la Simulación

set.seed(123)  # Para reproducibilidad

# Número de agentes
num_compradores <- 100
num_vendedores <- 10
periodos <- 50

# Inicialización de agentes
compradores <- data.frame(id = 1:num_compradores,
                          presupuesto = runif(num_compradores, 20, 100),  # Presupuesto entre 20 y 100
                          preferencia_calidad = runif(num_compradores, 0, 1))  # Preferencia por calidad entre 0 y 1

vendedores <- data.frame(id = 1:num_vendedores,
                         precio = runif(num_vendedores, 5, 30),  # Precios entre 5 y 30
                         calidad = runif(num_vendedores, 0, 1),  # Calidad entre 0 y 1
                         demanda = rep(0, num_vendedores))  # Demanda inicial 0

# Almacenar la evolución de los precios y la distribución de compradores
evolucion_precios <- matrix(NA, nrow = periodos, ncol = num_vendedores)
distribucion_compradores <- matrix(NA, nrow = periodos, ncol = num_vendedores)

# Simulación por períodos
for (t in 1:periodos) {
  # Resetear demanda de vendedores
  vendedores$demanda <- rep(0, num_vendedores)
  
  # Cada comprador toma una decisión
  for (i in 1:num_compradores) {
    presupuesto <- compradores$presupuesto[i]
    preferencia_calidad <- compradores$preferencia_calidad[i]
    
    # Evaluar vendedores dentro del presupuesto
    vendedores_asequibles <- vendedores[vendedores$precio <= presupuesto, ]
    
    # Elegir el vendedor con el precio más bajo, con preferencia por calidad
    if (nrow(vendedores_asequibles) > 0) {
      vendedor_seleccionado <- vendedores_asequibles[which.min(vendedores_asequibles$precio), ]
      if (sum(vendedores_asequibles$precio == vendedor_seleccionado$precio) > 1) {
        vendedor_seleccionado <- vendedores_asequibles[which.max(vendedores_asequibles$calidad), ]
      }
      
      # Aumentar la demanda del vendedor seleccionado
      vendedores$demanda[vendedores$id == vendedor_seleccionado$id] <- vendedores$demanda[vendedores$id == vendedor_seleccionado$id] + 1
    }
  }
  
  # Los vendedores ajustan precios según la demanda
  for (j in 1:num_vendedores) {
    if (vendedores$demanda[j] > 10) {
      vendedores$precio[j] <- vendedores$precio[j] * 1.05  # Aumentar precio si hay mucha demanda
    } else {
      vendedores$precio[j] <- vendedores$precio[j] * 0.95  # Disminuir precio si hay poca demanda
    }
  }
  
  # Almacenar resultados
  evolucion_precios[t, ] <- vendedores$precio
  distribucion_compradores[t, ] <- vendedores$demanda
}

# Visualización de la evolución de precios
library(ggplot2)

# Evolución de precios
evolucion_df <- data.frame(Periodo = rep(1:periodos, num_vendedores),
                           Precio = as.vector(evolucion_precios),
                           Vendedor = rep(1:num_vendedores, each = periodos))

ggplot(evolucion_df, aes(x = Periodo, y = Precio, color = factor(Vendedor))) +
  geom_line() +
  labs(title = "Evolución de Precios en el Mercado",
       x = "Período", y = "Precio") +
  theme_minimal()

# Distribución de compradores entre vendedores
distribucion_df <- data.frame(Periodo = rep(1:periodos, num_vendedores),
                               Compradores = as.vector(distribucion_compradores),
                               Vendedor = rep(1:num_vendedores, each = periodos))

ggplot(distribucion_df, aes(x = Periodo, y = Compradores, color = factor(Vendedor))) +
  geom_line() +
  labs(title = "Distribución de Compradores entre Vendedores",
       x = "Período", y = "Número de Compradores") +
  theme_minimal()

5. Análisis del Impacto de un Cambio en el Comportamiento de los Compradores

Imaginemos que los compradores empiezan a darle más importancia a la calidad en lugar de al precio. Esto se puede simular modificando la preferencia de calidad de los compradores, aumentando su enfoque en la calidad sobre el precio.

Código para Simular el Cambio en el Comportamiento de los Compradores

# Aumentar la preferencia por calidad en los compradores
compradores$preferencia_calidad <- runif(num_compradores, 0.5, 1)  # Más enfoque en calidad

# Rehacer la simulación con este nuevo comportamiento
evolucion_precios_calidad <- matrix(NA, nrow = periodos, ncol = num_vendedores)
distribucion_compradores_calidad <- matrix(NA, nrow = periodos, ncol = num_vendedores)

for (t in 1:periodos) {
  # Resetear demanda de vendedores
  vendedores$demanda <- rep(0, num_vendedores)
  
  for (i in 1:num_compradores) {
    presupuesto <- compradores$presupuesto[i]
    preferencia_calidad <- compradores$preferencia_calidad[i]
    
    vendedores_asequibles <- vendedores[vendedores$precio <= presupuesto, ]
    
    if (nrow(vendedores_asequibles) > 0) {
      vendedor_seleccionado <- vendedores_asequibles[which.max(vendedores_asequibles$calidad), ]
      
      # Aumentar la demanda del vendedor seleccionado
      vendedores$demanda[vendedores$id == vendedor_seleccionado$id] <- vendedores$demanda[vendedores$id == vendedor_seleccionado$id] + 1
    }
  }
  
  # Ajuste de precios
  for (j in 1:num_vendedores) {
    if (vendedores$demanda[j] > 10) {
      vendedores$precio[j] <- vendedores$precio[j] * 1.05
    } else {
      vendedores$precio[j] <- vendedores$precio[j] * 0.95
    }
  }
  
  # Almacenar resultados
  evolucion_precios_calidad[t, ] <- vendedores$precio
  distribucion_compradores_calidad[t, ] <- vendedores$demanda
}

# Visualización del impacto en la evolución de precios y compradores
evolucion_df_calidad <- data.frame(Periodo = rep(1:periodos, num_vendedores),
                                   Precio = as.vector(evolucion_precios_calidad),
                                   Vendedor = rep(1:num_vendedores, each = periodos))

ggplot(evolucion_df_calidad, aes(x = Periodo, y = Precio, color = factor(Vendedor))) +
  geom_line() +
  labs(title = "Evolución de Precios con Preferencia por Calidad",
       x = "Período", y = "Precio") +
  theme_minimal()

# Distribución de compradores
distribucion_df_calidad <- data.frame(Periodo = rep(1:periodos, num_vendedores),
                                       Compradores = as.vector(distribucion_compradores_calidad),
                                       Vendedor = rep(1:num_vendedores, each = periodos))

ggplot(distribucion_df_calidad, aes(x = Periodo, y = Compradores, color = factor(Vendedor))) +
  geom_line() +
  labs(title = "Distribución de Compradores con Preferencia por Calidad",
       x = "Período", y = "Número de Compradores") +
  theme_minimal()

##Conclusiones

Cambio en el comportamiento: Al aumentar la preferencia por calidad, los compradores tienden a elegir vendedores con mejor calidad, lo que puede llevar a una estabilización de los precios y a una distribución más equitativa de los compradores entre los vendedores con mayor calidad.

Evolución de precios: Los precios de los vendedores más enfocados en calidad pueden no variar tanto debido a la estabilidad en la demanda, mientras que los vendedores con menor calidad pueden bajar sus precios para atraer a más compradores.