alpar@1
|
1 |
# Model I Forest Estate Modelling using GLPK/MathProg
|
alpar@1
|
2 |
# Reading and writing dbf files
|
alpar@1
|
3 |
|
alpar@1
|
4 |
# by Noli Sicad --- nsicad@gmail.com
|
alpar@1
|
5 |
# 18 December 2009
|
alpar@1
|
6 |
|
alpar@1
|
7 |
# Forest Management 4th Edition
|
alpar@1
|
8 |
# by Lawrence Davis, K. Norman Johnson, Pete Bettinger, Theodore Howard
|
alpar@1
|
9 |
# Chapter 11 - Daniel Pickett
|
alpar@1
|
10 |
# http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm
|
alpar@1
|
11 |
|
alpar@1
|
12 |
# Model I Formulation
|
alpar@1
|
13 |
|
alpar@1
|
14 |
/* Note: This is not the full LP model mentioned in the book.
|
alpar@1
|
15 |
Some of the constraints are deliberately omitted in this model for the purpose of clarity.
|
alpar@1
|
16 |
|
alpar@1
|
17 |
The features of MathProg in this example are:
|
alpar@1
|
18 |
* reading and writing dbf from regular dbf files,
|
alpar@1
|
19 |
* reading dbf file (database of shapefile (stands.shp)) (e.g. area parameter),
|
alpar@1
|
20 |
* using the area data in the constraints and
|
alpar@1
|
21 |
* writing dbf file from result of LP model.
|
alpar@1
|
22 |
|
alpar@1
|
23 |
Model I - Harvest Scheduling formulation for Sustainable Forest Management (SFM)
|
alpar@1
|
24 |
|
alpar@1
|
25 |
Features are:
|
alpar@1
|
26 |
* Net Present Value for the objective function (Revenue - Cost)
|
alpar@1
|
27 |
* Harvest Constraints by period - Sustainable Yield per Period
|
alpar@1
|
28 |
* Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha (1-Apha)
|
alpar@1
|
29 |
* Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta (1 +Beta)
|
alpar@1
|
30 |
* Forest / Land Constraint -- Total Area of the forest
|
alpar@1
|
31 |
* Forest Stand Constraint -- Individual stands
|
alpar@1
|
32 |
|
alpar@1
|
33 |
What is next? -- Forest Mgt Carbon Accounting for Climate Change
|
alpar@1
|
34 |
|
alpar@1
|
35 |
Note: The model file that the data containing in
|
alpar@1
|
36 |
the dbf files is public domain material (so it is compatible with the
|
alpar@1
|
37 |
GNU GPL) and data can be found in
|
alpar@1
|
38 |
http://warnell.forestry.uga.edu/Warnell/Bettinger/mgtbook/index.htm
|
alpar@1
|
39 |
|
alpar@1
|
40 |
# Noli Sicad --- nsicad@gmail.com
|
alpar@1
|
41 |
|
alpar@1
|
42 |
*/
|
alpar@1
|
43 |
|
alpar@1
|
44 |
set G_STAND_TYPE; # A, B, C
|
alpar@1
|
45 |
|
alpar@1
|
46 |
set I_CULTURAL_PRES;
|
alpar@1
|
47 |
set J_MGT_YEAR;
|
alpar@1
|
48 |
|
alpar@1
|
49 |
param K_PERIOD;
|
alpar@1
|
50 |
param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR}; # cost
|
alpar@1
|
51 |
|
alpar@1
|
52 |
param Yield_Table_Vol{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0;
|
alpar@1
|
53 |
|
alpar@1
|
54 |
|
alpar@1
|
55 |
param Alpha >= 0;
|
alpar@1
|
56 |
param Beta >= 0;
|
alpar@1
|
57 |
|
alpar@1
|
58 |
param TCost_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD} >= 0;
|
alpar@1
|
59 |
|
alpar@1
|
60 |
param NetRev_Table{G_STAND_TYPE, I_CULTURAL_PRES, J_MGT_YEAR, 1..K_PERIOD};
|
alpar@1
|
61 |
|
alpar@1
|
62 |
|
alpar@1
|
63 |
var XForestLand{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} >= 0;
|
alpar@1
|
64 |
|
alpar@1
|
65 |
|
alpar@1
|
66 |
#reading dbf tables
|
alpar@1
|
67 |
table tab IN "xBASE" "standtype.dbf": G_STAND_TYPE <- [STAND];
|
alpar@1
|
68 |
display G_STAND_TYPE;
|
alpar@1
|
69 |
|
alpar@1
|
70 |
|
alpar@1
|
71 |
table tab2 IN "xBASE" "cultural_pres.dbf": I_CULTURAL_PRES <- [CUL_PRES];
|
alpar@1
|
72 |
display I_CULTURAL_PRES;
|
alpar@1
|
73 |
|
alpar@1
|
74 |
table tab3 IN "xBASE" "mgt_year.dbf": J_MGT_YEAR <- [MGT_YEAR];
|
alpar@1
|
75 |
display J_MGT_YEAR;
|
alpar@1
|
76 |
|
alpar@1
|
77 |
/*
|
alpar@1
|
78 |
param Forest_Cost{G_STAND_TYPE,I_CULTURAL_PRES, J_MGT_YEAR} default 0; # cost
|
alpar@1
|
79 |
*/
|
alpar@1
|
80 |
|
alpar@1
|
81 |
set S1, dimen 3;
|
alpar@1
|
82 |
table tab4 IN "xBASE" "Forest_Cost.dbf": S1 <- [STAND, CUL_PRES, MGT_YEAR],Forest_Cost ~FCOST;
|
alpar@1
|
83 |
display Forest_Cost;
|
alpar@1
|
84 |
|
alpar@1
|
85 |
set S2, dimen 4;
|
alpar@1
|
86 |
table tab5 IN "xBASE" "Yield_Table_Vol.dbf": S2 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],Yield_Table_Vol ~YIELD;
|
alpar@1
|
87 |
display Yield_Table_Vol;
|
alpar@1
|
88 |
|
alpar@1
|
89 |
set S3, dimen 4;
|
alpar@1
|
90 |
table tab5 IN "xBASE" "TCost_Table.dbf": S3 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],TCost_Table ~TCOST;
|
alpar@1
|
91 |
display TCost_Table;
|
alpar@1
|
92 |
|
alpar@1
|
93 |
|
alpar@1
|
94 |
set S4, dimen 4;
|
alpar@1
|
95 |
table tab5 IN "xBASE" "NetRev_Table.dbf": S4 <- [STAND, CUL_PRES, MGT_YEAR, PERIOD],NetRev_Table ~NETREV;
|
alpar@1
|
96 |
display NetRev_Table;
|
alpar@1
|
97 |
|
alpar@1
|
98 |
|
alpar@1
|
99 |
param MGT;
|
alpar@1
|
100 |
|
alpar@1
|
101 |
param Area_Stand_Indi{g in G_STAND_TYPE, m in 1..MGT} default 0;
|
alpar@1
|
102 |
|
alpar@1
|
103 |
set ST, dimen 2;
|
alpar@1
|
104 |
table tab5 IN "xBASE" "stands.dbf": ST <- [VEG_TYPE, MGT], Area_Stand_Indi ~ACRES;
|
alpar@1
|
105 |
display Area_Stand_Indi;
|
alpar@1
|
106 |
|
alpar@1
|
107 |
param Area_Stand_Type{g in G_STAND_TYPE}:= sum {m in 1..MGT } Area_Stand_Indi[g,m];
|
alpar@1
|
108 |
display Area_Stand_Type;
|
alpar@1
|
109 |
|
alpar@1
|
110 |
|
alpar@1
|
111 |
param Total_Area := sum {g in G_STAND_TYPE, m in 1..MGT } Area_Stand_Indi[g,m];
|
alpar@1
|
112 |
display Total_Area;
|
alpar@1
|
113 |
|
alpar@1
|
114 |
param Harvest_Min_Vol_Period;
|
alpar@1
|
115 |
|
alpar@1
|
116 |
|
alpar@1
|
117 |
var NetPresentValue;
|
alpar@1
|
118 |
|
alpar@1
|
119 |
# Objective function
|
alpar@1
|
120 |
maximize Net_Present_Value: NetPresentValue;
|
alpar@1
|
121 |
|
alpar@1
|
122 |
subject to NPV:
|
alpar@1
|
123 |
NetPresentValue = sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Forest_Cost[g,i,j] * XForestLand[g,i,j];
|
alpar@1
|
124 |
|
alpar@1
|
125 |
# Harvest Constraint by Period
|
alpar@1
|
126 |
subject to Harvest_Period_H {k in 1..K_PERIOD}:
|
alpar@1
|
127 |
sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] >= Harvest_Min_Vol_Period;
|
alpar@1
|
128 |
|
alpar@1
|
129 |
|
alpar@1
|
130 |
#Even-Flow Constraint / Volume - Harvest Flow Constraint - Alpha
|
alpar@1
|
131 |
subject to Even_Flow_Constaints_Alpha {k in 6..K_PERIOD-1}:
|
alpar@1
|
132 |
(1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] -
|
alpar@1
|
133 |
sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] <= 0;
|
alpar@1
|
134 |
|
alpar@1
|
135 |
# Even-Flow Constraint / Volume - Harvest Flow Constraint - Beta
|
alpar@1
|
136 |
subject to Even_Flow_Constaints_Beta {k in 6..K_PERIOD-1}:
|
alpar@1
|
137 |
(1 + Beta) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] -
|
alpar@1
|
138 |
sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j] >= 0;
|
alpar@1
|
139 |
|
alpar@1
|
140 |
# Forest / Land Constraints
|
alpar@1
|
141 |
subject to Total_Area_Constraint:
|
alpar@1
|
142 |
sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j] <= Total_Area;
|
alpar@1
|
143 |
display Total_Area;
|
alpar@1
|
144 |
|
alpar@1
|
145 |
# Forest / Land Constraints for A B C
|
alpar@1
|
146 |
subject to Area {g in G_STAND_TYPE}:
|
alpar@1
|
147 |
sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j] = Area_Stand_Type[g];
|
alpar@1
|
148 |
|
alpar@1
|
149 |
|
alpar@1
|
150 |
|
alpar@1
|
151 |
solve;
|
alpar@1
|
152 |
#RESULT SECTION
|
alpar@1
|
153 |
printf '#################################\n';
|
alpar@1
|
154 |
printf 'Forest Management Model I - Noli Sicad\n';
|
alpar@1
|
155 |
printf '\n';
|
alpar@1
|
156 |
printf 'Net Present Value = %.2f\n', NetPresentValue;
|
alpar@1
|
157 |
printf '\n';
|
alpar@1
|
158 |
|
alpar@1
|
159 |
printf '\n';
|
alpar@1
|
160 |
printf 'Variables\n';
|
alpar@1
|
161 |
printf 'Stand_Type Age_Class Mgt_Presc Sign Value \n';
|
alpar@1
|
162 |
printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR}:'%5s %10s %11s = %10.2f\n', g,i,j, XForestLand[g,i,j];
|
alpar@1
|
163 |
printf '\n';
|
alpar@1
|
164 |
|
alpar@1
|
165 |
printf 'Constraints\n';
|
alpar@1
|
166 |
printf 'Period Harvest Sign \n';
|
alpar@1
|
167 |
for {k in 1..K_PERIOD} {
|
alpar@1
|
168 |
printf '%5s %10.2f >= %.3f\n', k, sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j], Harvest_Min_Vol_Period;
|
alpar@1
|
169 |
}
|
alpar@1
|
170 |
|
alpar@1
|
171 |
# xbase (dbf) output
|
alpar@1
|
172 |
table Harvest{k in 1..K_PERIOD} OUT "xBASE" "HarvestArea1.dbf" "N(5)N(15,2)" : k ~ Period, (sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]) ~ H_Area;
|
alpar@1
|
173 |
|
alpar@1
|
174 |
# xbase (dbf) read
|
alpar@1
|
175 |
set S, dimen 2;
|
alpar@1
|
176 |
table tab2 IN "xBASE" "HarvestArea1.dbf": S <- [Period, H_Area];
|
alpar@1
|
177 |
display S;
|
alpar@1
|
178 |
|
alpar@1
|
179 |
|
alpar@1
|
180 |
|
alpar@1
|
181 |
|
alpar@1
|
182 |
printf '\n';
|
alpar@1
|
183 |
printf 'Constraint\n';
|
alpar@1
|
184 |
printf 'Harvest Period\n';
|
alpar@1
|
185 |
printf 'Type AgeClass PrescMgt Period Value\n';
|
alpar@1
|
186 |
printf{g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR, k in 1..K_PERIOD}:'%5s %11s %11s %5s %10.2f\n', g,i,j, k, (Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j]);
|
alpar@1
|
187 |
|
alpar@1
|
188 |
|
alpar@1
|
189 |
printf 'Even_Flow_Constaint_Alpha (1-Alpha)\n';
|
alpar@1
|
190 |
printf 'Period Sign \n';
|
alpar@1
|
191 |
for {k in 6..K_PERIOD-1} {
|
alpar@1
|
192 |
printf "%s %10.2f <= %s\n", k, ((1 - Alpha) * sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k] * XForestLand[g,i,j] - sum {g in G_STAND_TYPE,i in I_CULTURAL_PRES, j in J_MGT_YEAR} Yield_Table_Vol[g,i,j,k+1] * XForestLand[g,i,j]),0;
|
alpar@1
|
193 |
}
|
alpar@1
|
194 |
printf '\n';
|
alpar@1
|
195 |
|
alpar@1
|
196 |
|
alpar@1
|
197 |
# Forest / Land Constraints
|
alpar@1
|
198 |
printf '\n';
|
alpar@1
|
199 |
printf 'Total Area Constraint\n';
|
alpar@1
|
200 |
printf 'Type AgeClass PrescMgt Value Sign Total_Area \n';
|
alpar@1
|
201 |
printf '%5s <= %.3f\n',sum {g in G_STAND_TYPE, i in I_CULTURAL_PRES, j in J_MGT_YEAR} XForestLand[g,i,j], Total_Area;
|
alpar@1
|
202 |
|
alpar@1
|
203 |
printf 'Area\n';
|
alpar@1
|
204 |
printf 'Area Value Sign Areas_Stand\n';
|
alpar@1
|
205 |
for {g in G_STAND_TYPE} {
|
alpar@1
|
206 |
printf '%5s %10.2f <= %.3f\n', g, sum {i in I_CULTURAL_PRES,j in J_MGT_YEAR} XForestLand[g,i,j], Area_Stand_Type[g];
|
alpar@1
|
207 |
}
|
alpar@1
|
208 |
|
alpar@1
|
209 |
|
alpar@1
|
210 |
#DATA SECTION
|
alpar@1
|
211 |
|
alpar@1
|
212 |
data;
|
alpar@1
|
213 |
|
alpar@1
|
214 |
# Most of the data has been moved to dbf format
|
alpar@1
|
215 |
|
alpar@1
|
216 |
param MGT:=31;
|
alpar@1
|
217 |
|
alpar@1
|
218 |
param K_PERIOD:= 7;
|
alpar@1
|
219 |
|
alpar@1
|
220 |
param Alpha:= 0.20;
|
alpar@1
|
221 |
param Beta:= 0.20;
|
alpar@1
|
222 |
|
alpar@1
|
223 |
param Harvest_Min_Vol_Period:= 12000;
|
alpar@1
|
224 |
|
alpar@1
|
225 |
end;
|
alpar@1
|
226 |
|