From 0602d1425746dcb276796ad166b8c19f4d20f91e Mon Sep 17 00:00:00 2001 From: alexanpe <devnull@localhost> Date: Wed, 27 Feb 2019 13:55:21 +0000 Subject: [PATCH] Use previous demand results as initial conditions --- GAMS/elasticDemand.gms | 30 ++--- debug_config.properties | 10 +- src/ac/ed/lurg/ModelConfig.java | 1 - .../ed/lurg/country/AbstractCountryAgent.java | 2 +- .../country/gams/GamsCommodityDemand.java | 36 ++++++ .../ed/lurg/country/gams/GamsDemandInput.java | 39 +++++++ .../country/gams/GamsDemandOptimiser.java | 104 +++++++++++------- .../lurg/country/gams/GamsDemandOutput.java | 38 +++++++ .../ed/lurg/demand/ElasticDemandManager.java | 11 +- 9 files changed, 207 insertions(+), 64 deletions(-) create mode 100644 src/ac/ed/lurg/country/gams/GamsCommodityDemand.java create mode 100644 src/ac/ed/lurg/country/gams/GamsDemandInput.java create mode 100644 src/ac/ed/lurg/country/gams/GamsDemandOutput.java diff --git a/GAMS/elasticDemand.gms b/GAMS/elasticDemand.gms index e3f43c04..ca1a406f 100644 --- a/GAMS/elasticDemand.gms +++ b/GAMS/elasticDemand.gms @@ -10,6 +10,9 @@ PARAMETER delta(i) Parameter of MAIDADS tau(i) Parameter of MAIDADS omega Parameter of MAIDADS + previousU + previousSubs(i) + previousDisc(i) ; $gdxin %gdx_parameters% @@ -32,10 +35,10 @@ PARAMETER $gdxin %gdx_prices_and_gdp% *$gdxin "../../GAMS/PricesAndGdp.gdx" -$load p=price, m=gdp_pc +$load p=price, m=gdp_pc, previousU, previousSubs, previousDisc $gdxin -display p, m , alpha, beta, kappa, delta, tau, omega; +display p, m, alpha, beta, kappa, delta, tau, omega; w.up(j) = 1; @@ -69,12 +72,14 @@ model MAIDADS_Sim "MAIDADS model for simulation" / MAIDADS_Sim.optfile = 1; option cns=path; -u = 0; -SubsistenceC(j) = 0.05; -DiscretionaryC(i)$p(i) = 0.05; +u = previousU; +SubsistenceC(i) = previousSubs(i); +DiscretionaryC(i) = previousDisc(i); DiscretionaryC.LO(i) = 1E-11; SubsistenceC.LO(j) = 0; -w(j) = (SubsistenceC(j)+DiscretionaryC(j))*p(j)/m; +w(j) = (SubsistenceC(j)+DiscretionaryC(j))*p(j)/m; + +display u.l, DiscretionaryC.l, SubsistenceC.l; solve MAIDADS_Sim using cns; @@ -82,13 +87,8 @@ Scalar ms 'model status', ss 'solve status'; ms=MAIDADS_Sim.modelstat; ss=MAIDADS_Sim.solvestat; -display DiscretionaryC.l, alpha, beta, kappa,u.l; - -parameter totalDemand(i); -totalDemand(i) = SubsistenceC(i) + DiscretionaryC(i); - -parameter disc(i); - -disc(i) = [m-sum(j,p(j)*SubsistenceC(j))]; +display DiscretionaryC.l, u.l; -display disc; +*parameter disc(i); +*disc(i) = [m-sum(j,p(j)*SubsistenceC(j))]; +*display disc; diff --git a/debug_config.properties b/debug_config.properties index 29b8ba62..f5d79b5c 100644 --- a/debug_config.properties +++ b/debug_config.properties @@ -2,15 +2,15 @@ BASE_DIR=.. YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/LPJGPLUM_expt1.1_2006-2100_PLUM6xtra_20180412171654/rcp60 -DEBUG_LIMIT_COUNTRIES=false -DEBUG_COUNTRY_NAME=China +DEBUG_LIMIT_COUNTRIES=true +DEBUG_COUNTRY_NAME=Japan -IS_CALIBRATION_RUN = true +IS_CALIBRATION_RUN = false GENERATE_NEW_YIELD_CLUSTERS = false NUM_YIELD_CLUSTERS=8000 -END_TIMESTEP=0 -TIMESTEP_SIZE=1 +END_TIMESTEP=5 +TIMESTEP_SIZE=5 INTERPOLATE_OUTPUT_YEARS = false diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index c899a92c..c4042176 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -378,5 +378,4 @@ public class ModelConfig { public static final boolean USE_CRAFTY_COUNTRIES = getBooleanProperty("USE_CRAFTY_COUNTRIES", false); public static final String CRAFTY_PRODUCTION_DIR = getProperty("CRAFTY_PRODUCTION_DIR", OUTPUT_DIR + File.separator + "crafty"); - public static final double NON_FOOD_PRICE = getDoubleProperty("NON_FOOD_PRICE", 0.06); } diff --git a/src/ac/ed/lurg/country/AbstractCountryAgent.java b/src/ac/ed/lurg/country/AbstractCountryAgent.java index 892882eb..e6ca1af5 100644 --- a/src/ac/ed/lurg/country/AbstractCountryAgent.java +++ b/src/ac/ed/lurg/country/AbstractCountryAgent.java @@ -72,7 +72,7 @@ public abstract class AbstractCountryAgent { LogWriter.println(commodity.getGamsName() + ": " + commPrice); } - prices.put(CommodityType.NONFOOD, ModelConfig.NON_FOOD_PRICE); + prices.put(CommodityType.NONFOOD, Double.NaN); return prices; } diff --git a/src/ac/ed/lurg/country/gams/GamsCommodityDemand.java b/src/ac/ed/lurg/country/gams/GamsCommodityDemand.java new file mode 100644 index 00000000..162d5879 --- /dev/null +++ b/src/ac/ed/lurg/country/gams/GamsCommodityDemand.java @@ -0,0 +1,36 @@ +package ac.ed.lurg.country.gams; + +import ac.ed.lurg.types.CommodityType; + +public class GamsCommodityDemand { + + private CommodityType commodity; + private double subsistence; + private double discretionary; + + public GamsCommodityDemand(CommodityType commodity, double subsistence, double discretionary) { + this.commodity = commodity; + this.subsistence = subsistence; + this.discretionary = discretionary; + } + + public double getSubsistence() { + return subsistence; + } + + public double getDiscretionary() { + return discretionary; + } + + public double getKcalTotal() { + return (subsistence+ discretionary) * 2000; + } + + public double getPlumDemand() { + return getKcalTotal()*365/commodity.getkcalPerT(); + } + + public CommodityType getCommodity() { + return commodity; + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/gams/GamsDemandInput.java b/src/ac/ed/lurg/country/gams/GamsDemandInput.java new file mode 100644 index 00000000..d7cd2f3b --- /dev/null +++ b/src/ac/ed/lurg/country/gams/GamsDemandInput.java @@ -0,0 +1,39 @@ +package ac.ed.lurg.country.gams; + +import java.util.Map; + +import ac.ed.lurg.country.SingleCountry; +import ac.ed.lurg.types.CommodityType; + +public class GamsDemandInput { + private SingleCountry country; + private double gdpPc; + private Map<CommodityType, Double> prices; + private double usaGdpPc; + private GamsDemandOutput previousGamsDemands; + + public GamsDemandInput(SingleCountry country, double gdpPc, Map<CommodityType, Double> prices, double usaGdpPc, GamsDemandOutput previousGamsDemands) { + super(); + this.country = country; + this.gdpPc = gdpPc; + this.prices = prices; + this.usaGdpPc = usaGdpPc; + this.previousGamsDemands = previousGamsDemands; + } + + public SingleCountry getCountry() { + return country; + } + public double getGdpPc() { + return gdpPc; + } + public Map<CommodityType, Double> getPrices() { + return prices; + } + public double getUsaGdpPc() { + return usaGdpPc; + } + public GamsDemandOutput getPreviousDemands() { + return previousGamsDemands; + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java index 17e3650c..a3b8a5e2 100644 --- a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java @@ -1,7 +1,7 @@ package ac.ed.lurg.country.gams; import java.io.File; -import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Vector; @@ -11,29 +11,24 @@ import com.gams.api.GAMSJob; import com.gams.api.GAMSOptions; import com.gams.api.GAMSParameter; import com.gams.api.GAMSParameterRecord; +import com.gams.api.GAMSVariable; +import com.gams.api.GAMSVariableRecord; import com.gams.api.GAMSWorkspace; import com.gams.api.GAMSWorkspaceInfo; import ac.ed.lurg.ModelConfig; -import ac.ed.lurg.country.SingleCountry; import ac.ed.lurg.types.CommodityType; import ac.ed.lurg.utils.LogWriter; public class GamsDemandOptimiser { - private SingleCountry country; - private double gdpPc; - private Map<CommodityType, Double> prices; - private double usaGdpPc; + private GamsDemandInput inputData; - public GamsDemandOptimiser(SingleCountry country, double gdpPc, Map<CommodityType, Double> prices, double usaGdpPc) { - this.country = country; - this.gdpPc = gdpPc; - this.prices = prices; - this.usaGdpPc = usaGdpPc; + public GamsDemandOptimiser(GamsDemandInput inputData) { + this.inputData = inputData; } - public Map<CommodityType, Double> getDemandPc() { + public GamsDemandOutput getDemandPc() { File workingDirectory = new File(ModelConfig.TEMP_DIR); workingDirectory.mkdir(); GAMSWorkspaceInfo wsInfo = new GAMSWorkspaceInfo(); @@ -46,8 +41,6 @@ public class GamsDemandOptimiser { GAMSJob gamsJob = ws.addJobFromFile(ModelConfig.DEMAND_GAMS_MODEL); GAMSOptions opt = ws.addOptions(); -// opt.setAllModelTypes("conopt"); - opt.defines("gdx_parameters", new File(ModelConfig.DEMAND_PARAM_FILE).getAbsolutePath()); opt.defines("gdx_prices_and_gdp", inDB.getName()); @@ -60,25 +53,49 @@ public class GamsDemandOptimiser { private void setupInDB(GAMSDatabase inDB) { GAMSParameter gdpPcP = inDB.addParameter("gdp_pc", 0); - LogWriter.println(String.format("gdp_pc:\t= %.5f", gdpPc)); + double gdpPc = inputData.getGdpPc(); + LogWriter.println(String.format("gdp_pc = %.5f", gdpPc)); setGamsParamValue(gdpPcP.addRecord(), gdpPc, 5); + GamsDemandOutput previousGamsDemands = inputData.getPreviousDemands(); + + GAMSParameter prevUP = inDB.addParameter("previousU", 0); + double previousUtility = previousGamsDemands == null ? 0 : previousGamsDemands.getUtility();//-16.3829624069452 + 4.3659621833299 * Math.log10(gdpPc); + LogWriter.println(String.format("previousU = %.5f, estimated = %.5f", previousUtility, -16.3829624069452 + 4.3659621833299 * Math.log10(gdpPc))); + setGamsParamValue(prevUP.addRecord(), previousUtility, 5); LogWriter.println("\nPrice"); - GAMSParameter priceP = inDB.addParameter("price", 1); - - for (Map.Entry<CommodityType, Double> entry : prices.entrySet()) { + GAMSParameter priceP = inDB.addParameter("price", 1); + GAMSParameter prevSubsP = inDB.addParameter("previousSubs", 1); + GAMSParameter prevDiscP = inDB.addParameter("previousDisc", 1); + + for (Map.Entry<CommodityType, Double> entry : inputData.getPrices().entrySet()) { CommodityType comm = entry.getKey(); Vector<String> v = new Vector<String>(); v.add(comm.getGamsName()); + double priceComm, prevSubs = 0.1, prevDisc = 0.1; + + if (comm == CommodityType.NONFOOD) { + prevSubs = 5; + prevDisc = 1; + priceComm = 45.376+53.036*gdpPc/inputData.getUsaGdpPc(); + } + else + priceComm = entry.getValue() * 1000 / comm.getkcalPerT()*2000*365; //price per calorie of commodity x per year assuming 2000 kcal a day for whole year - double priceComm; - if (comm == CommodityType.NONFOOD) - priceComm = 45.376+53.036*gdpPc/usaGdpPc; - else - priceComm = entry.getValue() * 1000 / comm.getkcalPerT()*2000*365; //price per calorie of commodity x per year assuming 2000 kcal a day for whole year - - LogWriter.println(String.format("%14s: price= %.4f", comm.getGamsName(), priceComm)); + if (previousGamsDemands != null) { + GamsCommodityDemand demand = previousGamsDemands.getGamsDemands(comm); + if (demand == null) + LogWriter.printlnError("Null GamsCommodityDemand for " + comm); + else { + prevSubs = demand.getSubsistence(); + prevDisc = demand.getDiscretionary(); + } + } + + LogWriter.println(String.format("%14s: price=%.4f, previousSubs=%.4f, previousDisc=%.4f", comm.getGamsName(), priceComm, prevSubs, prevDisc)); setGamsParamValue(priceP.addRecord(v), priceComm, 4); + setGamsParamValue(prevSubsP.addRecord(v), prevSubs, 4); + setGamsParamValue(prevDiscP.addRecord(v), prevDisc, 4); } } @@ -88,36 +105,43 @@ public class GamsDemandOptimiser { return dOut; } - private Map<CommodityType, Double> handleResults(GAMSDatabase outDB) { + private GamsDemandOutput handleResults(GAMSDatabase outDB) { int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue(); - LogWriter.println(String.format("\nDemamd %s: Modelstatus %s, Solvestatus %s", country, + LogWriter.println(String.format("\nDemamd %s: Modelstatus %s, Solvestatus %s", inputData.getCountry(), GAMSGlobals.ModelStat.lookup( modelStatus ), GAMSGlobals.SolveStat.lookup((int) outDB.getParameter("ss").findRecord().getValue()) )); - - GAMSParameter parmProd = outDB.getParameter("totalDemand"); - Map<CommodityType, Double> demandMap = new HashMap<CommodityType, Double>(); + GAMSVariable varU = outDB.getVariable("u"); + double utility = varU.getFirstRecord().getLevel(); + LogWriter.println(String.format("u = %.4f", utility)); + + GAMSVariable varSubs = outDB.getVariable("SubsistenceC"); + GAMSVariable varDisc = outDB.getVariable("DiscretionaryC"); + + HashSet<GamsCommodityDemand> demandMap = new HashSet<GamsCommodityDemand>(); - for (GAMSParameterRecord rec : parmProd) { + for (GAMSVariableRecord rec : varSubs) { String commodityName = rec.getKeys()[0]; CommodityType commodity = CommodityType.getForGamsName(commodityName, true); + if (commodity == null) LogWriter.println(String.format("Can't find commodity from Gams demand, so ignoring: " + commodityName)); else { - //gams is calculating demand in number of 2000 kcal servings per day so * by 2000 and * 365 to get kcal per year - double demandGams = rec.getValue(); - + double subsGams = rec.getLevel(); + double discGams = varDisc.findRecord(commodityName).getLevel(); + if (commodity == CommodityType.NONFOOD) { // we don't want to consider non-food, so not added to demandMap - LogWriter.println(String.format("%14s: demand(gams)= %.3f", commodityName, demandGams)); + LogWriter.println(String.format("%14s: subs=%.3f, disc=%.3f", commodityName, subsGams, discGams)); } - else { - double demandPc = rec.getValue()*2000*365*1/commodity.getkcalPerT(); - LogWriter.println(String.format("%14s: demand(gams)= %.3f, demand(kcal)=%.1f, demand(plum)= %.3f", commodityName, demandGams, demandGams*2000, demandPc)); - demandMap.put(commodity, demandPc); + else { //gams is calculating demand in number of 2000 kcal servings per day so * by 2000 and * 365 to get kcal per year + GamsCommodityDemand demand = new GamsCommodityDemand(commodity, subsGams, discGams); + + LogWriter.println(String.format("%14s: subs=%.3f, disc=%.3f, demand(kcal)=%.1f, demand(plum)= %.3f", commodityName, subsGams, discGams, demand.getKcalTotal(), demand.getPlumDemand())); + demandMap.add(demand); } } } - return demandMap; + return new GamsDemandOutput(demandMap, utility); } } diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOutput.java b/src/ac/ed/lurg/country/gams/GamsDemandOutput.java new file mode 100644 index 00000000..c8f12785 --- /dev/null +++ b/src/ac/ed/lurg/country/gams/GamsDemandOutput.java @@ -0,0 +1,38 @@ +package ac.ed.lurg.country.gams; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import ac.ed.lurg.types.CommodityType; + +public class GamsDemandOutput { + public Collection<GamsCommodityDemand> demands; + public double utility; + + public GamsDemandOutput(Collection<GamsCommodityDemand> demands, double utility) { + this.demands = demands; + this.utility = utility; + } + + public Map<CommodityType, Double> getPlumDemands() { + Map<CommodityType, Double> plumDemands = new HashMap<CommodityType, Double>(); + + for (GamsCommodityDemand demand : demands) + plumDemands.put(demand.getCommodity(), demand.getPlumDemand()); + + return plumDemands; + } + + public GamsCommodityDemand getGamsDemands(CommodityType comm) { + for (GamsCommodityDemand demand : demands) + if (demand.getCommodity() == comm) + return demand; + + return null; + } + + public double getUtility() { + return utility; + } +} diff --git a/src/ac/ed/lurg/demand/ElasticDemandManager.java b/src/ac/ed/lurg/demand/ElasticDemandManager.java index 5c63ca71..4171d3e7 100644 --- a/src/ac/ed/lurg/demand/ElasticDemandManager.java +++ b/src/ac/ed/lurg/demand/ElasticDemandManager.java @@ -6,12 +6,15 @@ import java.util.Map; import ac.ed.lurg.ModelConfig; import ac.ed.lurg.country.CompositeCountryManager; import ac.ed.lurg.country.SingleCountry; +import ac.ed.lurg.country.gams.GamsDemandInput; import ac.ed.lurg.country.gams.GamsDemandOptimiser; +import ac.ed.lurg.country.gams.GamsDemandOutput; import ac.ed.lurg.types.CommodityType; public class ElasticDemandManager extends AbstractSSPDemandManager { - protected Map<SingleCountry, Map<CommodityType, Double>> baseCpcCache = new HashMap<SingleCountry, Map<CommodityType, Double>>(); + private Map<SingleCountry, Map<CommodityType, Double>> baseCpcCache = new HashMap<SingleCountry, Map<CommodityType, Double>>(); + private Map<SingleCountry, GamsDemandOutput> previousGamsDemands = new HashMap<SingleCountry, GamsDemandOutput>(); public ElasticDemandManager(String ssp_scenario, BaseConsumpManager baseConsumpManager, CompositeCountryManager compositeCountryManager) { super(ssp_scenario, baseConsumpManager, compositeCountryManager); @@ -20,8 +23,12 @@ public class ElasticDemandManager extends AbstractSSPDemandManager { @Override Map<CommodityType, Double> getFoodDemandMap(SingleCountry c, double gdpPc, double population, Map<CommodityType, Double> prices, double usaGdpPc) { + GamsDemandInput inputData = new GamsDemandInput(c, gdpPc, prices, usaGdpPc, previousGamsDemands.get(c)); + // Do the projection - Map<CommodityType, Double> foodPc = new GamsDemandOptimiser(c, gdpPc, prices, usaGdpPc).getDemandPc(); + GamsDemandOutput gamsOutput = new GamsDemandOptimiser(inputData).getDemandPc(); + previousGamsDemands.put(c, gamsOutput); + Map<CommodityType, Double> foodPc = gamsOutput.getPlumDemands(); Map<CommodityType, Double> foodDemands = new HashMap<CommodityType, Double>(); SspData baseSspData = sspManager.get(ssp_scenario, ModelConfig.BASE_YEAR, c); -- GitLab