PlanWise Tutorial

From Heureka Wiki
Jump to: navigation, search

(Available only in Swedish)

Om PlanVis

PlanVis är ett datorprogram för att göra konsekvensanalyser och upprätta åtgärdsplaner inom skogsbruket. Analyser kan göras på heltäckande data (alla bestånd inom ett skogsinnehav) eller på ett urval (s.k. stickprovsavdelningar). Tidshorisonten kan vara alltifrån några enstaka år vid taktisk planering till mer än 100 år för avverkningsberäkningar. I PlanVis integreras indata, generering av alternativa aktiviteter, optimering och resultatredovisning. Det senare görs i form av tabeller, diagram och kartor. Vill man ha ut ytterligare resultat än de som kan tas fram direkt i PlanVis kan man göra detta utplock ur databasen. Med generering av alternativa aktiviteter menas att PlanVis kan generera ett antal olika skötselprogram för varje bestånd inom ett valt område. Ett skötselprogram är en sekvens av åtgärder, utfall och tillstånd över tiden. Som användare kan man dela in skogen i olika grupper, och skapa olika skötselinstruktioner för dessa.

Innan du fortsätter, läs användarmanualen som finns på sidan User's guide to PlanWise.

Upplägg av övning

Första delen av övningen är en guide där du steg för steg får gå igenom grundläggande moment som installera program, skapa projekt, inspektera ingående tillstånd, skapa skogsdomäner, lära dig lite om att göra avancerade inställningar genom kontrollkategorier, skapa skötselinstruktioner (d.v.s. skötselkategorier), skapa skötselprogram, lösa optimeringsproblem samt inspektera resultat.

Andra delen av övningen är problembaserad där du får uppgifter du själv ska lösa.

Installera PlanVis

Installationen ska redan vara gjord på de datorer vi här använder. Annars är det bara att följa instruktionen på sidan PlanWise.

Skapa ett nytt projekt

Se även Arbeta med projekt. Se http://heurekaslu.org/help/index.html?skapa_nytt_projekt.htm


Beräkna ingående tillstånd och visa översikt

En översiktlig sammanställning erhålles både i tabell-/diagramform och som karta.

  1. Välj fliken "Analysis Area"-fönstret längst till höger. Välj här "Landscape8" (eller namnet på det område/skogsinnehav som ska analyseras).
  2. I huvudfönstret finns fliken "Ingående tillstånd (Initial State)". Under den finns "Details", "Forest Data Overview", och "Map". Klicka på knappen som hete "Calculate Initial State"...
  3. I fliken "Forest Data Overview" finns ett urval tillståndsvariabler, såsom medelvolym och medelålder. Denna del ska så småningom byggas ut med fler diagram och tabeller. Tills vidare, om det du söker inte finns med får du kopiera data från "Details" och göra egna diagram i t ex Excel.

Visa ingående tillstånd i karta

Här får man prova på kartverktyget, välj menyn "View" och därunder "Map Page". I rutan "Result:" må man välja "Current State", figur 3 (1), om ingenting visas så klicka på "Fit map to window", figur 3 (2).

Figur 3

I fönstret "Map Properties" kan man välja en variabel att göra en temakarta för. Exempelvis för beståndens förrådsuppgifter;

  • Expandera (klicka på +) "Forest Data"...

högerklicka på "Volume" och välj "Add Iterms Automatically". Klicka på färgerna och välj förslagsvis samma kulör men olika nyanser (för min- resp. max-värde). Markera "Width of items in gradient" och värdet "20". Detta ger en klassindelning med 20 m3sk/ha-intervall.

  • Sedan högerklickar man på "Volume" igen och väljer "Show in Map"

Bland kartverktygen finns en rullgardin till vänster om "Opacity" där man kan välja att visa en bakgrund, t.ex. ett ortofoto eller en vägkarta, figur 3 (3). Vad som finns tillgängligt för aktuellt analysområde beror vilka bakgrundsbilder som i PlanStart importerades till databasen.

  • För kartan finns också ett selekteringsverktyg, figur 3 (4)

Med det kan man välja en åtgärdsenhet och då visas i fönstret "Treatment Unit Properties" ett antal uppgifter för den valda enheten.

Skapa domäner och skötselgrupper

Toppnivån i ett projekt är analysområdet ("Analysis Area") som innehåller alla behandlingsenheter ("Treatment Units") som ska analyseras. Nästa nivå utgörs av skogsdomänerna ("Forest Domains"). En skogsdomän är en grupp av behandlingsenheter (bestånd) som uppfyller ett eller flera villkor. Villkoren ställs utifrån enheternas ingående tillstånd. Användaren anger villkoren själv och skapar därmed sina egna skogsdomäner. Man kan spara definitionen för skogsdomäner som en mall (i form av en fil på hårddisken). Denna mall kan delas med andra användare. Domäntillhörigheten är statisk genom föreliggande analyser (ett bestånd kan alltså inte t.ex. "växa in" i en annan domän än den initiala under pågående planperiod).

I början av en analys tilldelas varje behandlingsenhet en (och endast en) skogsdomän. Domänerna ställs upp i prioritetsordning och utvärderas därefter, så att den domän som står överst utvärderas först. Man kan enkelt ändra i ordningen. Om enheten inte tillhör den första domänen kontrolleras nästa domän, osv. Det finns alltså inga problem med att domäner faktiskt kan överlappa varandra. Den sista domänen är en "restdomän". Denna har inga villkor utan inkluderar alla enheter som inte hamnat i annan domän. Det finns alltså heller inga problem med att ställda villkor "glappar".

