Ga naar inhoud

Maatregelen bundelen

De bundelingstool draait om het slim bundelen van maatregelen in de tijd. Hiervoor is een optimalisatiemodel geïmplementeerd dat aan te roepen is vanuit Python. In deze handleiding verkennen we de opties daarvoor.

Voor de volledigheid: RwsProject inladen

Voor de rest van deze handleiding gaan we er vanuit dat er een RwsProject is ingeladen:

from raplan_rws.project import Horizon, RwsProject

# Een horizon van 2026 tot 2050 om de maatregelen te filteren.
horizon = Horizon(start=2026, end=2050)

# Laad het RWS project in vanaf een Excel.
rws_project = RwsProject.van_excel_bestand(
    # Bestandspad naar de maatregelplanning
    "../generated/irene_marijke_volledig.xlsx",
    # Projectnaam (mag alles zijn)
    naam="Irene -en Marijkesluis",
    # Horizon van 2026 tot 2050
    horizon=horizon,
    # Maximale uitstel wordt genomen als factor maal het uiterst advies-uitstel
    vervroeging_factor=0.25,
    # Bonus t.o.v. uiterst advies jaar
    later_dan_uiterst=0,
    # Maximaal aantal jaar naar voren
    max_vervroeging=1,
    # Maximaal aantal jaar naar achter
    max_uitstel=5,
)

Bundelen van maatregelen per kolk

Hier maken we een kopie van het projectobject en voeren een optimalisatie met de standaardinstellingen uit die steeds per kolk de maatregelplanning heroverweegt.

Later gaan we de standaardinstellingen aanpassen.

  • Na optimalisatie wordt de gewijzigde planning weggeschreven naar een Excelbestand.
  • Alle nodige informatie zit hierin opgeslagen en is weer in te laden met RwsProject.van_excel_bestand.
  • Op deze manier kun je ook handmatig aangepaste data uit de Excel terug inladen voor visualisatie!
# Maak een kopie om in te werken met de optimalisatie.
optim = rws_project.maak_kopie()

# Zet een wat kortere horizon om de optimalisatie sneller te laten verlopen.
optim.horizon = Horizon(start=2026, end=2036)
optim.herbouw_project()

# Bundel maatregelen per kolk met de standaardinstellingen.
optim.bundel_maatregelen_per_kolk()

# Schrijf de gebundelde planning weer weg naar Excel.
suffix = "per_kolk"
optim.naar_excel_bestand(f"./generated/irene_marijke_{suffix}.xlsx")

Bundelen van maatregelen met instellingen

Er zijn een aantal parameters om aan te draaien en de optimalisatie.

In het snippet hieronder wordt een instellingen object aangemaakt en toegepast op een nieuwe kopie van de planning.

from raplan_rws.model import Discipline, MaatregelVerschuiving, MaatregelSynchronisatie, ModelInstellingen

# Maak eigen instellingen
instellingen = ModelInstellingen(
    maatregel_verschuiving=MaatregelVerschuiving(
        gratis_naar_voren=True,
        vaste_factor=0,
        kosten_per_jaar_factor=0,
        frequentie_factor=0,
        specifiek={},
    ),
    maatregel_synchronisatie=MaatregelSynchronisatie(
        forceer_gelijk_starten=False,
        verbied_duplicatie=True,
        jaar_samenvallen=-1,
        zelfde_discipline=-0.1,
        discipline_combis={
            frozenset((Discipline.Werktuigbouw, Discipline.Elektrotechniek)): -0.05,
            frozenset((Discipline.Werktuigbouw, Discipline.IndustriëleAutomatisering)): -0.05,
            frozenset((Discipline.Elektrotechniek, Discipline.IndustriëleAutomatisering)): -0.05,
            frozenset((Discipline.IndustriëleAutomatisering, Discipline.CyberSecurity)): -0.05,
            frozenset((Discipline.Civiel, Discipline.Algemeen)): -0.05,
        },
    ),
    model_output=False,  # Zet op `True` om meer tussentijdse output te zien van de solver.
    tijdsduur_naar_jaar=1,  # Aan te raden om zo te laten.
    segmenten_per_jaar=1,  # Aan te raden om zo te laten.
    score_precisie=1,  # Aan te raden om zo te laten.
)

# Maak een kopie om in te werken met de optimalisatie.
optim2 = optim.maak_kopie()
# ALTERNATIEF: wederom een kopie van het origineel en pas eventueel een aangepaste horizon toe.
# optim2.horizon = Horizon(start=2026, end=2036)
# optim2.herbouw_project()

# Bundel maatregelen per kolk met de standaardinstellingen.
optim2.bundel_maatregelen_per_kolk(instellingen=instellingen)

# Schrijf de gebundelde planning weer weg naar Excel.
suffix = "per_kolk_met_instellingen"
optim2.naar_excel_bestand(f"../generated/irene_marijke_{suffix}.xlsx")

Zie de volgende secties voor toelichting van de instellingen en het spanningsveld dat ze opspannen in de optimalisatie.

Wat betreft de tijdsduur_naar_jaar, segmenten_per_jaar, score_precisie

MaatregelVerschuiving: Instellingen voor het verschuiven van maatregelen

Zoals hierboven te zien is, is er een MaatregelVerschuiving object om de instellingen daarvoor op te geven.

Note

Let op! In principe optimaliseert het model een kostenfunctie. Vandaar dat 'kosten' groter zijn dan nul, en besparingen kleiner dan nul.

Tip

Voor alle factoren is het mogelijk om een tuple op te geven van twee getallen zoals (3.0, 1.0) waarbij het eerste getal de factor geeft het met een jaar naar voren schuiven van een maatregel en het tweede de factor die van toepassing is voor een jaar uitstel.

Mag naar voren schuiven zonder kosten? Dan je ook de gratis_naar_voren toggle aanzetten.

MaatregelVerschuiving: Vaste factor

De meest basale instelling is de vaste_factor. Die zorgt ervoor dat een maatregel verschuiven een vaste last met zich meebrengt. Dat wil zeggen, een jaar verschuiven van 'een' maatregel kost altijd dit bedrag. Verschuift een maatregel met twee jaar? Dan wordt tweemaal de vaste_factor in rekening gebracht.

Het is mogelijk om dat bedrag op 0 te zetten, dan staat de vaste factor in principe 'uit'.

MaatregelVerschuiving: kosten per jaar / frequentie

Omdat niet alle maatregelen even vaak terugkomen en ook zeker niet hetzelfde kostenkaartje met zich meebrengen zijn nog twee extra velden toegevoegd aan de MaatregelVerschuiving instellingen:

kosten_per_jaar_factor: Vanuit POEMA is de kostenraming en herhalingsperiode van een maatregel geïmporteerd. Daarmee wordt een kostenbedrag per jaar uitgerekend in de tool. Het getal wat je voor deze parameter opgeeft wordt gebruikt om de verschuivingskosten als volgt uit te rekenen:

\[ \mathrm{kosten} = \frac{\Delta_\mathrm{t.o.v.\ advies} \times \mathrm{kosten\ per\ jaar\ factor} \times \mathrm{raming\ incl}}{\mathrm{periode}} \]

Voor de frequentie_factor geldt een zelfde formule, maar met de maatregelkosten buiten beschouwing. Maatregelen met een hogere frequentie (kortere periode) komen namelijk sneller in elkaars vaarwater te zitten als ze worden verschoven. Dit is onwenselijk omdat je dan onderdelen vaker te vroeg of te laat gaat vervangen. De kostenbijdrage met deze factor kan dan worden uitgedrukt als:

\[ \mathrm{kosten} = \frac{\Delta_\mathrm{t.o.v.\ advies} \times \mathrm{frequentie\ factor}}{\mathrm{periode}} \]

Note

\[ \mathrm{frequentie} = \frac{1}{\mathrm{periode}} \]

MaatregelVerschuiving: Standaard op 0

