Allocatie procedure in formules
Modeloverzicht
Het model van landallocatie en -ontwikkeling schematiseert hoe eigenaren van land units (bijvoorbeeld rastercellen) een subsector kiezen, en hoe ontwikkelaars van subsectoren besluiten of zij een land unit willen ontwikkelen. De keuzes worden verondersteld gestuurd te worden door ontwikkelwinsten en regionale claims per subsector-regio. N.B. Het model schat géén marktevenwicht of prijsaanpassing.
Sets
- $I$: set van land units (e.g. rastercellen), index $i$.
- $J$: set van subsectoren (e.g. eengezins vrije sector woningen), index $j$.
- $R$: set van regio’s (e.g. NVM, COROP, Provincie), index $r$.
Parameters
- $p_{ij}$: potentiele verkoopprijs van een woonobject op land unit $i$ in subsector $j$ (met kenmerken van het onderliggende ontwikkelpakket)
- $c^b_{ij}$: bouwkosten op land unit $i$ per object van subsector $j$ (met kenmerken van het onderliggende ontwikkelpakket)
- $c^s_{ij}$: sloopkosten op land unit $i$ per object van subsector $j$
- $D_{ij}$: aantal objecten van subsector $j$ dat in land unit $i$ kan worden gerealiseerd bij potentiële dichtheid
- $E_{ij}$: bestaand aantal objecten van subsector $j$ in land unit $i$
- $K^v_{ij}$: verwervingskosten van de huidige objecten op land unit $i$ per object van subsector $j$
- $K^w_i$: kosten voor woon-/bouwrijp maken van land unit $i$
- $K^p_i$: plan- en proceskosten voor land unit $i$
- $K^g_i$: bovenwijkse kosten voor land unit $i$
- $R_{ir}\in \{0,1\}$: regio assignment matrix, de mate waarin land unit $i$ in regio $r$ ligt, i.e. \(\forall i: \sum_{r} R_{ir} = 1\)
- $C_{jr}$: claim (regionale vraag) van subsector $j$ in regio $r$
De ontwikkelkosten $c^{ow}_i$ van land unit $i$ voor subsector $j$ worden berekend als:
\[c^{ow}_i := K^w_i + K^p_i + K^g_i + \sum_j [ (K^v_{ij} + c^s_{ij}) \cdot E_{ij} ]\]De ontwikkelwinst $S_{ij}$ van land unit $i$ voor subsector $j$ wordt berekend als:
\[S_{ij} = (p_{ij} - c^b_{ij}) \cdot D_{ij} - c^{ow}_i\]Beslissingsvariabelen
- $x_{ij}\in\{0,1\}$: 1 als land unit $i$ herontwikkeld wordt naar subsector $j$; anders 0.
- $x_{i0}\in \{0,1\}$: 1 als land unit $i$ ongewijzigd blijft (status quo); anders 0. Buitenoptie $j=0$ heeft by definition $S_{i0}=0,\ D_{i0}=0$.
- $Z_{jr}$: minimale ontwikkel-winst die ontwikkelaar $j$ in regio $r$ kan verlangen.
Formulering van het model
Doel/heuristiek
We wijzen ontwikkelopties $ij$ toe in aflopende volgende van $S_{ij}$ voor zover subsector $j$ nog niet $C_{jr}$ kan realiseren met eerdere toewijzingen. De consequentie hiervan is dat er voor iedere $j$ indien gesatureerd is, een laatste toewijzing is met waarde $S_{ij}$, dit noemen we $Z_{jr}$. Met andere woorden, iedere ontwikkelaar $j$ ontwikkelt verkregen land units binnen regio $r$ tot aan $Z_{jr}$:
\[\max Z_{jr} \qquad \forall j, \forall r \qquad \text{(1)}\]Gegeven voorwaarde (2):
\[Z_{jr} \cdot R_{ir} \cdot x_{ij} \le S_{ij} \cdot x_{ij} \qquad \forall i, \forall j, \forall r \qquad \text{(2)}\]Er geldt dat voor iedere $i$ met $S_{ij} > Z_{jr}$ dat die gealloceerd is aan $j$ of een betere optie en voor iedere $S_{ij} <= Z_{jr}$ dat die $i$ tenminste niet aan die $j$ is toegewezen.
Iedere eigenaar van land unit $i$ wordt veronderstelt de land units beschikbaar te stellen aan de ontwikkelaar van subsector $j$ voor zover subsector $j$ deze unit nog wil ontwikkelen.
\[\max_{x}\sum_{i} S_{ij} \cdot x_{ij} \qquad \forall i \qquad \text{(3)}\]Exclusiviteit per land unit $i$ (exact één keuze: herontwikkel of niets doen):
\[\sum_{j} x_{ij} + x_{i0} = 1 \qquad \forall i \qquad \text{(4)}\]Regionale claims op eindvoorraden:
\[\sum_{i} R_{ir} \cdot \left( E_{ij} \cdot x_{i0} + D_{ij} \cdot x_{ij} \right) \ge C_{jr} \qquad \forall j, \forall r \qquad \text{(5)}\]Oftewel, bij herontwikkeling $(x_{ij}=1)$ vervangt $D_{ij}$ de bestaande $E_{ij}$ in die land unit; bij niets doen $(x_{i0}=1)$ blijft $E_{ij}$ staan.
Aannames:
- elke land unit heeft een aparte ontwikkelaar (eigenaar) die een onafhankelijke keuze maakt.
- uitkopen huidig opstal obv huidige prijzen
Binnen algeheel allocatie proces
Het allocatieproces wordt op meerdere niveaus herhaald. De hiërarchie is als volgt:
- Zichtjaren – per zichtjaar wordt het model opnieuw uitgevoerd.
- Sequenties – binnen een zichtjaar vinden meerdere sequenties plaats.
- Sector-alloc-regio’s – binnen elke sequentie wordt per sector-alloc-regio gealloceerd (bijvoorbeeld Wonen – NVM).
- Iteraties – binnen een sector-alloc-regio wordt het allocatiemodel iteratief toegepast totdat claims zijn verwerkt.
De volgorde van sector-alloc-regio’s wordt bepaald in de variantparameters. Uiteindelijk wordt dus hetzelfde model meerdere keren uitgevoerd, afhankelijk van zichtjaar, sequentie, regio en iteratie.
Sequenties en verdringing
Sequenties zijn nodig om verdrongen objecten (zoals woningen of banen) opnieuw te kunnen alloceren.
Wanneer in een eerdere sequentie objecten worden verdrongen, levert dit restclaims op. Deze restclaims worden in de volgende sequentie opnieuw ingebracht, zodat ze alsnog elders gealloceerd kunnen worden.
Verzorgend werken blijft bij wonen
Op die verdringingsregel geldt sinds ObjectVision/RSopen#710 een uitzondering. De verdringing zette alle werkgelegenheid in een cel op nul zodra wonen die cel won, dus elke woningbouwlocatie sloopte de buurtvoorzieningen die er stonden. Die banen kwamen als restclaim terug en moesten elders landen, en omdat binnen bestaand gebied nauwelijks iets beschikbaar is, landden ze op kaal buitengebied. Gemeten in zichtjaar 2040 van WLO_hoog BAU ging het om 135.924 banen in een enkel zichtjaar, goed voor 22,6 procent extra restclaim voor de drie verzorgende subsectoren.
Dat het om een artefact gaat en niet om een modelkeuze blijkt uit de basisjaarstand zelf: die zit vol cellen met woningen en banen tegelijk, dus de menging is prima representeerbaar. Alleen het moment van herallocatie vernietigde haar.
Er zijn nu twee regels, elk op een schakelaar in ModelParameters/Werken:
VerzorgendBlijftBijWoningbouw: detailhandel, overige consumentendiensten en overheid en kwartaire diensten blijven staan waar wonen de cel wint, inclusief hun pandvoetafdruk. De hoofdfunctie van de cel wordt wonen, de voorzieningen blijven eronder staan. Niet-verzorgend werken wordt wel gesloopt, want een fabriek verdwijnt wel als er een wijk komt, en andere sectoren die de cel overnemen, zoals waterberging of natuur, slopen ook door.VerzorgendInWoonOP: een woonontwikkelpakket brengt zelf verzorgende werkgelegenheid mee, ter hoogte van de woningdichtheid van het pakket maal de waargenomen verhouding banen per woning. Die verhouding is gemeten op de basisjaarstand inBaseData/StartState/VerzorgendBijWonenen niet als expertgetal ingevoerd: op woongebiedcellen staan 6.966.258 woningen met 0,0258 baan detailhandel, 0,0721 overige consumentendiensten en 0,1154 overheid en kwartaire diensten per woning. De bezetting is een ondergrens naast wat er al stond, en deze banen krijgen geen eigen pandvoetafdruk omdat zij in de plint van het pakket zitten en dus al in de gebouwvoetafdruk die het pakket oplegt.
Welke subsectoren verzorgend zijn staat als data in Classifications/Actor/Jobs6/IsVerzorgend, met een IntegrityCheck die de vlag aan de subsectornamen bindt.
Samen brengen de twee regels de restclaim van deze drie subsectoren na het wonenblok van 738.457 naar 418.097 banen. De pakketbezetting gebruikt 37,2, 49,9 en 23,9 procent van de ruimte tot de claim, dus zij loopt niet boven de claim uit. Dat laatste is de toets die eerst moest: banen zijn exogeen en zijn de claimvariabele, en bij ObjectVision/RSopen#668 leverde een regel die de stand ophoogde eerder overrealisatie op voordat de allocatie begon.
Overflow-mechanisme
Het alloceren start altijd op het laagste ruimtelijke niveau (bijvoorbeeld regio A).
- Eerst wordt geprobeerd alle claims binnen regio A te plaatsen.
- Indien dit niet lukt (te weinig geschikte locaties), wordt de restclaim bepaald:
\(\text{restclaim} = \text{claim} - \text{gerealiseerd in A}\) - Deze restclaim wordt vervolgens doorgeschoven naar een hoger ruimtelijk niveau (regio B, dat A bevat).
- Het allocatieproces verloopt in regio B identiek, maar nu met de resterende claims. Zo kunnen claims die lokaal niet passen alsnog regionaal worden opgevangen.