För varje skogsdomän kan man koppla särskilda skötseldirektiv genom att redigera och skapa nya kontrollkategorier ("Control Categories"). Vi kallar dessa ibland skötselkategorier. En kontrollkategori utgörs av att antal kontrolltabeller. Genom dessa styr man, bland annat, vilka åtgärder som ska simuleras och hur de ska utföras. Genom att skapa en eller flera kontrollkategorier för varje skogsdomän, kan man differentiera skötseln över de olika skogsdomänerna. Genom en kontrolltabell av typen "Treatment Program Generator" styr man vilka åtgärder som ska simuleras och till viss del tidpunkter för dessa. Genom en kontrolltabell av typen "Treatment Model" styr man hur åtgärderna ska simuleras (utföras).

För att skapa skogsdomäner används verktyget "Forest Domain Builder", figur 4 (1). Exempelvis kan man skapa en domän som heter "Äldre skiktad granskog" och ange villkoren som gäller för att en åtgärdsenhet ska tillhöra denna. I exemplet nedan skapar vi domäner utifrån en befintlig s.k. målklassning som fanns angivet i beståndsregistret.

Definiera skogsdomäner

  • Under "View" aktiveras "Forest Domain Builder"
  • Högerklicka på "Other" och välj "Add Forest Domain" varefter dialogrutan "Edit Conditions" visas
  • Under "Property" väljs "Select property..."

Expandera "StandObject Data" och markera "ManagementClass" (avser i detta fallet Skogsstyrelsens målklassning i s.k. Gröna skogsbruksplaner).

  • Ange att "ManagementClass Equal" (under "Operator") NO (under "Expression")

NO står för Naturvårdsinriktning, lämnas Orört (till skillnad från NS, Naturvårdsinriktning som kräver någon form av Skötsel).

  • Döp om "Forest Domain 1" till t.ex. "NO-skog"

Nu innehåller inte alla beståndsregister målklasser. Då får man istället utgå ifrån befintliga beståndsparametervärden. För att skapa ett skogsdomän med "Äldre skiktad granskog" skulle följande kriterier kunna gälla:

Figur 3b

Vill du kolla hur många bestånd som hamnade i det skapade skogsdomänet högerklickar du i domänet och väljer "Evaluate forest domains" (syns i fönstret "Properties") alt. "View treatmentunit assignment...". Hamnade inga här får du kanske gå tillbaka och ändra kriterierna, "Edit conditions..." (i ovanstående exempel kanske sänka ålderskravet till t.ex. större än 70 år).

I andra lägen kanske man vill skapa ett domän för specifika bestånd (som kanske identifierats i GISet som "bestånd angränsande till sjö med häckande storlom", "bestånd med förvaltarens favoritpass", osv.), dessa id-nummer listas då, semi-kolonseparerade, "in" "TreatmentUnit.Description". Alla siffror, inkl. nollor, och mellanslag må med, vilket är lite bökigt. Alldeles strax tillkommer sådan funktionalitet att man i kartan kan markera (ett eller) flera bestånd och direkt hänföra dessa till ett domän.

Minns du att det vid importen av beståndsregistret fanns ett antal kolumner på slutet av .csv-filen som hette "UserDefinedVariable"? Om man vill ta hänsyn till genomförda GIS-analyser, t.ex. bestånd helt eller delvis inom buffertzon till område med störningskänsliga arter, bör man alltså se till att sådana uppgifter medföljer redan vid dataimport. T.ex. skulle en av kolumnerna kunna bestå av värden 0 - 100%, beroende på hur stor del av beståndets yta som är inom nämnda buffertzon. Utifrån dessa uppgifter skulle sedan olika skogsdomäner, med olika skötselformer, kunna tillämpas.

Definiera skötselkategorier (kontrollkategorier)

Välj fliken "Control Categories" (under "Analysis Area"), figur 4 (2). Om fönstret inte syns aktiverar du det via menyn "View".

Inspektera och ändra befintlig kontrollkategori

  • Klicka på kategorin "DefaultTreatmentCategory"

Vi låter denna motsvara traditionellt trakthyggesbruk.

  • Längre ner visas fönstret "Properties", figur 4 (3)

Om inte så aktiverar du det via menyn "View". Du kan flytta och förstora/förminska fönster på arbetsytan.

  • Varje "ControlCategory" har ett antal kontrolltabeller

Ändra i dessa för "DefaultTreatmentCategory", figur 4 (4). Du hittar lite mer information på sidan Control Tables etc. Du kan dessutom se vad alla parametrarna betyder genom att markera dem och läsa hjälptexten längst ned i fönstret "Properties" (hovra med pekaren ifall inte all text syns).

Figur 4
  • Forts:
    • Välj kontrolltabellen "Treatment Program Generator" (under "Control Categories"), figur 4 (4)
    • Under "ManagementSystem" (i fönstret "Properties") väljs "EvenAged"
    • Sätt "MaxAlternatives" till 100
    • "CCDelayMax" är satt till 4 vilket betyder att slutavverkningstidpunkten får skjutas upp max 4 perioder (dvs. 20 år) jämfört med lägsta tillåtna slutavverkningsålder (LSÅ enligt Skogsvårdslagen). Du kan ändra till ett annat värde om du vill.
    • Välj sedan kontrolltabellen "Treatment Model". Under "4. Thinning - model" och "4.1 Thinning – settings" kan du ändra t.ex:
      • ThinningModelType = Hugin
      • HarvestStriproads = True
      • MinDiameterThinning = 0
      • MaxThinningIntensity = 40
      • VaryThinningIntensity = True. Glöm inte att markera parametrar och läsa hjälptexterna.
    • Välj slutligen tabellen "Production Model" och titta igenom inställningsmöjligheterna. Inget behövs här ändras emedan du alltid kan läsa hjälptexterna.

Lägg till ny kontrollkategori

  • Högerklicka i någon tom del i fönstret "Control Categories" och välj "Add Treatment Category"
  • Ändra namn på den nyskapade "TreatmentCategory2" till "Fri utveckling"
  • Högerklicka på "Fri utveckling" (i fönstret "Control Categories") och välj "Edit ControlTables"
  • Klicka på "Add..."

Håll ner Ctrl-tangenten och markera p.s.s. både "Production Model" och "Treatment Program Generator". Klicka på "Ok".

  • Gör följande inställningar för denna kategori:
    • Sätt "ManagementSystem" till "FreeDevelopment"
    • Klicka på "Treatment Program Generator"
    • Sätt "MaxAlternatives" till 1 (i fönstret "Properties")

Valet av "ManagementSystem" avgör vilken huvudtyp av skogsbrukssätt som ska simuleras. Man man välja mellan "EvenAged" (dvs. trakthyggesbruk), "Continuous" (hyggesfritt, t.ex. blädning) och "FreeDevelopment" (fri utveckling, inga åtgärder simuleras).

Koppla kontrollkategori till skogsdomän

  • Högerklicka på domänen "NO-skog"
  • Välj "Add control category connections"
  • Välj "Fri utveckling" och klicka på "Ok"
  • Ta bort kategorin "DefaultTreatmentCategory" från denna domän genom att markera och trycka "Delete"

Nu har vi angett att all skogsmark ska skötas med trakthyggesbruk, utom den NO-klassade skogen som ska lämnas orörd (till fri utveckling).

Beräkna prislista

  • Under menyn "Action" väljs "Add Pricelist..."
  • Välj "Add Default pricelist"

I nästa dialog kan du se vilka apteringsgränser, priser, etc. som gäller. Längst ner står det "Prices" och "Timber" och bredvid "Pine;Spruce". Klicka på "..." så öppnas en prislista (som är viktad, se nedan). Klicka slutligen på "Finish" och vänta tills prislistan har räknats fram. Vad som görs är att trädpriser beräknas (i kr/m3fub) för en mängd kombinationer av trädslag, diametrar och höjder. Värdet på ett träd beräknas sedan under en prognos genom att multiplicera det beräknade priset med trädvolymen. Varje träd får således ett slags genomsnittspris baserat på en prislista som har viktats utifrån ett genomsnittligt utfall av olika kvaliteter. Vi tar alltså inte hänsyn till kvaliteten på varje träd (vi har inte tillgång till den variabeln).

Har du intresse av att ändra kalkylräntan kan det göras här, i rutan bredvid "DiscountingRate" anges önskat värde i procent.

Nu är vi klara att skapa alternativa skötselprogram för varje bestånd!

Skapa alternativa skötselprogram för varje bestånd

  • Under menyn "Action" väljs "Generate Treatment Programs..."

Följande dialog visar de resultat som kommer att sparas. Du kan låta alla vara markerade.

  • (Vill tyvärr fortfarande krångla, välj följande, för fortsatta analyser nödvändiga resultat;
    • "Alternative summary"
    • "Data per Species"
    • "Financial Value"
    • "Forest Data"
    • "Forest Domain"
    • "Treatments".) Klicka på "Ok" och vänta (det tar några minuter). Processen kan följas längst ner i "Output Window".

Granska simuleringsresultaten

  • Under fliken "Results" (långt till höger) visas alla körningar

Högerklicka på den du just gjort och välj "View Treatment Programs".

  • Tabellen visar åtgärdskoder för valt bestånd (via blädder-pilarna högt upp) under en sekvens av tidsperioder (5-åriga)

Varje rad representerar ett alternativt skötselprogram för föreliggande bestånd.

  • Under menyn "Action" väljs "View Alternative Details..."

Välj ett bestånd och ett alternativ som du vill titta närmare på under "Select alternative" och vilka data du vill granska under "Select results".

Spara projektet då och då.

Beakta särskilt skötselprogrammen för bestånd i de nya skogsdomänerna, t.ex. att inga åtgärder görs vid fri utveckling, att "överhållning" funkat (såtillvida att ev. slutavverkning infaller först vid en relativt hög beståndsålder) eller att det vid "gransanerande gallringar" främst sker ett uttag av granvolymer (före lövvolymer).

Optimering

Handledning för optimeringsverktyget finner du här.

Nästa steg består i att med hjälp av optimering välja ut ett skötselprogramalternativ (av de många vi nyss skapade) för varje åtgärdsenhet.

  • Under menyn "Optimization" väljs "Open Optimization"
  • Välj "Model8b.Hops"

