Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@trialsolution
Created April 16, 2013 12:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save trialsolution/5395505 to your computer and use it in GitHub Desktop.
Save trialsolution/5395505 to your computer and use it in GitHub Desktop.
GAMS implementation of the textbook example for farm planning model Published in Moss "Risk, uncertainty and the agricultural firm", originally from the article of Freund (1956) in Econometrica
$ontext
Freund showed that the expected utility of a normally distributed gamble given
negative exponential preferences could be written as:
E(U(x)) = mu(x) - rho/2 * sigma^2(x)
where mu and sigma are the mean and standard deviation of the normally distributed gamble
In a vector form the expected utility maximization problem can be written in the form:
max x'mu - rho/2 * x' SIGMA x
where SIGMA is the covariance matrix
Freund, R. J. "The Introduction of Risk into a Programming Model." Econometrica 24(1956): 253-63.
$offtext
* resource requirements
set x "activities" /
x1 "Early_Irish_Potatoes", x2 "Corn", x3 "Beef", x4 "Fall_Cabbage"
/;
alias(x,y);
set season /January_June, July_December/;
table landuse_coef(season,x)
x1 x2 x3 x4
January_June 1.199 1.382 2.776 .000
July_December .000 1.382 2.776 .482
;
parameter land_total(season);
land_total(season)=60.;
set period "time periods" /p1 * p3/;
table capital_coef(period,x)
x1 x2 x3 x4
P1 1.064 .484 .038 .000
P2 -2.064 .020 .107 .229
P3 -2.064 -1.504 -1.145 -1.229
;
parameter capital_total(period)
/
p1 24.0
p2 12.0
p2 0.0
/;
table labor_coef "Managerial Labor"
x1 x2 x3 x4
P1 5.276 4.836 .000 .000
P2 2.158 4.561 .000 4.198
P3 .000 4.561 .000 13.606
parameter labor_total
/
p1 799.0
p2 867.0
p3 783.0
/;
table SIGMA(x,x)
x1 x2 x3 x4
x1 7304.69 903.89 -688.73 -182.05
x2 620.16 -471.14 110.43
x3 1124.64 750.69
x4 3689.53
;
*SIGMA(x,y) $ (x.pos gt y.pos) = SIGMA(y,x);
$ontext
Definition of risk aversion coeffitients
----------------------------------------
absolute risk aversion coef: Ra(x) = - U''(x) / U'(x)
relative risk aversion coef: Rr(x) = - x*U''(x) / U'(x)
In case of exponential utility f.: U(x) = -exp(-rho*x)
Ra(x) = rho
Power utility function: U(x) = x**(1-r) / (1-r)
Ra(x) = r/x
Rr(x) = r [constant relative risk aversion]
Sclaing of risk aversion coeffs
-------------------------------
Important when using risk aversion coeffs. from literature!
Scaling of the outcome space is required: rho_lit = const * rho_new
example: from literature r = 0.0001/USD => r=0.0000667/AUSD (with an exchange rate of 1/.667)
Do not confuse the scaling with an arbirary linear transformatin of the utility function
Ra is invariant to linear transformation...
Interpretation of Ra
--------------------
Following Raskin and Cochran develops an interpretation in terms of marginal utility.
r(x) = - u'/u''(x) = - [du'/dx] / u' = - d/dx [ln(u'(x))]
= - [du'(x)/u'(x)] / dx
Thus Ra is the percent change in the marginal utility level for a given level of income.
So r is associated with a unit of change in outcome space.
E.g. r=.0001/USD means that marginal utility is falling at a rate of .01% per dollar change in income.
$offtext
scalar rho "Arrow Pratt absolute risk aversion coefficient";
rho = 1/1250;
display rho;
* The farm planning problem is defined based on 100 USD of expected farm revenue rather than based on acres
* mu is one unit of hundred dollars
parameter mu(x);
mu(x) = 1;
variable
v_x(x) "activity levels"
EU "expected utility"
;
positive variable v_x;
v_x.L(x) = 1;
equation
utility "expected utility"
labor_constr(period)
capital_constr(period)
land_constr(season)
;
utility..
EU =e= sum(x, mu(x) * v_x(x))
- rho/2 *
sum{y, v_x(y) * [sum(x $ (x.pos le y.pos), SIGMA(x,y) * v_x(x))
+ sum(x $ (x.pos gt y.pos), SIGMA(y,x) * v_x(x))]};
* [ sum((x,y) $ (x.pos le y.pos), SIGMA(x,y) * v_x(x) * v_x(y))
* + sum((x,y) $ (x.pos gt y.pos), SIGMA(y,x) * v_x(x) * v_x(y))];
land_constr(season)..
sum(x, landuse_coef(season,x) * v_x(x)) =l= land_total(season);
labor_constr(period)..
sum(x, labor_coef(period,x) * v_x(x)) =l= labor_total(period);
capital_constr(period)..
sum(x, capital_coef(period,x) * v_x(x)) =l= capital_total(period);
model freund /utility, land_constr, labor_constr, capital_constr/;
solve freund using nlp maximizing EU;
$ontext
I was not able to reproduce the textbook solution...
---- VAR v_x activity levels
LOWER LEVEL UPPER MARGINAL
x1 . . +INF -0.453
x2 . 4.195 +INF EPS
x3 . 2.869 +INF .
x4 . . +INF -1.094
LOWER LEVEL UPPER MARGINAL
---- VAR EU -INF 3.532 +INF .
$offtext
* interprete the shadow values of the constraint as changes in certainty equivalence
parameter shadow_values;
shadow_values("land",season) = land_constr.M(season);
shadow_values("labor",period) = labor_constr.M(period);
shadow_values("capital",period) = capital_constr.M(period);
display shadow_values;
* SCENARIO with zero risk aversion => quadratic term in the objective eliminated
*===============================================================================
* putting risk aversion to zero
rho = 0;
solve freund using nlp maximizing EU;
$ontext
I find the same solution as in the textbook.
Probably I have a data problem with the variance matrix or with rho...
---- VAR v_x activity levels
LOWER LEVEL UPPER MARGINAL
x1 . 22.141 +INF .
x2 . . +INF -0.214
x3 . 11.622 +INF .
x4 . 57.548 +INF .
LOWER LEVEL UPPER MARGINAL
---- VAR EU -INF 91.311 +INF .
$offtext
* CALIBRATION to textbook optimal levels (calibration by rho)
*=======================================
* finding a risk aversion matching the solution x=(10.29,26.76,2.68,32.35)
parameter x0(x)
/
x1 10.29
x2 26.76
x3 2.68
x4 32.35
/;
variable v_rho;
positive variable v_rho;
equation
utility2 "with variable rho"
;
utility2..
EU =e= sum(x, mu(x) * v_x(x))
- v_rho/2 *
sum{y, v_x(y) * [sum(x $ (x.pos le y.pos), SIGMA(x,y) * v_x(x))
+ sum(x $ (x.pos gt y.pos), SIGMA(y,x) * v_x(x))]};
model calibration /utility2, land_constr, labor_constr, capital_constr/;
* fix the activity levels
v_x.fx(x) = x0(x);
* fix the objective value
EU.fx = 53.8308;
* try to deal with preciosion in the publication
labor_total(period) = labor_total(period)*1.01;
capital_total(period) = capital_total(period)*1.01;
land_total(season) = land_total(season)*1.01;
solve calibration using nlp maximizing EU;
* SOLVE with calibrated rho
*==========================
* solve the orignal model again with the calibrated rho
rho = v_rho.L;
EU.up = inf;
EU.lo = 0;
v_x.up(x) = inf;
v_x.lo(x) = 0;
* get back original bounds
labor_total(period) = labor_total(period)/1.01;
capital_total(period) = capital_total(period)/1.01;
land_total(season) = land_total(season)/1.01;
solve freund using nlp maximizing EU;
* compare it to the textbook solution
$ontext
still does not match.
The solution seems to be extremely sensitive to rounding errors in rho...
Does better scaling help???
---- VAR v_x activity levels
LOWER LEVEL UPPER MARGINAL
x1 . 8.041 +INF .
x2 . 31.909 +INF .
x3 . . +INF -0.222
x4 . 32.992 +INF .
LOWER LEVEL UPPER MARGINAL
---- VAR EU . 54.563 +INF .
$offtext
* scaled model -- calibration
*============================
variable v_theta "inverse of rho";
positive variable v_theta;
v_theta.L = 1250;
equation utility_scaled2 "scaled objective function";
utility_scaled2..
EU =e= sum(x, mu(x) * v_x(x))
- (1/v_theta)/2 *
sum{y, v_x(y) * [sum(x $ (x.pos le y.pos), SIGMA(x,y) * v_x(x))
+ sum(x $ (x.pos gt y.pos), SIGMA(y,x) * v_x(x))]};
model calibration_scaled /utility_scaled2, land_constr, labor_constr, capital_constr/;
* fix the activity levels
v_x.fx(x) = x0(x);
* fix the objective value
EU.fx = 53.8308;
* try to deal with preciosion in the publication
labor_total(period) = labor_total(period)*1.01;
capital_total(period) = capital_total(period)*1.01;
land_total(season) = land_total(season)*1.01;
solve calibration_scaled using nlp maximizing EU;
* scaled model SOLVE
*=====================
scalar theta;
theta = v_theta.L;
EU.up = inf;
EU.lo = 0;
v_x.up(x) = inf;
v_x.lo(x) = 0;
* get back original bounds
labor_total(period) = labor_total(period)/1.01;
capital_total(period) = capital_total(period)/1.01;
land_total(season) = land_total(season)/1.01;
* define scaled equation and model
equation utility_scaled "scaled objective function";
utility_scaled..
EU =e= sum(x, mu(x) * v_x(x))
- (1/theta)/2 *
sum{y, v_x(y) * [sum(x $ (x.pos le y.pos), SIGMA(x,y) * v_x(x))
+ sum(x $ (x.pos gt y.pos), SIGMA(y,x) * v_x(x))]};
model freund_scaled /utility_scaled, land_constr, labor_constr, capital_constr/;
solve freund_scaled using nlp maximizing EU;
$ontext
the scaled model delivers the same solution...
---- VAR v_x activity levels
LOWER LEVEL UPPER MARGINAL
x1 . 8.041 +INF .
x2 . 31.909 +INF .
x3 . . +INF -0.222
x4 . 32.992 +INF .
LOWER LEVEL UPPER MARGINAL
---- VAR EU . 54.563 +INF .
$offtext
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment