# Gravitatsioonimudel (trip distribution)

## Eesmärk

Jaotada liikumised väljapääsupunktide vahel nii, et **ühtegi sihtpunkti ei eelistata a priori** — sarnaselt jõgikonna vee liikumisele. See on gravitatsioonimudeli (gravity model) põhiolemus.

## Ühtne süsteem (2026-08)

Rahvastiku ja liikumiste jaotus väljapääsupunktide vahel põhineb **gravitatsioonimudelil**:

1. **Sõlme-taseme rahvastik** (`{prefix}_node_population.csv`) — WorldPop-i rahvastik igal kohaliku tee sõlmel (population-analüüs §5)
2. **Gravitatsioonipõhine parim väljapääs** iga sõlme jaoks — impedants + gravitatsioonitõmme (vt allpool)
3. **Gravitatsioonipõhine rahvastik väljapääsupunkti kohta** (`{prefix}_gravity_exit_population.csv`) — iga sõlme rahvastik liidetakse selle sõlme parima väljapääsupunkti alla
   - `gravity_population`, `gravity_trips` (= 2 × pop)
   - Võrdluseks `nearest_population`, `nearest_trips` (lähim-jaotus)

See on **peamine rahvastiku hinnang** veebiatlasesse (popup "Elanikke (gravitatsioon)").

## Kontseptsioon

Klassikalises gravitatsioonimudelis on kahe piirkonna vaheline liikumine võrdeline nende "masside" (rahvastiku) korrutisega ja pöördvõrdeline kauguse/kulu astmega:

```
T_ij ∝ (P_i · P_j) / f(c_ij)
```

Selles rakenduses on igal teede sõlmel:
- **kulupotentsiaal** lähima väljapääsupunktini (impedance)
- **gravitatsiooniline atraktiivsus** — mida suurem väljapääsupunkti teenindatav rahvastik, seda rohkem see trippe "tõmbab"

## Meetod

### 1. Ühtne impedance-kaalutud graaf

```python
unified = nx.Graph()
weight = length * impedance_factor
```

Iga tee klass on kaalutud impedantsi kordajaga (kõrgem = aeglasem/vähem eelistatud):

| Tee klass | Impedants |
|-----------|-----------|
| motorway, trunk | 1.0 |
| primary | 1.1 |
| secondary | 1.3 |
| tertiary | 1.8 |
| residential, unclassified, service | 4.0 |
| track | 5.0 |

### 2. Gravitatsiooniline kulufunktsioon

```python
GRAVITY_ALPHA = 1000   # meetrit log-rahvastiku ühiku kohta
adjusted_cost = path_impedance - alpha * log(population + 1)
```

Suurem teenindusala rahvastik **vähendab** efektiivset kulu (tõmbab trippe juurde):
- linn 1000 inimesega: `alpha * ln(1001) ≈ 6.9 km` kompensatsioon
- küla 100 inimesega: `alpha * ln(101) ≈ 4.6 km` kompensatsioon

### 3. Parima väljapääsupunkti valik

Iga sõlme jaoks leitakse Dijkstra'ga kulu igast väljapääsupunktist, kohandatakse gravitatsiooniga, ja parim = argmin(adjusted_cost):

```python
best_exit = argmin(adjusted_cost)  # gravitatsiooniga kohandatud
nearest_exit = argmin(impedance)   # lihtsalt lähim (võrdluseks)
switched = best_exit != nearest_exit
```

`switched` näitab, kus gravitatsioon muudab valikut (sõlm kuulub "loogiliselt" kaugemasse, aga suuremasse keskusesse).

### 4. Sõlmede ja lõikude jaotus

- `{prefix}_gravity_node_exits.csv` — iga sõlm: `best_exit`, `impedance_to_exit`, `gravity_value`, `switched`
- `{prefix}_gravity_segment_exits.csv` — iga lõik: `best_exit`, `impedance_to_exit`, `assignment_type`

### 5. Gravitatsioonipõhine rahvastik väljapääsupunkti kohta

```python
for node, e in best_exit.items():
    grav_exit_pop[e] += node_population[node]
```

`{prefix}_gravity_exit_population.csv` — iga väljapääsupunkti rahvastik + päevased sõidud (2× pop).

## Gravitatsioon vs lähim väljapääs

- **Lähim (nearest):** aluseks [[Liiklussageduse kaudne hindamine/02_Metoodika/03 Väljapääsupunktid ja teenindusalad]] — iga sõlm lähima väljapääsupunkti teenindusalasse
- **Gravitatsioon:** suuremad keskused tõmbavad kauemalt liikumisi — realistlikum "voolupilt"

**Veebiatlases:** väljapääsupunkti `pop`/`trips` = **gravitatsioonipõhine** (peamine). Lähim-jaotus on võrdluseks popupis ("Lähim-jaotus") ja `nearest_pop_catch` veeruna.

## Rakendus

Skript: `pipeline/gravity_exit_analysis.py`
Loeb: `{prefix}_pop_catchment.csv` (väljapääsu rahvastik), `{prefix}_node_population.csv` (sõlmede rahvastik)
Kirjutab: `{prefix}_gravity_node_exits.csv`, `{prefix}_gravity_segment_exits.csv`, `{prefix}_gravity_exit_population.csv`