Ev. må du söka rätt på den själv, under den delade mappen "SH0085". Här finns nu en ny version, "Model9c.Hops" som är mycket bättre (när den fungerar). För dig som kan din linjärprogrammering och även har kört Lingo eller AIMMS så kanske vissa saker känns bekanta? Man bygger upp sin optimeringsmodell genom att definiera "Sets", "Parameters", "Variables" och "Constraints".

Förvånad att LP används i Heureka? Som namnet antyder trodde man förvisso först att någon heuristisk metod skulle nyttjas i optimeringarna emedan LP-utvecklingen liksom kommit ikapp och nu är nästan jämsides med utvecklingen av Heureka-applikationerna (!) och häri passar riktigt bra.

  • Högerklicka på "Model8b" i fönstret "Model Optimization Builder" och välj "Solve Model"

Klicka på "Ok" och vänta några minuter.

  • Gör en temakarta för variabeln "Treatments" för att se vilka åtgärder som görs i de olika bestånden i olika perioder

Tag först fram fliken "Map" (ev. via menyn "View") och välj "Strategic Optimization" i rutan bredvid "Result:" (ev. må du först trycka på "Refresh"-knappen). I fönstret "Map Properties" expanderar du "Treatments" och väljer "Treatment". Högerklicka och välj "Add Items Automatically" så får du upp en dialogruta. Ta bort åtgärder som du inte vill visa (markera och klicka på "Remove"). Spara bara t.ex. "Thin(ning)" och "FinalFelling" och ändra färgerna på dessa. Högerklicka igen på "Treatment" och välj "Show in Map". Högt upp i kartfönstret finns pilar för att bläddra mellan planperioderna.

Slutavverkas ett och samma bestånd i två på varandra följande tidsperioder? Det kan verka så emedan det eg. är fråga om delavverkning (t.ex. 75% (av beståndets yta) avverkas först, 25% under nästa 5-årsperiod). Sådant kan bli aktuellt om man har relativt få men stora bestånd (och kanske i optimeringen inkluderat ett villkor som begränsar hyggesstorleken, "_limitFinalFelling"). Ett sätt att undvika detta är att för beslutsvariabeln "_x" ändra "RangeType" till binär, alltså accepteras endast värdena 0 eller 1, optimeringen blir då emellertid svårare och kan ta rysligt lång tid.

Formulering av optimeringsproblem