In beginsel geven deze verschuivingskosten een intuïtief mechanisme mee aan de tool. Het verschuiven van een maatregel ten opzichte van het advies plan jaar neemt 'kleine' kosten met zich mee, die werden afgewogen tegen besparingen vanwege eventueel schaalvoordeel of slimme combinaties van maatregelen.

Later in de ontwikkeling van de bundelingstool zijn deze factoren standaard op 0 komen te staan, omdat verschuiven binnen de gestelde windows in de tijd niet als problematisch wordt gezien.

Dat wil niet zeggen dat ze niet hun plek verdienen! Er is nog meer onderzoek nodig wat een goede balans geeft tussen het (mogen) verschuiven van maatregel en het op de goede manier afwegen van de voor- en nadelen daarvan.

Gevorderd: Aangepaste waarden voor specifieke maatregelen

Voor een "volledig eigengereide" beloning per jaar verschuiving is een specifiek veld toegevoegd aan het MaatregelVerschuiving object waar je een dictionary kunt opnemen met als "keys" de unieke ID's van maatregelen en als values een specifieke waarde voor het verschuiven van één jaar.

# rws_project = RwsProject(...)

specifiek = dict()
for gmr in rws_project.planning:
    if gmr.periode < 5:
        specifiek[gmr.uuid] = 10

verschuiving=MaatregelVerschuiving(
    ...,
    specifiek=specifiek
)

Note

Wanneer een ID maatregel voorkomt in het specifieke dictionary wordt die waarde aangenomen. Als dat niet het geval is wordt naar de overige instellingen gekeken.

MaatregelSynchronisatie: Instellingen voor het samenvallen van maatregelen

Het doel van de bundelingstool is het slim combineren van maatregelen. In het MaatregelSynchronisatie object kunnen diverse contributies voor de optimalisatiescore worden ingesteld.

MaatregelSynchronisatie: Jaar samenvallen

De tegenhanger van de vaste_factor bij het verschuiven is de jaar_samenvallen bij de synchronisatie. Hier wordt gekeken hoeveel tijdssegmenten twee taken samenvallen op basis van hun taakduur en gepland uitvoeringsjaar. In de huidige resolutie van jaren is dit eigenlijk altijd één jaar. De score wordt per tijdssegment berekend op basis van hoeveel maatregelen er in één tijdssegment (== standaard 1 jaar) op één beheerobject (sluiskolk) staan ingepland:

\[ \mathrm{kosten} = \mathrm{jaar\ samenvallen} \times (N_\mathrm{maatregelen\ in\ segment\ op\ object} - 1) \]

Wat uiteraard voor alle objecten en tijdsegmenten in de analyse gesommeerd wordt.

Info

De laatste term geeft aan hoeveel maatregelen er "extra" staan ingepland bovenop het basis-geval van één maatregel in zijn eigen segment.

Tip

Beloningen dienen opgegeven te worden als een negatief getal (besparing op kosten).

MaatregelSynchronisatie: Gedrag forceren

We kunnen twee dingen echt hard afdwingen wat de synchronisatie betreft, het gelijk starten van maatregelen en het verbieden van maatregelen met dezelfde omschrijving in hetzelfde tijdslot.

  • forceer_gelijk_starten: Op dit moment duren alle maatregelen standaard 1 jaar en dus ook één tijdssegment in de optimalisatie. Met ook één tijdssegment per jaar vallen maatregelen daarom eigenlijk altijd 100% samen. Met meer detailinformatie met betrekking tot de tijdsduur van maatregelen zou dit niet het geval hoeven zijn. Stel een maatregel duurt 2 jaar, dan zou deze instelling ervoor zorgen dat eventuele gegroepeerde maatregelen hetzelfde startmoment moeten hebben. Staat standaard uit omdat dit met de huidige resolutie niet hoeft te worden afgedwongen.

  • verbied_duplicatie: Het verbieden van maatregelen met dezelfde omschrijving kan helpen voorkomen dat maatregelen met een (te) korte herhalingsperiode ten opzichte van hun planningsvrijheid in ieder geval niet in hetzelfde jaar worden geprogrammeerd. Staat standaard aan.