Dichtheden
Bij allocatie is niet alleen de keuze welke subsector in welke land unit wordt ontwikkeld van belang, maar ook met welke dichtheid dit gebeurt.
- Elke subsector heeft een potentiële dichtheid ($D_{ij}$), die de maximale intensiteit van gebruik in een land unit aangeeft (bijv. aantal woningen per hectare).
- De ontwikkel-winst ($S_{ij}$) is berekend gegeven deze potentiële dichtheid, inclusief bouwkosten, sloopkosten en bijkomende plan- en inrichtingskosten.
- Bij toewijzing van een claim wordt dus impliciet een keuze voor een bepaalde dichtheid gemaakt: hogere dichtheden vergen meer investeringen maar kunnen per saldo meer objecten opleveren.
Iteraties
Binnen elke sector-alloc-regio loopt het allocatieproces iteratief.
Bij elke iteratie worden opties met de hoogste ontwikkelwinst ($S_{ij}$) geselecteerd, totdat de regionale claims ($C_{jr}$) zijn ingevuld of geen geschikte opties meer beschikbaar zijn.
Allocatiedomein: van AllocDomain naar AdminDomain
In eerdere modelversies werd de allocatie zelf uitgevoerd op een grover AllocDomain (doorgaans 100 m), terwijl geschiktheid en beschikbaarheid op het fijnere AdminDomain (25 m) werden bepaald. Versnippering werd toen tegengegaan met een minimale-beschikbaarheidsdrempel per AllocDomain-cel (MinimalLandAvailability): een 100 m-cel die te weinig vrij oppervlak overhield werd restrictief verklaard.
Voor de stedelijke sectoren is dit AllocDomain inmiddels grotendeels uitgefaseerd. De allocatie vindt nu rechtstreeks plaats op het 25 m-niveau, op het zogeheten CompactedAdminDomain. Dat is de verzameling AdminDomain-cellen die binnen het studiegebied vallen (select_with_attr_by_org_rel(AdminDomain, AdminDomain/IsCompactedDomain)). Het “compacten” houdt het domein klein en daarmee de allocatie snel. Welke 25 m-cellen meedoen wordt nog steeds op AllocDomain-niveau bepaald, zodat er geen losse 25 m-celletjes buiten de selectie vallen. Het AdminDomain- en AllocDomain-grid zijn instelbaar via ModelParameters/Advanced/AdminDomain_ref en AllocDomain_ref.
Het wegvallen van de grove AllocDomain-drempel betekende dat versnippering (losse cellen, smalle linten) op een andere manier moest worden voorkomen. Daarvoor is geclusterd alloceren geïntroduceerd.
N.B. De AllocDomain-drempel is niet overal verdwenen. Voor landbouw geldt nog steeds een minimale-beschikbaarheidsdrempel (
MinimalLandAvailability_Landbouw, standaard 0,60 ha per hectare, sinds #770 toegepast als aandeel van een schijf van 50 meter rond de cel van 25 meter), omdat landbouw via discrete allocatie op een ander spoor loopt.
Geclusterd alloceren
Geclusterd alloceren vervangt de oude minimale-beschikbaarheid-per-AllocDomain-cel door een eis op de aaneengeslotenheid en omvang van het allocatieresultaat zelf. Het doel is “geen confetti”: geen versnipperde, losliggende of lintvormige toewijzingen, maar samenhangende clusters van voldoende omvang (bijvoorbeeld woonmilieus, bedrijventerreinen of waterbergingsgebieden).
De stappen binnen één iteratie (zie Templates/Allocatie/Iter_T/Iter_Allocatie.dms) zijn:

-
Afkapgrens en arg_max (zie hierboven). Per subsector wordt met de weighted nth element de afkapgrens bepaald en met arg_max per cel de winnende subsector gekozen. Dit levert een ruw allocatieresultaat op 25 m op. Voor werken is deze onderlinge keuze sinds augustus 2026 lexicografisch: eerst wint de subsector met plancapaciteit- of stimuliprioriteit op die cel (hard boven zacht boven stimuli, KanOp-gefilterd), pas daarbinnen de hoogste MNL-kans (
ModelParameters/Werken/TredePrioriteitInSubsectorKeuze). De tredescores zelf zijn hiervoor onbruikbaar, omdat het aantal treden per subsector verschilt. Binnen een subsector rangschikt werken bovendien op het raw-nut in plaats van de kans (GeschiktheidAlsRaw), omdat de MNL-noemer per cel verschilt en de rangorde verstoort; zie Geschiktheid. -
Morfologische opschoning (lintfilter). Smalle linten, bijvoorbeeld het volbouwen van een weg dwars door de stad, worden eruit gefilterd via een erosie-dilatie (opening):
- Erosie: een cel overleeft alleen als minimaal een instelbaar aantal van zijn acht buren ook is gealloceerd (
ModelParameters/Advanced/MorfologischeCleaning_BuurCellen_<sector>, per sector instelbaar, voor alle sectoren 6). Dat is de minimale beukmaat: 6 buren komt neer op 75 meter, 5 op 50 meter. - Dilatie: een cel hoort weer bij het resultaat als minstens één buurcel de erosie overleefde.
- Het opgeschoonde resultaat is de oorspronkelijke allocatie binnen het gedilateerde gebied. Cellen die hierdoor afvallen krijgen
IsAfgewezen_dmv_Morfologie.
- Erosie: een cel overleeft alleen als minimaal een instelbaar aantal van zijn acht buren ook is gealloceerd (

De figuur laat de vier stappen zien, met het echte algoritme toegepast op een voorbeeldpatroon van 34 bij 22 cellen. Blauw is wat er na die stap overblijft, lichtgrijs is wat de ruwe allocatie had en onderweg is afgevallen. De drempel staat hier op 6 buren en de minimale clusteromvang op 16 cellen, dus 1 hectare.
Van boven naar beneden. De ruwe allocatie bevat een compact blok van 8 bij 8, een strook van 3 cellen breed, een strook van 2 cellen breed, een lint van 1 cel breed, een blokje van 3 bij 3 en een handvol losse cellen. Na de erosie blijven alleen de binnenkant van het blok, de middelste rij van de strook van 3 en het hart van het blokje over; de strook van 2, het lint en de losse cellen halen de eis van 7 van de 9 niet en verdwijnen. De dilatie zet daar weer een rand omheen en de doorsnede met de oorspronkelijke allocatie herstelt het blok en de strook van 3 precies. De toets op clusteromvang gooit tenslotte het blokje van 9 cellen eruit, want dat haalt de hectare niet. Van de 156 gealloceerde cellen blijven er 100 over.
-
Clusteren met
district_8. De opgeschoonde cellen worden metdistrict_8gegroepeerd tot aaneengesloten districten (8-connectiviteit). Per district wordt het oppervlak bepaald (pcountmaal ha per cel). Aaneengeslotenheid mag ontstaan door cellen van verschillende subsectoren, en ook door cellen van andere sectoren die dit zichtjaar zijn gealloceerd; waterberging is daarop de uitzondering. Zie Hoe ver de aangroei reikt. -
Toets op minimale clustergrootte. Een cluster wordt alleen behouden als het oppervlak boven de minimumdrempel ligt. De drempel verschilt binnenstedelijk versus buitenstedelijk, bepaald uit de BRT-woonkernkaart (
SourceData/Grondgebruik/BRT/IsWoonkern):Sector Binnenstedelijk (woonkern) Buitenstedelijk Wonen 0,4 ha 2 ha Werken 0,4 ha 2 ha Verblijfsrecreatie 0,4 ha 2 ha Waterberging 2 ha (uniform) 2 ha (uniform) De drempels staan in
ModelParameters/AdvancedalsMinimum_alloc_group_size_Binnenstedelijk_<sector>enMinimum_alloc_group_size_Buitenstedelijk_<sector>. Waterberging valt daarbuiten: die heeft een enkele drempelMinimum_alloc_group_size_Waterberging, zonder het binnen- versus buitenstedelijke onderscheid. Het grootste cluster in een regio (IsNonGroup) wordt altijd behouden, mits het minstens een halve hectare beslaat, zodat een claim nooit volledig op de clustertoets sneuvelt. -
Afgewezen cellen vallen terug in de volgende iteratie. Cellen in te kleine clusters (of weggefilterd door de morfologie) worden
IsAfgewezen. Deze afwijzing wordt cumulatief over iteraties bijgehouden (IsAfgewezen_Cumulatief). Vanaf een instelbare iteratie (ModelParameters/Advanced/IterVanafWaarWeAfgewezenCellenUitsluitenInAlloc, standaard 1) worden afgewezen cellen uit de beschikbaarheid gehaald, zodat de weighted nth element in een volgende iteratie elders zoekt.
Hoe een cluster kan aangroeien
De erosie, de dilatie en de districtenbepaling kijken naar alles wat er dit zichtjaar al gealloceerd is, plus de cellen van de lopende iteratie. Daardoor kan een cluster over iteraties heen aangroeien. Alleen cellen van de lopende iteratie kunnen nog worden afgewezen; wat al ligt blijft liggen.
Dat was niet altijd zo. Tot augustus 2026 keken de vormtoetsen alleen naar de lopende iteratie, en dat had twee gevolgen die lang onopgemerkt zijn gebleven. Een bestaand cluster kon niet aangroeien: een cel die tegen een eerder gealloceerd gebied aan lag, zag in de erosiestap alleen zijn niet-gealloceerde buren, haalde de eis van zes van de acht buren niet en werd blijvend uitgesloten. Elke iteratie moest op eigen kracht een compleet nieuw cluster van voldoende omvang vormen, en verloor daarbij opnieuw zijn eigen rand. En zolang de afgewezen cellen nog niet blijvend werden uitgesloten stond het proces stil: de allocatie koos steeds dezelfde randcellen, die steeds weer afvielen.
De ingreep bracht de claimrealisatie van waterberging in zichtjaar 2030 van 89,0 naar 99,2 procent, en samen met een geclusterde rangorde naar 99,99 procent, met een achtmaal kleiner aantal afgewezen cellen. Bij wonen daalde het aantal afgewezen cellen met 27 procent en steeg het aandeel dat binnen een woonkern landt van 16,9 naar 20,2 procent. Zie #575, #643 en Uitwerking waterberging.
Hoe ver de aangroei reikt
Waar de aangroei begint en ophoudt is een bewuste afbakening, want de lopende stand SubSector_rel stapelt van nature veel breder op dan bedoeld.
Wat wel meetelt: alle iteraties, sector-allocregios en sequenties binnen hetzelfde zichtjaar. Wonen op COROP bouwt dus voort op wat wonen op NVM heeft neergezet.
Wat ook meetelt, behalve voor waterberging: cellen van andere sectoren. Een woning die tegen een nieuw bedrijventerrein aan ligt is geen versnipperde ontwikkeling, dus die mag aanhechten. Bij waterberging is de minimale clusteromvang een functionele eis, want een bergingsgebied moet zelf groot genoeg zijn om water vast te houden, en dat wordt niet anders van woningen ernaast. Daar tellen alleen eigen cellen.
Wat niet meetelt: wat er in eerdere zichtjaren is gealloceerd. Zonder die grens werkt het model zich over een reeks zichtjaren cel voor cel het landschap in.
Wat ook niet meetelt: de bestaande bebouwing uit het basisjaar. Dat is de eigenschap die versnippering tegenhoudt. Zou een cel naast een bestaand dorp de toets al halen omdat dat dorp er staat, dan is de minimale clusteromvang betekenisloos en krijg je precies de losse spikkels die het mechanisme moet voorkomen. Nu geldt: het eerste cluster van een zichtjaar moet op eigen kracht aan de drempel voldoen, en pas daarna mag eraan gegroeid worden.
De aangroei geldt voor alle sectoren, dus ook wonen, werken en verblijfsrecreatie krijgen er clusters mee die over iteraties heen kunnen aangroeien.
Let daarbij op de rol van IterVanafWaarWeAfgewezenCellenUitsluitenInAlloc. Dat mechanisme lijkt een rem maar is een motor. Cellen die losliggend boven de zaaglijn uitkomen hebben geen gealloceerde buren en halen de erosie-eis nooit, ook niet met de cumulatieve toets. Zolang ze beschikbaar blijven kiest de allocatie ze elke iteratie opnieuw en wijst ze elke iteratie opnieuw af, zonder dat er iets gealloceerd wordt. Pas na blijvende uitsluiting komt de allocatie verder. De parameter staat daarom op 1: een afgewezen cel blijft meteen uitgesloten voor de rest van deze sector en allocregio. Op de eerdere waarde 5 kostte dat vier lege iteraties met precies dezelfde eindstand. Twee mildere varianten zijn geprobeerd en allebei afgevallen, zie #643.
Een minimale beukmaat (minimale breedte van een cluster) staat als de erosie-eis per sector in de morfologische opening; een aparte breedtetoets is er niet. Samenhang wordt verder via de minimale clusteromvang afgedwongen.
Geclusterd alloceren is generiek over de sectoren wonen, werken en verblijfsrecreatie, en wordt ook gebruikt door de nieuwe sector waterberging (met een eigen, uniforme drempel). Zie issue ObjectVision/RSopen #508.