I Heureka har vi gjort ett verktyg för att modellera och lösa LP- och MIP-problem. Som modelleringsspråk tillämpas ZIMPL. ZIMPLs User’s Guide finns på nätet (http://www.zib.de/koch/zimpl/download/zimpl.pdf) men även sparat på datorn, under "SH0085", läs kapitel 4.2 till och med 4.5. Nedan följer sedan ett antal syntax-exempel från PlanVis.

Kontovariabel som summerar avverkad volym i varje tidsperiod:

FORALL <p> IN _periods DO
        SUM<i,j,r> IN _treatmentunits * _alternatives * _rowno :
        _volumeHarv[i,j,p,r] * _area[i] * _x[i,j] == _volHarvTot[p];

Definitionen skrivs in direkt i variabelns definitionsfönster, men är i egentlig mening en restriktion. Restriktionen motsvarar följande matematiska uttryck (restriktion) i en LP-modell:

PlanVis Tut Fig5 formula.png

där:

I = mängden (set) av behandlingsenheter ("Treatment Units")

J = mängden av (index) för tillgängliga skötselprogram

R = mängden åtgärder (åtgärdsnummer) i en och samma period

areai = areal för behandlingsenhet i (faktisk eller "representativ")

volumeHarvijpr = avverkad volym i enhet i under period p, givet att skötselprogram j tillämpas, från åtgärd r

volHarvTotp = summa avverkad volym under period p

xij = beslutsvariabel (binär) = 1 om skötselprogram j tillämpas för enhet i, annars 0

Kontovariabel som summerar volym som slutavverkas i varje tidsperiod:

FORALL <p> IN _periods DO
        SUM<i,j,r> IN _treatmentunits * _alternatives * _rowno with _treatment[i,j,p,r]==8:
          _volumeHarv[i,j,p,r] * _area[i] * _x[i,j] == _volHarvFinalFelledTot[p];

Skillnaden mot föregående uttryck är att efter "rowno" följer ett villkor att summering bara ska göras för slutavverkningsåtgärder (som har koden 8). Notera användningen av dubbla likhetstecken. För att visa definitionen av en definierad kontovariabel dubbelklickar du på den.

Kontovariabel för arealen slutavverkning i varje tidsperiod:

Denna variabel är nästan identisk med den föregående, vi tar bara bort parametern "_volumeHarv(i,j,p,r)" från uttrycket.

FORALL <p> IN _periods DO
        SUM<i,j,r> IN _treatmentunits * _alternatives * _rowno with _treatment[i,j,p,r]==8:
        _area[i] * _x[i,j] == _areaFinalFelledTot[p];

"8" i ovanstående två uttryck är alltså det numeriska värde som motsvarar slutavverkning för parametern "_treatment". Man kan kontrollera dylikt genom att högerklicka på parametern och välja "View definition" (testa detta även för "_forestDomain" och "_trmtCategory", särskilt bra om man skapat flera nya skogsdomäner med viss sorts skötsel definierat i kontrollkategorierna).

Restriktion som begränsar hur stor areal som får slutavverkas i varje tidsperiod:

FORALL <p> IN _periods DO
 _areaFinalFelledTot[p] <= 20;

Vi använder alltså den kontovariabel för slutavverkningsareal som vi skapade ovan, och lägger in restriktionen (eg. restriktionerna) att den slutavverkade arealen får vara högst 20 hektar i en och samma period. Om du vill inaktivera en restriktion utan att ta bort så högerklicka och välj "Exclude".

Lägga till ny parameter

"Sets" och "Parameters" utgör indata till optimeringsmodellen. En parameter får sitt värde antingen genom att koppla den till resultatdata som har beräknats av skötselprogramgeneratorn eller genom att ge den en matematisk definition. Blanda inte ihop "variabler" som beräknas av skötselprogramgeneratorn med "beslutsvariabler" i optimeringsmodellen. För modellen är alla variabler som beräknas utanför den konstanter (dvs. element i ett "Set" eller i en "Parameter").

Så här gör man för att skapa en ny parameter och koppla den till resultatdata:

  • Högerklicka på "Parameters" och välj "Add new parameter"

Har du gått vilse bland alla fönster så under menyn "View" väljs "Model Optimization Builder".

  • Låt "Heureka result variable" vara valt och klicka på "Next"

Vi ska alltså i detta läge inte skriva en ny formel, utan koppla parametern direkt till en kolumn i databasen där skötselprogramalternativen har sparats.

  • Välj t.ex. "TreatmentControlCategory" under noden "Forest Domain"
  • Byt parameternamnet till något bättre.

Den nya hamnar längst ner bland alla "Parameters". Ett bättre namn är ett som indikerar vad det handlar om, i rutan "Properties" och bredvid "Description" kan en ännu fylligare förklaring skrivas in.

Notera att systemet själv håller reda på indexeringen. I detta fall har vi en skötselkategori för varje behandlingsenhet, skötselprogramalternativ och period. Att vi har med period beror på att skötselkategorin kan vara olika före och efter slutavverkning (vi går inte in på detta mer i denna övning).

Lägga till ny restriktion

  • Högerklicka på "Constraints" och välj "Add new constraint"
  • Klicka på den restriktion som har skapats.

I rutan "Properties" för restriktionen väljer du "Click to add index", lägger till och väljer "_Periods[p]" för att skapa en restriktion för varje tidsperiod.

Exempelfiler

Dessa optimeringsfiler kan du ladda ner och öppna via meny "Optimization" > "Open optimization":

Nya och andra komponenter kommer att göras tillgängliga på denna ftp-server (ftp://salix.slu.se/download/Heureka/), t.ex. skript ("SQL queries") att använda (som mall - skriv om för att få ut det du vill ha) för rapporter från resultat-databasen. Detta avser både när man vill närmre studera initialtillståndet men kanske främst planen - simulerings- och optimeringsresultatet.

Förbättrad funktionalitet under "View" > "Optimization Result Viewer" och möjligheten att här välja en simulering/optimering och sedan skapa egna diagram (under "Diagrams" > "User defined") för att beakta resultaten gör ev. SQL queries överflödiga.

Tillämpade övningar

Kostnad för naturvårdshänsyn

Skapa skogsdomäner för alla målklasserna:

NO = naturvårdsmål där skogen lämnas orörd

NS = naturvårdsmål med naturvårdande skötsel

PF = produktionsmål med förstärkt hänsyn (till natur- och kulturvärden)

PG = produktionsmål med generell hänsyn (till natur- och kulturvärden)

Skapa sedan lämpliga skötselkategorier för dessa och kör om "Generate Treatment Programs". Tag också fram ett scenario där ingen hänsyn tas. Tag reda på vad kostnaden (i form av minskat nuvärde) blir för att tillämpa målklassningen, jämfört med ett uteslutande produktionsinriktat skogsbruk.

Denna övning kan nog upplevas konstlad för de åtta bestånden i "Landscape8", kanske inte alla olika målklasser finns representerade i beståndsregistret etc. Mer realistiskt blir det med ett större skogsinnehav, t.ex. Östad som vi kanske istället kan använda här.

Eget problem

Lös något problem som du finner intressant, t.ex. maximera rekreationsindex eller se vad som händer med högre (eller lägre) virkespriser.

Projekt Östad med Heureka

Själva övningen finns på kursens hemsida (http://slunik.slu.se/kursfiler/SH0085/40032.0809/Heureka_Ovningsinstruktion.pdf).

För att lösa uppgifterna häri kommer man långt med skogsdomänerna och inställningar i tillhörande kontrolltabeller. I en del fall må man dock in i optimeringsmodellen och definiera nya variabler och restriktioner (befintliga parametrar kan nog räcka). Att skriva egen syntax med Heurekas modelleringsspråk är det roligaste som finns. När det går bra (dvs. när syntaxen accepteras, modellen kan kompileras och lösas och man erhåller relevanta resultat). När det går dåligt är det förstås inte fullt lika roligt. Här lite tips:

  • Du kommer kanske misslyckas några gånger,

se därför till att göra försöken på ett begränsat material; stratadatat (dvs. de 230 stickprovsavdelningarna) och 10 perioder så behöver man inte vänta länge på ev. felmeddelande.

  • Snegla på (och kopiera) befintliga, liknande variabler

och ändra i syntaxen så det stämmer med dina syften.

  • För jämnhetsvariabeln s (eller vad du nu valt att kalla den) är variabeln _volHarvTot troligen av vikt.

Tänk dock här på indexeringen; t.ex. är perioden p-1 odefinierad när man är i den första perioden.

  • Vilka värden kan variabeln s förväntas anta?

Om negativa värden kan förväntas så må det vara definierat i "Properties" > "RangeType" (förslagsvis "All").

  • Börja med någonting enkelt, t.ex. att virkesförrådet efter avverkning vid sista perioden inte ska understiga 140 m3sk/ha;
    • Skapa en variabel som är kvoten av totalvolymen (i varje period, efter att periodens åtgärder/avverkningar genomförts) och analysområdets totala skogsmarksareal
    • Högerklicka på "Variables" och välj "Add new variable"
    • Ändra namnet till t.ex. "_volMean"
    • Lägg till perioder som index ("Properties" > "Sets")
    • Skriv den ekvation som tilldelar ett värde på _volMean[p], typ;
FORALL <p> IN _periods DO
 (_volTot[p] - _volHarvTot[p]) / 3567 == _volMean[p];

3567 ha är alltså den totala arealen (t.ex. via "Action" > "Forest Data Overview..."). På detta sätt kan man i "Output Window" se vad virkesförrådet är i samtliga perioder (inte bara i sista). Använd sen den nya variabeln i en restriktion, gör på motsvarande sätt för "Constraints" och skriv typ;

FORALL <p> IN _periods WITH p >= 9 DO
 _volMean[p] >= 140;

Här säkerställs alltså att förrådet inte understiger 140 m3sk/ha i sista perioden (lätt att justera ifall man vill att restriktionen ska gälla i flera perioder).

För variabeln (och restriktionen och slutligen målfunktionen) s blir det förstås lite knöligare. Man kan förmodligen göra på många olika sätt men här är några, mer eller mindre, pedagogiska exempel:

  • Se till att skapa en ny variabel typ _totNPV och här kopiera in målfunktionen från _objFunc (så denna kan definieras som något annat än för nuvärdesmaximering, t.ex. "jämnhetsmaximering" eller åtminstone "minimering av avtagande avverkade volymer"). På köpet får du då alltid en utskrift av analysområdets totala nuvärde (i SEK, i "Output Window"), även när målfunktionen ges en annan definition.
  • Det går alldeles utmärkt att definiera en variabel bara genom att ge den ett namn (och ev. i "Properties", under "Constraints" se till att "Range Type" är "All", om variabeln kan anta både positiva och negativa värden). Syntaxen, det matematiska uttrycket, som tilldelar variabeln sitt värde kan istället definieras i en restriktion. Vi börjar dock med ett exempel med en variabel med syntax, _harvDiff:
FORALL <p> IN _periods WITH p >= 1 DO
 _volHarvTot[p-1] - _volHarvTot[p] == _harvDiff[p] ;

Du ser väl vad den beräknar? Lite opedagogiskt, men av stor vikt i fortsatt joxande, erhåller här en stigande avverkningsnivå ett negativt värde och vice versa, komihåg detta. Sen definierar vi en variabel utan syntax, _harvDiffMax. Den erhåller istället sitt värde via den syntax som anges i restriktionen _minDiff:

FORALL <p> IN _periods WITH p >= 1 DO
 _harvDiff[p] <= _harvDiffMax ;

Nu blev det kanske inte lika lätt att se vad som beräknas..? Så här kan man tänka; restriktionen - att detta villkor alltid uppfylls (här i alla perioder utom i den första - period 0) är endast fallet om _harvDiffMax är det största värdet av alla förekommande värden på _harvDiff. Och restriktioner må ju uppfyllas om optimeringsproblemet ska erhålla en lösning. Kolla i ovanstående delar om du glömt vad _harvDiff var för något (och vad som avses med "störst" i sammanhanget).

Sen på tur står tillskapandet av två variabler, Z1 respektive Z2, som ska ingå i en målfunktion med två, sinsemellan viktade mål enligt modellen: 0.x * Z1 - (1 - 0.x) * Z2 (som ska maximeras eller minimeras? och varför är det ett minustecken mellan de två delmålen? borde de inte adderas?). De två målen är här lämpligen "maximerat nuvärde" respektive "jämnhet". Innan de två variablerna tillämpas i en och samma målfunktion må de relativiseras (endast kunna erhålla värden mellan 0 och 1) och samtidigt göras enhetslösa (de ska ju inte spela någon roll om de mäts i EURO, SEK, m3sk eller nånting annat) enligt modellen: Z1 = relNPV = (_totNPV - NPVmin) / (NPVmax - NPVmin). När du sedan ska definiera Z2 gör du på motsvarande sätt och är särdeles observant på + och -.

Ovanstående finns implementerat i Model9d.hops, redo att laddas ner från ftp-servern och laddas upp i PlanVis. Sen är det rekommendabelt att du fortsätter använda din egen modell (den modifierade Model9c) för att lösa ditt optimeringsproblem, men med möjlighet att jämföra (och ev. kopiera) definitioner och formuleringar som finns i 9d. Namngivningen av variabler och restriktioner skiljer sig säkert mycket åt, kanske även definitioner och beräkningssätt. Som en kommentar till ovanstående frågor tittar vi lite närmre på målfunktionen _objFunc:

0.5 *_NPVgoal - 0.5 * _harvDiffgoal ;

Under "Properties" > "ModelDirection" ser vi att denna funktion ska maximeras. Detta är uppenbart för nuvärdet men inte för den avtagande avverkningsnivån. Som vi tidigare definierat denna variabel så vill vi minimera sänkningen från en period till nästa (komihåg att det är ett positivt värde - en ökning erhåller ett negativt värde och utan begränsning uppåt (utan ett "komplett" jämnhetsvillkor) kan vi lugnt minimera en sådan målfunktion). Därför subtraherar vi de två viktade delmålen, tidigare i kursen adderade ni nog de två för då skulle båda maximeras (t.ex. nuvärde och "renbetesmarker"). För övrigt valde jag inte ovanstående 50/50-viktning som referensmodell, 25/75 blev istället så här tjusigt:

Figur 6

Visst förlorades en del i nuvärde (här, med 3% kalkylränta, 115 milj. SEK, i föregående fall 143 milj. SEK) men å andra sidan är nog kassaflödet ungefär detsamma vid de båda fallen. Totala uttagsmängden, summerat över hela planperioden: 1.21 milj. m3sk, var här något lägre än i föregående fall så kanske kan man säga allt en del av det "förlorade nuvärdet" finns kvar i skogen (som ett något större, kvarstående virkesförråd), medelförrådet vid planperiodens slut: 157 m3sk/ha. Jag skyller detta resonemang helt och hållet på Ola Lindgren (vars intressanta föreläsningsmaterial också finns på kurshemsidan; http://slunik.slu.se/kursfiler/SH0085/40032.0809/Ola_Lindgren_Del1_09.pdf samt http://slunik.slu.se/kursfiler/SH0085/40032.0809/Ola_Lindgren_Del3_09.pdf). Lägg märke till uppdelningen av volymen från slutavverkning och från gallring. Det är förvisso relativt stor skillnad mellan första och sista perioden map. andelen från gallring men utan kraftiga fluktuationer under planperioden (något som skogsindustrin säkert skulle ogillat). Vi låter detta vara en överkursuppgift (att försöka få jämnhet även map. sortiment; sågtimmer-massaved-skogsbränsle).

Känslighetsanalyser, stratadata

Olika uppgifter ska här lösas för respektive grupp. Samtliga grupper kan dock vänta med indelning i skogsdomäner, detta moment lämpar sig bättre vid heltäckande data. Använd istället kontrolltabeller för att generera skötselprogram i linje med er uppgift och/eller modifiera optimeringsmodellen. Man kanske vill begränsa gallringarna och kan då införa restriktionen _maxThinnProp:

FORALL <p> IN _periods DO
 _thinnVol[p] <= _volHarvTot[p] * 0.3 ;

Detta har förstås föregåtts av definering av variabeln _thinnVol[p] (som i varje period beräknar differensen mellan totala volymen som avverkats och volymen som avverkats i slutavverkning). Restriktionen begränsar gallringsandelen (av volymen) till max 30% i varje period. T.ex. för att undvika de plötsligt höga andelarna i de två sista perioderna, figur 6b. Vill man införa en lägstanivå, t.ex. minst 10% gallringsvolym i varje period, rekommenderas att detta görs i en egen restriktion (istället för att försöka få med båda gränsvärdena i en och samma). Observera att vår optimeringsmodell bygger på linjärprogrammering och alla modeller må vara linjära - "_volHarvTot" kan då inte vara nämnare i division med täljaren "_thinnVol" (på andra sidan <=) utan multipliceras upp (på båda sidor (o)likhetstecknet).

Om denna restriktion infördes med hänsyn till skogsindustrins önskemål om jämnhet över tiden med avseende på sortimentsutfall, ja då är ju ovanstående "gallringsandel" endast en approximation under antagande om stora mängder massaved vid gallringar (och små vid slutavverkningar). Om vi istället vill titta på andelen massaved så får vi börja med att lägga till denna parameter; högerklicka på "Parameters" och välj "Add new parameter...", ge den ett lämpligt namn (t.ex. _pulpVolume) och välj "Heureka result variable". Sen är det bara att söka rätt på denna, under noden "Financial Value" finns "PulpVolumeTotal" (observera att "Total" här avser alla trädslag), välj och klicka "Finish". Observera samtidigt att här finns mycket data att välja bland men endast de som valts att följa med vid skötselprogramsgenereringen kan vi använda i optimeringsmodellens variabler, restriktioner och målfunktioner. För att beräkna den mer relevanta massavedsandelen skapas en ny variabel, t.ex. _volHarvPulpTot:

FORALL <p> IN _periods DO
        SUM<i,j,r> IN _treatmentunits * _alternatives * _rowno WITH _altIncluded[i,j] >= 1:
        _pulpVolume[i,j,p,r] * _area[i] * _x[i,j] * 1.2 == _volHarvPulpTot[p];

Här summeras alltså avverkad volym massaved i varje period, gånger faktorn 1.2 då den är i m3fub och vi vill förmodligen jämföra med befintliga variabeln _volHarvTot (i m3sk, se denna schablon som en snabb problemlösning för att komma vidare - givetvis finns i systemet, ända ner på enskilda träd-nivån, alla förekommande sortiments volymer angivna i rätt enhet). Variabeln _altIncluded kollas vara "1" (så summeringen endast görs för de alternativa skötselprogrammen (med index j) som simulerats i resp. bestånd (med index i)). Man kan dock ana något fel i syntaxen (eller i hela tänket...), se tabell 1; i kolumnen "Gallringsandel" ser vi att restriktionen max 30% funkade och kapade gallringstopparna i de två sista perioderna (se även figur 6b) och dessutom fyllde luckan i period sju, bra, men visst ser värdena i kolumnen "Timmerandel" alltför låga ut? I perioder när mer än 90% av avverkade volymer kommer från slutavverkning borde väl timmerandelen vara avsevärt högre?

Tabell 1

Känslighetsanalyser, heltäckande data

För att undvika långa väntetider och överbelastning av systemet så analyseras endast Östads skifte ett ("Map ID = 1"). Dessutom minskar vi planperioden till 50 år. Då bör man erhålla ett initialtillstånd för 924 bestånd motsvarande 2332 ha skogsmark (= representativ areal) med bl.a. ett medelförråd = 167 m3sk/ha och en medelålder = 44.5 år. Skogen här avviker alltså avsevärt från den i stickprovsavdelningarna (stratadatat) varför en ny referenslösning nog bör tas fram, för att kunna jämföra med vid respektive grupps uppgifts resultat. Komihåg att välja er kalkylränta innan TPGn körs!

Dessutom verkar ett av bestånden ställa till med mycket oreda; välj bort nr. 1228 ur analysområdet (som då ska bestå av 923 bestånd motsvarande 2331 ha), en medelålders NO-skog med 0 m3sk/ha som, trots att den lämnas utan åtgärder till fri utveckling, lyckas föra in två till perioder och förlänga planeringshorisonten med tio år (och här då många gånger föra in odefinierade variabler och orimliga värden).

Granska referenslösningen innan ni går vidare (är en jämnhetsrestriktion berättigad? borde ett lägsta utgående förråd sättas? etc.) och välj lämplig optimeringsmodell.

Uppgifterna bör sedan kunna lösas främst med indelning av analysområdet i skogsdomäner. Varje domän tilldelas sedan specifika förutsättningar via kontrolltabellerna. Det är givetvis helt ok ifall man även vill införa nya restriktioner (eller ytterligare delmål i målfunktionen) i optimeringsmodellen. Vi har ju redan nu upptäckt en brist i TPG-kontrollkategorin "ManagementSystem" där "Continuous" inte ger upphov till något nuvärde (trots att en eller flera åtgärder av typen "Selective felling" gjorts i skötselprogrammet under planperioden. Enligt uppgift ska dock volymer och kassaflöden(?) från dessa åtgärder vara medräknade).

Övningen nämner momentet "zona in lämpliga områden" och det är kanske mest lämpligt att göra i ett GIS. GIS-delen i PlanVis är dock ännu inte fullt utbyggd. Iofs. kan du titta på analysområdet i ArcMap och nyttja dina GIT-kunskaper och kanske buffra runt sjöar och vattendrag eller beakta överlappande teman som älgpass och beståndsindelning. Vill vi ha med oss sådana uppgifter må de vara med redan vid dataimporten i PlanStart och det hinns tyvärr inte. Den GIS-zoning som hinns är isåfall att du noterar intressanta bestånd (deras ID-nummer) och låter dessa utgöra ett eget skogsdomän (tillvägagångssätt beskrivs ovan). Nu kan man lika bra zona in med hjälp av befintliga beståndsparametrar, enklast med målklasserna men heller inte särskilt krångligt med kombinationer av trädslag, ålder, etc. (tillvägagångssätt beskrivs ovan). Komihåg att kolla så tillräckligt många bestånd hamnade i tillskapat domän, så fortsatt särbehandling av dessa kan förväntas ha genomslag i resultaten!

Vill du i kartan se vilka bestånd som hamnade i vilka domäner väljer du under "Map Properties" > "Forest Domain" > "ForestDomain" med högerklick att först ta bort gammalt ("Remove all subitems") och sen lägga till nytt; "Add items automatically". Fortfarande bara det gamla? Se till att senaste körningen valts i rutan "Result:" (uppdatera först) och gör om.

Som uppgift valde jag att försöka ta fram en miljö- och rekreationsanpassad plan; höga naturvärden finns idag främst representerat på "Djurgården", halvön strax öster om Östads gård. Djurgården är samtidigt ett populärt strövområde, för Alingsåsare likväl som för Göteborgare. NO-bestånden lämnas orörda (för fri utveckling) inom hela analysområdet emedan deras skydd förstärks på Djurgården. Det förstärkta skyddet här avses även öka områdets rekreationsvärden och uppnås genom överhållning och "gransanerande" gallringar i särskilda bestånd. De särskilda bestånden ligger i anslutning till Djurgårdens NO-bestånd och/eller har, vid planperiodens början, relativt hög andel gran. Observera att detta bara är ett exempel på möjligheterna i PlanVis men med relativt litet genomslag i föreliggande planeringsresultat; endast 77 st. NO-bestånd sköts med "Fri utveckling" och endast 18 st. bestånd sköts "NV-anpassat". Detta exempel sänkte nuvärdet endast med 3.3% (till 58600 SEK/ha vid 4% kalkylränta). Figur 7 visar förekommande skogsdomäner på Djurgården.

Figur 7

Komihåg att kolla så skötselprogram genererats såsom du ville, särskilt för bestånden i dina nya skogsdomäner!