Repositorio minimalista para generar perfiles de instancias del problema MS-CFLP-CI-SR: Multi-Source Capacitated Facility Location Problem with Customer Incompatibilities and Service Radius Constraints.
El objetivo es partir de instancias base en formato MiniZinc .dzn y construir,
para cada una, tres variantes con restricciones de radio de servicio:
low, medium y high. El archivo ms-cflp-ci-base-instances/toy.dzn
se incluye como ejemplo pequeño y legible para entender el flujo completo.
En MS-CFLP-CI-SR se conserva la estructura de una instancia MS-CFLP-CI: clientes, facilities, demandas, capacidades, costes de apertura, matriz de costes de transporte e incompatibilidades entre pares de clientes.
La extensión -SR añade un umbral global de servicio Cmax. Un cliente i
solo puede ser servido por una facility j si:
c_ij <= Cmax
Esto induce un grafo bipartito de asignaciones admisibles:
A = {(i, j) : c_ij <= Cmax}
La densidad del grafo se resume como:
rho = |A| / (num_customers * num_facilities)
Valores bajos de rho representan restricciones de radio más fuertes; valores
altos representan redes de servicio más flexibles.
Para evitar elegir radios absolutos que no sean comparables entre instancias, los perfiles se obtienen a partir de percentiles de la matriz de costes de transporte.
Para cada .dzn:
- Se lee la matriz de costes
c_ij. - Se calculan los percentiles empíricos
q25,q50yq75. - Se construyen tres perfiles:
low:Cmax = q25medium:Cmax = q50high:Cmax = q75
- Para cada perfil se construye
A = {(i, j) : c_ij <= Cmax}. - Si el perfil falla condiciones deterministas básicas de factibilidad, se
relaja
Cmaxal siguiente coste disponible y se recomputaA. - Se guarda un JSON
radius_profile.
La comprobación de factibilidad incluida es ligera: detecta clientes aislados, capacidad total insuficiente y clientes cuya demanda supera la capacidad alcanzable por sus facilities admisibles. La factibilidad exacta, incluyendo el efecto completo de las incompatibilidades, debe comprobarse con un solver.
toy.dzn contiene 4 warehouses, 10 stores, 3 pares de clientes incompatibles y
una matriz SupplyCost de tamaño 10 x 4. Por tanto, antes de aplicar el radio
de servicio hay:
num_customers * num_facilities = 10 * 4 = 40
posibles asignaciones cliente-facility.
Contenido de la instancia:
Warehouses = 4;
Stores = 10;
Capacity = [100, 40, 60, 60];
FixedCost = [860, 350, 440, 580];
Goods = [12, 17, 5, 13, 20, 20, 17, 19, 11, 20];
SupplyCost = [|27, 66, 44, 55
|53, 89, 68, 46
|17, 40, 18, 61
|20, 68, 44, 78
|42, 89, 65, 78
|57, 55, 49, 31
|89, 101, 90, 16
|37, 31, 23, 55
|76, 60, 63, 44
|82, 107, 91, 31|];
Incompatibilities = 3;
IncompatiblePairs = [| 1, 10 | 2, 7 | 8, 9 |];La matriz SupplyCost es la que determina los radios de servicio:
Al generar los perfiles, el script calcula percentiles sobre los 40 costes de
SupplyCost. En el perfil low, el percentil 25 produce:
cmax_original = 39.25
Ese umbral inicial es demasiado restrictivo para las condiciones básicas de
factibilidad. Con Cmax = 39.25, los stores 2, 5 y 9 quedan sin ninguna
facility admisible, porque todos sus costes superan el umbral:
store 2: [53, 89, 68, 46]
store 5: [42, 89, 65, 78]
store 9: [76, 60, 63, 44]
Como N(i) queda vacío para esos clientes, el perfil low teórico sería
inviable. El generador relaja Cmax al siguiente coste disponible hasta
obtener:
cmax_final = 46.0
num_feasible_arcs = 16
rho = 16 / 40 = 0.4
La densidad rho = 0.4 significa que sobreviven 16 de las 40 asignaciones
cliente-facility posibles. El perfil medium alcanza rho = 0.525 y el perfil
high alcanza rho = 0.75, por lo que sus grafos de asignación son
progresivamente menos restrictivos.
El perfil resultante queda guardado en:
ms-cflp-ci-sr-instances/toy/low.json
ms-cflp-ci-base-instances/: instancias base.dzn.ms-cflp-ci-sr-instances/: perfiles-SRgenerados como JSON.scripts/generate_radius_profiles.py: genera perfileslow,mediumyhighdesde los.dzn.examples/load_profile.py: ejemplo mínimo para cargar un perfil y resolver la ruta al.dzn.requirements.txt: dependencias del proyecto.
El proyecto usa solo la librería estándar de Python. Si se trabaja con entorno virtual:
source .venv/bin/activate
pip install -r requirements.txtColoca los .dzn base en:
ms-cflp-ci-base-instances/
Este repositorio incluye ms-cflp-ci-base-instances/toy.dzn como instancia
pequeña de ejemplo y ms-cflp-ci-base-instances/wlp01.dzn como instancia real
de prueba. Para generar los perfiles:
python scripts/generate_radius_profiles.pySalida esperada:
ms-cflp-ci-sr-instances/
toy/
low.json
medium.json
high.json
wlp01/
low.json
medium.json
high.json
También se pueden indicar carpetas explícitamente:
python scripts/generate_radius_profiles.py \
--base-dir ms-cflp-ci-base-instances \
--output-dir ms-cflp-ci-sr-instancesCada archivo JSON describe una variante -SR de una instancia base. Contiene:
profile_id: identificador del perfil, por ejemplowlp01_low.base_instance_id: instancia.dznde origen.profile_name:low,mediumohigh.source: ruta, checksum y dialecto del.dzn.generation_policy: percentil usado y modo de relajación.cmax_original: valor inicial obtenido por percentil.cmax_final: valor final tras posible relajación.density_ratio: valorrho.num_feasible_arcs: cardinalidad deA.feasibility_diagnostics: diagnóstico ligero de factibilidad.cost_distribution: resumen de la distribución de costes.variable_map: nombres de variables detectados en el.dzn.
Primero genera los perfiles:
python scripts/generate_radius_profiles.pyDespués ejecuta el ejemplo:
python examples/load_profile.pyO carga un perfil concreto, por ejemplo el perfil low de toy.dzn:
python examples/load_profile.py ms-cflp-ci-sr-instances/toy/low.jsonEl ejemplo lee el JSON, resuelve source.path contra la raíz del proyecto,
comprueba que el .dzn enlazado existe y carga sus datos principales:
dimensiones, capacidades, demandas, tamaño de la matriz de costes e
incompatibilidades.