diff --git a/GAMS/elasticDemand.gms b/GAMS/elasticDemand.gms old mode 100644 new mode 100755 index ca1a406f9906b5924b57abf69527a2514d87f80c..9d62dd08e2e6a67fa59ee9abce4383e66845ed09 --- a/GAMS/elasticDemand.gms +++ b/GAMS/elasticDemand.gms @@ -31,14 +31,16 @@ POSITIVE VARIABLE PARAMETER p(i) Price, m GDP per capita + maxIncomePropFoodSpend Maximum proportion of income spent on food, + desiredConsumpFactor Affordable consumption used when below minimum subsistence level ; $gdxin %gdx_prices_and_gdp% *$gdxin "../../GAMS/PricesAndGdp.gdx" -$load p=price, m=gdp_pc, previousU, previousSubs, previousDisc +$load maxIncomePropFoodSpend, p=price, m=gdp_pc, previousU, previousSubs, previousDisc $gdxin -display p, m, alpha, beta, kappa, delta, tau, omega; +display maxIncomePropFoodSpend, p, m, alpha, beta, kappa, delta, tau, omega; w.up(j) = 1; @@ -72,23 +74,27 @@ model MAIDADS_Sim "MAIDADS model for simulation" / MAIDADS_Sim.optfile = 1; option cns=path; -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; - -display u.l, DiscretionaryC.l, SubsistenceC.l; - -solve MAIDADS_Sim using cns; +desiredConsumpFactor = m * maxIncomePropFoodSpend / sum(i, p(i)*delta(i)); +display desiredConsumpFactor; Scalar ms 'model status', ss 'solve status'; -ms=MAIDADS_Sim.modelstat; -ss=MAIDADS_Sim.solvestat; - -display DiscretionaryC.l, u.l; - -*parameter disc(i); -*disc(i) = [m-sum(j,p(j)*SubsistenceC(j))]; -*display disc; +u = previousU; + +If (desiredConsumpFactor > 1.0, + 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; + desiredConsumpFactor = 1; + + solve MAIDADS_Sim using cns; + + ms=MAIDADS_Sim.modelstat; + ss=MAIDADS_Sim.solvestat; + +else + SubsistenceC(i) = delta(i) * desiredConsumpFactor; +); + +display SubsistenceC.l, DiscretionaryC.l; diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java old mode 100644 new mode 100755 index 3f5a651068ae9672953bd23015e858e3e692e745..00c0c10288b2bd88c9b03c5d25d53fb4e4570d03 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -190,8 +190,8 @@ public class ModelConfig { public static final double CALIB_FACTOR_RICE = getDoubleProperty("CALIB_FACTOR_RICE", 0.972); public static final double CALIB_FACTOR_OILCROPS = getDoubleProperty("CALIB_FACTOR_OILCROPS", 0.578); public static final double CALIB_FACTOR_PULSES = getDoubleProperty("CALIB_FACTOR_PULSES", 0.686); - public static final double CALIB_FACTOR_STARCHY_ROOTS = getDoubleProperty("CALIB_FACTOR_STARCHY_ROOTS", 3.526); - public static final double CALIB_FACTOR_FRUITVEG = getDoubleProperty("CALIB_FACTOR_FRUITVEG", 4.560); + public static final double CALIB_FACTOR_STARCHY_ROOTS = getDoubleProperty("CALIB_FACTOR_STARCHY_ROOTS",4.560); + public static final double CALIB_FACTOR_FRUITVEG = getDoubleProperty("CALIB_FACTOR_FRUITVEG",3.526); public static final double CALIB_FACTOR_SUGAR = getDoubleProperty("CALIB_FACTOR_SUGAR", 11.909); // These are production prices in PLUM style feed equivalent terms @@ -289,6 +289,7 @@ public class ModelConfig { public static final double ANNUAL_MAX_DEMAND_FRACT_CHANGE = getDoubleProperty("ANNUAL_MAX_DEMAND_FRACT_CHANGE", 0.0); public static final boolean LIMIT_DEMAND_FRACTION = getBooleanProperty("LIMIT_DEMAND_FRACTION", true); public static final int DEMAND_FRACT_CHANGE_START_STEP = getIntProperty("DEMAND_FRACT_CHANGE_START_STEP", 0); + public static final double MAX_INCOME_PROPORTION_FOOD_SPEND = getDoubleProperty("MAX_INCOME_PROPORTION_FOOD_SPEND", 0.7); public static final double PASTURE_HARVEST_FRACTION = getDoubleProperty("PASTURE_HARVEST_FRACTION", 0.5); public static final double ANIMAL_FEED_FROM_OTHER_SOURCES_RATE = getDoubleProperty("ANIMAL_FEED_FROM_OTHER_SOURCES_RATE", 0.127); // animal nutrition coming from sources other crops modelled diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java old mode 100644 new mode 100755 index ef34748595f336a5562fce28fc4969df15e11d82..0ee9ca27fc7fefe2844467e4b1aa83d174851c41 --- a/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java +++ b/src/ac/ed/lurg/country/gams/GamsDemandOptimiser.java @@ -1,6 +1,8 @@ package ac.ed.lurg.country.gams; import java.io.File; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Vector; @@ -62,6 +64,9 @@ public class GamsDemandOptimiser { 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); + + GAMSParameter maxIncomePropFoodSpendP = inDB.addParameter("maxIncomePropFoodSpend", 0); + setGamsParamValue(maxIncomePropFoodSpendP.addRecord(), ModelConfig.MAX_INCOME_PROPORTION_FOOD_SPEND, 4); LogWriter.println("\nPrice"); GAMSParameter priceP = inDB.addParameter("price", 1); @@ -104,8 +109,8 @@ public class GamsDemandOptimiser { private GamsDemandOutput handleResults(GAMSDatabase outDB) { int modelStatus = (int) outDB.getParameter("ms").findRecord().getValue(); String status = GAMSGlobals.ModelStat.lookup(modelStatus).toString(); - LogWriter.println(String.format("\nDemamd %s %d: Modelstatus %s, Solvestatus %s", inputData.getCountry(), inputData.getYear(), - status, GAMSGlobals.SolveStat.lookup((int) outDB.getParameter("ss").findRecord().getValue()) )); + LogWriter.println(String.format("\nDemamd %s: Modelstatus (%d) %s, Solvestatus %s", inputData.getCountry(), + modelStatus, status, GAMSGlobals.SolveStat.lookup((int) outDB.getParameter("ss").findRecord().getValue()) )); GAMSVariable varU = outDB.getVariable("u"); double utility = varU.getFirstRecord().getLevel(); @@ -115,6 +120,7 @@ public class GamsDemandOptimiser { GAMSVariable varDisc = outDB.getVariable("DiscretionaryC"); HashSet<GamsCommodityDemand> demandMap = new HashSet<GamsCommodityDemand>(); + Collection<CommodityType> unhandledComms = new ArrayList<CommodityType>(CommodityType.getAllFoodItems()); for (GAMSVariableRecord rec : varSubs) { String commodityName = rec.getKeys()[0]; @@ -124,13 +130,23 @@ public class GamsDemandOptimiser { LogWriter.println(String.format("Can't find commodity from Gams demand, so ignoring: " + commodityName)); else { double subsGams = rec.getLevel(); - double discGams = varDisc.findRecord(commodityName).getLevel(); + double discGams = modelStatus==0 ? 0 : varDisc.findRecord(commodityName).getLevel(); //modelStatus==0 is optimiser not run, i.e. too low GDP GamsCommodityDemand demand = new GamsCommodityDemand(commodity, subsGams, discGams); LogWriter.println(demand.toString()); demandMap.add(demand); + unhandledComms.remove(commodity); } } - return new GamsDemandOutput(status, demandMap, utility); + for (CommodityType commodity : unhandledComms) { + LogWriter.println(commodity + " not found in Gams output so adding with zero demand"); + demandMap.add(new GamsCommodityDemand(commodity, 0, 0)); + } + + GAMSParameter parConsumpFact = outDB.getParameter("desiredConsumpFactor"); + double desiredConsumpFactor = parConsumpFact.getFirstRecord().getValue(); + LogWriter.println(String.format("desiredConsumpFactor=%.4f", desiredConsumpFactor)); + + return new GamsDemandOutput(status, demandMap, utility, desiredConsumpFactor); } } diff --git a/src/ac/ed/lurg/country/gams/GamsDemandOutput.java b/src/ac/ed/lurg/country/gams/GamsDemandOutput.java index 9fb461082b8bf15a80a68c1d11e450fedb4ff661..450e9866c8f926fe5b08d5c04888561e6bd1664c 100644 --- a/src/ac/ed/lurg/country/gams/GamsDemandOutput.java +++ b/src/ac/ed/lurg/country/gams/GamsDemandOutput.java @@ -11,11 +11,13 @@ public class GamsDemandOutput { private Collection<GamsCommodityDemand> demands; private double utility; + private double desiredConsumpFactor; - public GamsDemandOutput(String status, Collection<GamsCommodityDemand> demands, double utility) { + public GamsDemandOutput(String status, Collection<GamsCommodityDemand> demands, double utility, double desiredConsumpFactor) { this.status = status; this.demands = demands; this.utility = utility; + this.desiredConsumpFactor = desiredConsumpFactor; } public Map<CommodityType, Double> getPlumDemands() { @@ -38,6 +40,9 @@ public class GamsDemandOutput { public double getUtility() { return utility; } + public double getHungerFactor() { + return 1-desiredConsumpFactor; + } public String getStatus() { return status; } diff --git a/src/ac/ed/lurg/demand/ElasticDemandManager.java b/src/ac/ed/lurg/demand/ElasticDemandManager.java old mode 100644 new mode 100755 index e0d466cc8d361ec98d266eb281ef11f40f9e812f..90560a6b48272cf81decfe42a9de79c9290da6b3 --- a/src/ac/ed/lurg/demand/ElasticDemandManager.java +++ b/src/ac/ed/lurg/demand/ElasticDemandManager.java @@ -44,7 +44,7 @@ public class ElasticDemandManager extends AbstractSSPDemandManager { GamsDemandOutput gamsOutput = null; for (int i = 1; i < 50; ++i) { gamsOutput = new GamsDemandOptimiser(inputData).getDemandPc(); - if (gamsOutput.getStatus().equals("SOLVED")) + if (gamsOutput.getStatus().equals("SOLVED") || gamsOutput.getStatus().equals("UNDEFINED_STAT")) break; else { LogWriter.printlnError(i + ": Problem solving " + c + ", " + year + " got " + gamsOutput.getStatus()); @@ -88,7 +88,7 @@ public class ElasticDemandManager extends AbstractSSPDemandManager { for (CommodityType commodity : CommodityType.values()) sbHeader.append(",price_" + commodity.getGamsName()); - sbHeader.append(",status,utility"); + sbHeader.append(",status,utility,hungerFactor"); for (CommodityType commodity : CommodityType.values()) sbHeader.append(",gamssubs_" + commodity.getGamsName()); @@ -110,7 +110,7 @@ public class ElasticDemandManager extends AbstractSSPDemandManager { for (CommodityType commodity : CommodityType.values()) sbData.append(String.format(",%.4f", inputData.getPrices().get(commodity))); - sbData.append(String.format(",%s,%.6f", gamsOutput.getStatus(), gamsOutput.getUtility())); + sbData.append(String.format(",%s,%.6f,%.6f", gamsOutput.getStatus(), gamsOutput.getUtility(),gamsOutput.getHungerFactor())); for (CommodityType commodity : CommodityType.values()) sbData.append(String.format(",%.4f", gamsOutput.getGamsDemands(commodity).getSubsistence())); diff --git a/src/ac/ed/lurg/types/CommodityType.java b/src/ac/ed/lurg/types/CommodityType.java index 378878150ba40e0910c61c29bc55df740946e0a6..29ceb084991dd16094cd0c51f5e24efe3c910546 100644 --- a/src/ac/ed/lurg/types/CommodityType.java +++ b/src/ac/ed/lurg/types/CommodityType.java @@ -11,8 +11,8 @@ import ac.ed.lurg.utils.LogWriter; public enum CommodityType { - CEREALS("Cereals", "cereals", false, new CropType[]{CropType.WHEAT, CropType.MAIZE, CropType.RICE}, new Double[]{0.4, 0.3, 0.3}, 2741847.3, ModelConfig.CEREALS_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_CEREALS), - OILCROPSPULSES("OilcropsPulses", "oilcropspulses", false, new CropType[]{CropType.OILCROPS, CropType.PULSES}, new Double[]{0.5, 0.5}, 1864622.3, ModelConfig.OILCROPSPULSES_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_OILCROPS_PULSES), + CEREALS("Cereals", "cereals", false, new CropType[]{CropType.WHEAT, CropType.MAIZE, CropType.RICE}, new Double[]{0.385, 0.171, 0.444}, 2741847.3, ModelConfig.CEREALS_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_CEREALS), + OILCROPSPULSES("OilcropsPulses", "oilcropspulses", false, new CropType[]{CropType.OILCROPS, CropType.PULSES}, new Double[]{0.815, 0.185}, 1864622.3, ModelConfig.OILCROPSPULSES_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_OILCROPS_PULSES), STARCHY_ROOTS("Starchy Roots", "starchyRoots", false, new CropType[]{CropType.STARCHY_ROOTS}, new Double[]{1.0}, 819065.4, ModelConfig.STARCHY_ROOTS_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_STARCHYROOTS), MONOGASTRICS("Monogastrics", "monogastrics", true, new CropType[]{CropType.MONOGASTRICS}, new Double[]{1.0}, 455874.3, Double.NaN, ModelConfig.INITAL_DEMAND_PRICE_MONOGASTRICS), RUMINANTS("Ruminants", "ruminants", true, new CropType[]{CropType.RUMINANTS}, new Double[]{1.0}, 236969.8, Double.NaN, ModelConfig.INITAL_DEMAND_PRICE_RUMINANTS),