Skip to content

[Core] Zones create demands #16

Description

@Lecrapouille
## 4. Génération de la demande OD (le modèle gravitaire)

### 4.1 Le problème que ça résout

Dans le document précédent, la matrice OD $d_{ij}$ était une donnée d'entrée du solveur de trafic. Dans un jeu type SimCity, elle doit au contraire être **générée dynamiquement** à partir de l'état de la ville (population, emplois, attractivité des zones) — recalculée à chaque fois que la ville évolue significativement.

### 4.2 Modèle gravitaire simple

Emprunté à la physique (loi de gravitation), par analogie : deux zones "s'attirent" proportionnellement à leur masse (population, emplois) et inversement à la distance qui les sépare :

$$
d_{ij} = k \cdot \frac{P_i \cdot E_j}{d(i,j)^\gamma}
$$

- $P_i$ : population de la zone $i$ (origine)
- $E_j$ : emplois disponibles dans la zone $j$ (destination)
- $d(i,j)$ : distance (ou coût de trajet) entre $i$ et $j$
- $\gamma$ : exposant de friction de distance, typiquement $1$ à $2$ — plus $\gamma$ est grand, plus la distance décourage le trajet
- $k$ : constante de calibration (ajustée pour que le total de trajets générés corresponde à un ordre de grandeur réaliste)

Directement exploitable avec les structures `Unit`/`Resources` déjà existantes dans OpenGlassBox : population comme ressource portée par les `Units` résidentielles, emplois comme capacité d'un `Sink` industriel/commercial.

### 4.3 Généralisation à plusieurs couches : attractivité composite

Le problème pratique : une ville a plusieurs facteurs d'attractivité (emplois, mais aussi pollution, désirabilité, criminalité...). La structure de la formule ne change pas — on remplace seulement $E_j$ par un score composite $A_j$ :

$$
d_{ij} = k \cdot \frac{P_i \cdot A_j}{d(i,j)^\gamma}
$$

**Option naïve (multiplicative)** — chaque couche devient un facteur à exposant, sur le modèle de Cobb-Douglas :

$$
A_j = E_j^{\,w_1} \cdot Des_j^{\,w_2} \cdot (1 + Pol_j)^{-w_3}
$$

Problème pratique : ingérable dès qu'on ajoute des couches (un exposant à calibrer par couche), et fragile si une couche vaut $0$ (le produit entier s'annule).

### 4.4 Combinaison log-linéaire (recommandée)

Forme utilisée dans les modèles de choix de destination modernes, directement liée à la structure du modèle logit (document précédent, §5.1) :

$$
A_j = \exp\left(\sum_{k} \beta_k \, x_{jk}\right) = \exp\big(\beta_1 E_j + \beta_2 Des_j - \beta_3 Pol_j + \cdots \big)
$$

- $x_{jk}$ : valeur (normalisée) de la couche $k$ dans la zone $j$
- $\beta_k$ : poids de la couche $k$ — **positif** si elle attire (emplois, désirabilité), **négatif** si elle repousse (pollution, criminalité)

**Avantages sur la forme multiplicative** :
- Ajouter une couche = ajouter un terme dans la somme (linéaire), pas remultiplier toute la formule
- Aucune couche ne peut annuler tout le score à elle seule (contrairement au produit)
- Cohérence mathématique directe avec le modèle logit déjà utilisé pour le choix de *chemin* — ici appliqué au choix de *zone destination*, même famille de modèle dans tout le moteur

### 4.5 Conservation des flux : modèle à double contrainte

Une fois $A_j$ défini, un problème apparaît : rien ne garantit que $\sum_j d_{ij}$ (total des trajets partant de $i$) corresponde réellement à la population de $i$, ni que $\sum_i d_{ij}$ (total arrivant en $j$) ne dépasse la capacité réelle d'emploi de $j$. Le modèle gravitaire brut peut "inventer" des trajets en excès ou saturer une zone au-delà du possible.

La solution standard, le **modèle gravitaire à double contrainte** (Wilson, 1967), introduit deux facteurs d'équilibrage $\alpha_i$ et $\beta_j$ :

$$
d_{ij} = \alpha_i \, \beta_j \, P_i \, A_j \, f\big(d(i,j)\big), \qquad f(d) = d^{-\gamma} \ \text{(ou } e^{-\gamma d} \text{)}
$$

sous les deux contraintes de conservation :

$$
\sum_j d_{ij} = P_i \qquad \text{(tout le monde à } i \text{ part effectivement)}
$$

$$
\sum_i d_{ij} = C_j \qquad \text{(la zone } j \text{ n'absorbe pas plus que sa capacité } C_j\text{)}
$$

### 4.6 Résolution par IPF (Iterative Proportional Fitting / algorithme de Furness)

Les facteurs $\alpha_i, \beta_j$ ne se calculent pas directement en une formule fermée — ils s'obtiennent par un algorithme itératif :

1. Initialiser $\beta_j = 1$ pour tous les $j$
2. Calculer $\alpha_i$ pour que chaque ligne $i$ vérifie $\sum_j d_{ij} = P_i$
3. Calculer $\beta_j$ pour que chaque colonne $j$ vérifie $\sum_i d_{ij} = C_j$
4. Répéter les étapes 2–3 jusqu'à ce que les deux contraintes soient satisfaites à une tolérance près

**Remarque de cohérence avec le reste du moteur** : c'est encore un algorithme à point fixe par itérations successives — même famille que MSA (document précédent, §4), sauf qu'ici on ajuste deux facteurs d'échelle en alternance plutôt qu'un flux sur un graphe. Trafic (MSA), économie (EMA) et génération de la demande (IPF) partagent ainsi le même principe algorithmique de base : converger par ajustements successifs plutôt que résoudre un système exact d'un coup — cohérent avec une simulation qui doit rester réactive à une ville en évolution constante plutôt que recalculer un équilibre figé.

### 4.7 Récapitulatif des couches pour OpenGlassBox

| Couche | Rôle dans $A_j$ | Signe de $\beta_k$ |
|---|---|---|
| Emplois disponibles | Attractif | $+$ |
| Désirabilité (parcs, vue, calme) | Attractif | $+$ |
| Pollution | Répulsif | $-$ |
| Prix du logement / loyer | Répulsif pour habiter, neutre pour un trajet travail | dépend du contexte |
| Criminalité | Répulsif | $-$ |

Chaque couche correspond probablement déjà à une `Map` spatiale dans GlassBox — $A_j$ devient une combinaison pondérée de plusieurs `Maps` lues à la position $j$, recalculée uniquement quand la demande OD est régénérée (pas nécessairement à chaque tick).```

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions