Skip to content

Commit 5368fdd

Browse files
committed
Added DICE Experiments from Climate School.
1 parent 7c039a7 commit 5368fdd

File tree

4 files changed

+422
-0
lines changed

4 files changed

+422
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package net.finmath.experiments.ui;
2+
3+
import java.text.DecimalFormat;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.function.BooleanSupplier;
7+
import java.util.function.DoubleConsumer;
8+
import java.util.function.UnaryOperator;
9+
import java.util.stream.Collectors;
10+
11+
import net.finmath.climate.models.ClimateModel;
12+
import net.finmath.climate.models.dice.DICEModel;
13+
import net.finmath.climateschool.utilities.DICEModelPlots;
14+
import net.finmath.experiments.ui.parameter.BooleanParameter;
15+
import net.finmath.experiments.ui.parameter.DoubleParameter;
16+
import net.finmath.time.TimeDiscretization;
17+
import net.finmath.time.TimeDiscretizationFromArray;
18+
19+
public class DICEAbatementTimeExperimentUI extends ExperimentUI {
20+
21+
private static final double timeStep = 1.0;
22+
private static final double timeHorizon = 500.0;
23+
24+
private final DecimalFormat numberDigit3 = new DecimalFormat("#.000");
25+
private final DecimalFormat numberPercent2 = new DecimalFormat("#.00%");
26+
27+
private final DICEModelPlots plots = new DICEModelPlots();
28+
29+
public DICEAbatementTimeExperimentUI() {
30+
super(List.of(
31+
new DoubleParameter("Discount Rate", 0.03, 0.01, 0.05),
32+
new DoubleParameter("Abatement Max Time", 50.0, 10.0, 200.0),
33+
new BooleanParameter("Show Cost", false)
34+
));
35+
}
36+
37+
38+
public String getTitle() { return "DICE Model - One Parametric Abatement Model - NOT CALIBRATED"; }
39+
40+
public void runCalculation(BooleanSupplier isCancelled, DoubleConsumer progress) {
41+
Map<String, Object> currentParameterSet = getExperimentParameters().stream().collect(Collectors.toMap(p -> p.getBindableValue().getName(), p -> p.getBindableValue().getValue()));
42+
43+
System.out.println("Calculation with Parameters: " + currentParameterSet);
44+
45+
/*
46+
* Discount rate
47+
*/
48+
final double discountRate = (Double)currentParameterSet.get("Discount Rate");
49+
50+
/*
51+
* Parameters for the abatement model (abatement = fraction of industrial CO2 reduction; 1.00 ~ 100 % reduction ~ carbon neutral).
52+
*/
53+
final double abatementInitial = 0.03;
54+
final double abatementMax = 1.00;
55+
final double abatementMaxTime = (Double)currentParameterSet.get("Abatement Max Time");
56+
57+
/*
58+
* Create a time discretization
59+
*/
60+
final int numberOfTimeSteps = (int)Math.round(timeHorizon / timeStep);
61+
final TimeDiscretization timeDiscretization = new TimeDiscretizationFromArray(0.0, numberOfTimeSteps, timeStep);
62+
63+
/*
64+
* Create our abatement model: it is a piecewise linear funtion: starting in abatementInitial, then reaching abatementMax in abatementMaxTime years, then staying at abatementMax.
65+
*/
66+
final UnaryOperator<Double> abatementFunction = time -> Math.min(abatementInitial + (abatementMax-abatementInitial)/abatementMaxTime * time, abatementMax);
67+
68+
/*
69+
* Create our savings rate model: a constant.
70+
*/
71+
final UnaryOperator<Double> savingsRateFunction = time -> 0.26;
72+
73+
/*
74+
* Create the DICE model from the given parameters.
75+
*/
76+
final ClimateModel climateModel = new DICEModel(timeDiscretization, abatementFunction, savingsRateFunction, discountRate);
77+
78+
/*
79+
* Plots
80+
*/
81+
82+
if(!Thread.currentThread().isInterrupted() && !isCancelled.getAsBoolean()) {
83+
synchronized(this) {
84+
String spec = "T(\u03BC=1) =" + numberDigit3.format(abatementMaxTime) + ", r = " + numberPercent2.format(discountRate);
85+
86+
plots.plot(climateModel, spec);
87+
88+
boolean showCost = (boolean)currentParameterSet.get("Show Cost");
89+
if(showCost) {
90+
plots.plotCost(climateModel, discountRate, spec);
91+
}
92+
else {
93+
plots.closeCost();
94+
}
95+
}
96+
}
97+
}
98+
99+
100+
@Override
101+
protected void onClose() {
102+
synchronized(this) {
103+
super.onClose();
104+
105+
if(plots != null) plots.close();
106+
}
107+
}
108+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package net.finmath.experiments.ui;
2+
3+
import java.text.DecimalFormat;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.function.BooleanSupplier;
8+
import java.util.function.DoubleConsumer;
9+
import java.util.function.UnaryOperator;
10+
import java.util.stream.Collectors;
11+
12+
import net.finmath.climate.models.ClimateModel;
13+
import net.finmath.climate.models.dice.DICEModel;
14+
import net.finmath.climateschool.utilities.AdamOptimizerUsingFiniteDifferences;
15+
import net.finmath.climateschool.utilities.AdamOptimizerUsingFiniteDifferences.GradientMethod;
16+
import net.finmath.climateschool.utilities.DICEModelPlots;
17+
import net.finmath.experiments.ui.parameter.BooleanParameter;
18+
import net.finmath.experiments.ui.parameter.DoubleParameter;
19+
import net.finmath.stochastic.RandomVariable;
20+
import net.finmath.stochastic.Scalar;
21+
import net.finmath.time.TimeDiscretization;
22+
import net.finmath.time.TimeDiscretizationFromArray;
23+
24+
public class DICECalibrationExperimentUI extends ExperimentUI {
25+
26+
private static final double timeStep = 1.0;
27+
private static final double timeHorizon = 500.0;
28+
29+
private final DecimalFormat numberDigit3 = new DecimalFormat("#.000");
30+
private final DecimalFormat numberPercent2 = new DecimalFormat("#.00%");
31+
32+
double[] initialParameters;
33+
34+
private final DICEModelPlots plots = new DICEModelPlots();
35+
36+
public DICECalibrationExperimentUI() {
37+
super(List.of(
38+
new DoubleParameter("Discount Rate", 0.03, 0.01, 0.05),
39+
new BooleanParameter("Show Cost", false)
40+
// new Parameter("Abatement Max Time", 50.0, 10.0, 200.0)
41+
));
42+
}
43+
44+
public String getTitle() { return "DICE Model - Full Abatement Model - Optimized Emisison Path (Calibration)"; }
45+
46+
public void runCalculation(BooleanSupplier isCancelled, DoubleConsumer progress) {
47+
Map<String, Object> currentParameterSet = getExperimentParameters().stream().collect(Collectors.toMap(p -> p.getBindableValue().getName(), p -> p.getBindableValue().getValue()));
48+
49+
System.out.println("Calculation with Parameters: " + currentParameterSet);
50+
51+
/*
52+
* Create a time discretization
53+
*/
54+
final int numberOfTimeSteps = (int)Math.round(timeHorizon / timeStep);
55+
final TimeDiscretization timeDiscretization = new TimeDiscretizationFromArray(0.0, numberOfTimeSteps, timeStep);
56+
57+
/*
58+
* Create our savings rate model: a constant.
59+
*/
60+
final UnaryOperator<Double> savingsRateFunction = time -> 0.26;
61+
62+
/*
63+
* Discount rate
64+
*/
65+
final double discountRate = (Double)currentParameterSet.get("Discount Rate");
66+
67+
// Initial parameters for our abatement function
68+
if(initialParameters == null) {
69+
initialParameters = new double[timeDiscretization.getNumberOfTimes()];
70+
Arrays.fill(initialParameters, -Math.log(-Math.log(0.8)));
71+
}
72+
73+
final AdamOptimizerUsingFiniteDifferences optimizer = new AdamOptimizerUsingFiniteDifferences(initialParameters, 800, 0.05, GradientMethod.AVERAGE) {
74+
private int iteration = 0;
75+
@Override
76+
public RandomVariable setValue(RandomVariable[] parameters) {
77+
if(Thread.currentThread().isInterrupted()) {
78+
this.stop();
79+
}
80+
81+
double[] abatementParameter = Arrays.stream(parameters).mapToDouble(RandomVariable::getAverage).map(x -> Math.exp(-Math.exp(-x))).toArray();
82+
abatementParameter[0] = 0.03;
83+
initialParameters = Arrays.stream(parameters).mapToDouble(RandomVariable::getAverage).toArray();
84+
85+
/*
86+
* Create our abatement model
87+
*/
88+
final UnaryOperator<Double> abatementFunction = time -> abatementParameter[(int)Math.round(time/timeStep)];
89+
90+
/*
91+
* Create the DICE model
92+
*/
93+
final ClimateModel climateModel = new DICEModel(timeDiscretization, abatementFunction, savingsRateFunction, discountRate);
94+
95+
final double value = climateModel.getValue().expectation().doubleValue();
96+
97+
// Penalty for non-smoothness - it works without this, but this helps the optimizer to avoid onszillations (that are la
98+
double roughness = 0.0;
99+
for(int i=1; i<abatementParameter.length-2; i++) {
100+
roughness += Math.pow(abatementParameter[i+1] - abatementParameter[i], 2.0);
101+
}
102+
roughness = Math.sqrt(roughness);
103+
roughness /= abatementParameter.length;
104+
roughness *= 0.1;
105+
106+
// Update the plot every 200 iterations
107+
if(iteration%200 == 0 && !Thread.currentThread().isInterrupted()) {
108+
String spec = "r = " + numberPercent2.format(discountRate) + "; value = " + numberDigit3.format(value);
109+
plots.plot(climateModel, spec);
110+
boolean showCost = (boolean)currentParameterSet.get("Show Cost");
111+
if(showCost) {
112+
plots.plotCost(climateModel, discountRate, spec);
113+
}
114+
else {
115+
plots.closeCost();
116+
}
117+
}
118+
iteration++;
119+
120+
return Scalar.of(-value);// + roughness);
121+
}
122+
};
123+
124+
optimizer.run();
125+
126+
System.out.println("Optimizer finished.");
127+
128+
// Get optimal value
129+
final RandomVariable[] bestParameters = optimizer.getBestFitParameters();
130+
double[] abatementParameter = Arrays.stream(bestParameters).mapToDouble(RandomVariable::getAverage).map(x -> Math.exp(-Math.exp(-x))).toArray();
131+
abatementParameter[0] = 0.03;
132+
System.out.println(Arrays.toString(abatementParameter));
133+
134+
/*
135+
* Create our abatement model
136+
*/
137+
final UnaryOperator<Double> abatementFunction = time -> abatementParameter[(int)Math.round(time/timeStep)];
138+
139+
/*
140+
* Create the DICE model
141+
*/
142+
final ClimateModel climateModel = new DICEModel(timeDiscretization, abatementFunction, savingsRateFunction, discountRate);
143+
144+
/*
145+
* Plots
146+
*/
147+
148+
if(!Thread.currentThread().isInterrupted() && !isCancelled.getAsBoolean()) {
149+
synchronized(this) {
150+
String spec = "r = " + numberPercent2.format(discountRate);
151+
plots.plot(climateModel, spec);
152+
153+
boolean showCost = (boolean)currentParameterSet.get("Show Cost");
154+
if(showCost) {
155+
plots.plotCost(climateModel, discountRate, spec);
156+
}
157+
else {
158+
plots.closeCost();
159+
}
160+
}
161+
}
162+
}
163+
164+
@Override
165+
protected void onClose() {
166+
synchronized(this) {
167+
super.onClose();
168+
169+
if(plots != null) plots.close();
170+
}
171+
}
172+
}

0 commit comments

Comments
 (0)