From f313e8d6ea282dea4e736433ee08904a2863a8d3 Mon Sep 17 00:00:00 2001 From: Peter Alexander <peter@blackhillock.co.uk> Date: Thu, 14 Mar 2019 08:16:36 +0000 Subject: [PATCH] Use single price markup factor per commodity between demand and production prices --- src/ac/ed/lurg/InternationalMarket.java | 20 ++-------- .../ed/lurg/country/AbstractCountryAgent.java | 40 +++++++------------ src/ac/ed/lurg/types/CommodityType.java | 37 +++++++++++------ src/ac/ed/lurg/types/CropType.java | 34 +++++++++------- 4 files changed, 63 insertions(+), 68 deletions(-) diff --git a/src/ac/ed/lurg/InternationalMarket.java b/src/ac/ed/lurg/InternationalMarket.java index c9cd1cbc..4504439a 100644 --- a/src/ac/ed/lurg/InternationalMarket.java +++ b/src/ac/ed/lurg/InternationalMarket.java @@ -17,25 +17,13 @@ import ac.ed.lurg.utils.LogWriter; public class InternationalMarket { - private Map<CropType, GlobalPrice> worldPrices; + private Map<CropType, GlobalPrice> worldPrices = new HashMap<CropType, GlobalPrice>(); private Map<CropType, Double> stockLevel; public InternationalMarket() { - // in first timestep we don't have this info, but ok as constrained to - // import/export specified amount, values based on - // http://www.indexmundi.com/commodities/ for Jun 2010 - worldPrices = new HashMap<CropType, GlobalPrice>(); - worldPrices.put(CropType.WHEAT, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_WHEAT)); - worldPrices.put(CropType.MAIZE, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_MAIZE)); - worldPrices.put(CropType.RICE, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_RICE)); - worldPrices.put(CropType.OILCROPS, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_OILCROPS)); - worldPrices.put(CropType.PULSES, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_PULSES)); - worldPrices.put(CropType.STARCHY_ROOTS, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_STARCHYROOTS)); - worldPrices.put(CropType.MONOGASTRICS, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_MONOGASTRICS)); // quantities is in feed equivalent term (0.4 is weighted average price per feed, and 0.5 accounts for mark-up for additional processing) - worldPrices.put(CropType.RUMINANTS, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_RUMINANTS)); // quantities is in feed equivalent term - worldPrices.put(CropType.ENERGY_CROPS, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_ENERGYCROPS)); - worldPrices.put(CropType.FRUITVEG, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_FRUITVEG)); - worldPrices.put(CropType.SUGAR, GlobalPrice.createInitial(ModelConfig.INITAL_PRICE_SUGAR)); + for (CropType crop : CropType.getImportedTypes()) + worldPrices.put(crop, GlobalPrice.createInitial(crop.getInitialPrice())); + stockLevel = getInitialStockLevels(); } diff --git a/src/ac/ed/lurg/country/AbstractCountryAgent.java b/src/ac/ed/lurg/country/AbstractCountryAgent.java index 89cb3ded..0f2bb225 100644 --- a/src/ac/ed/lurg/country/AbstractCountryAgent.java +++ b/src/ac/ed/lurg/country/AbstractCountryAgent.java @@ -1,6 +1,5 @@ package ac.ed.lurg.country; -import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -20,7 +19,6 @@ public abstract class AbstractCountryAgent { protected Map<CommodityType, Double> currentProjectedDemand; private Map<CropType, CountryPrice> currentCountryPrices; private Map<CommodityType, Map<CropType, Double>> baseDemandFact; - private Map<CommodityType, Double> priceMarkupFactors = new HashMap<CommodityType, Double>(); public AbstractCountryAgent(AbstractDemandManager demandManager,CompositeCountry country, Map<CropType, Double> tradeBarriers) { @@ -40,6 +38,7 @@ public abstract class AbstractCountryAgent { for (CropType c : CropType.getImportedTypes()) { GlobalPrice worldPrice = worldPrices.get(c); Double tb = tradeBarriers.get(c); + LogWriter.println(worldPrice + " " + c); CountryPrice prices = new CountryPrice(worldPrice.getCountryImportPrice(tb==null ? 0 : tb, timestep), worldPrice.getExportPrice()); countryPrices.put(c, prices); } @@ -62,34 +61,25 @@ public abstract class AbstractCountryAgent { Map<CommodityType, Double> prices = new HashMap<CommodityType, Double>(); for (CommodityType commodity : CommodityType.getAllFoodItems()) { - double commPricePlum = 0; - Collection<CropType> crops = commodity.getCropTypes(); + double commPricePlum = getCommPriceFromCropPrice(commodity); + double commPrice = commPricePlum * commodity.getPlumPriceToKcalPriceConversion(); //price per person per year commodity x per year assuming 2000 kcal a day + commPrice *= commodity.getPriceMarkupFactor(); // * priceMarkupFactor to rebase prices to those provide by G&G - for (CropType crop : crops) { - commPricePlum += getCropPrice(crop) * baseDemandFact.get(commodity).get(crop); // weight price by base demand of each cereal crop - } - - double commPrice = commPricePlum * 1000 / commodity.getkcalPerT() * 2000 * 365; //price per person per year commodity x per year assuming 2000 kcal a day - - double priceMarkupFactor; - if (timestep.isInitialTimestep()) { - double initialDemandPrice = commodity.getInitialPrice(); - priceMarkupFactor = initialDemandPrice / commPrice; - priceMarkupFactors.put(commodity, priceMarkupFactor); - } - else - priceMarkupFactor = priceMarkupFactors.get(commodity); - - prices.put(commodity, commPrice * priceMarkupFactor); // * priceMarkupFactor to rebase prices to those provide by G&G - LogWriter.println("Price for " + commodity.getGamsName() + " is " + commPrice * priceMarkupFactor + " after markup of " + priceMarkupFactor); + prices.put(commodity, commPrice); + LogWriter.println("Price for " + commodity.getGamsName() + " is " + commPrice); } return prices; } - - protected double getCropPrice(CropType crop) { - CountryPrice cropPrice = currentCountryPrices.get(crop); - return cropPrice.getImportPrice(); + + private double getCommPriceFromCropPrice(CommodityType commodity) { + double commPricePlum = 0; + Map<CropType, Double> demandFract = baseDemandFact.get(commodity); + + for (CropType crop : commodity.getCropTypes()) { + commPricePlum += currentCountryPrices.get(crop).getImportPrice() * demandFract.get(crop); // weight price by base demand of each cereal crop + } + return commPricePlum; } public Map<CommodityType, Double> getCurrentProjectedDemand() { diff --git a/src/ac/ed/lurg/types/CommodityType.java b/src/ac/ed/lurg/types/CommodityType.java index 0922347d..37887815 100644 --- a/src/ac/ed/lurg/types/CommodityType.java +++ b/src/ac/ed/lurg/types/CommodityType.java @@ -7,17 +7,18 @@ import java.util.HashSet; import java.util.Map; import ac.ed.lurg.ModelConfig; +import ac.ed.lurg.utils.LogWriter; public enum CommodityType { - CEREALS("Cereals", "cereals", false, new CropType[]{CropType.WHEAT, CropType.MAIZE, CropType.RICE},2741847.3, ModelConfig.CEREALS_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_CEREALS), - OILCROPSPULSES("OilcropsPulses", "oilcropspulses", false, new CropType[]{CropType.OILCROPS, CropType.PULSES},1864622.3, ModelConfig.OILCROPSPULSES_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_OILCROPS_PULSES), - STARCHY_ROOTS("Starchy Roots", "starchyRoots", false, new CropType[]{CropType.STARCHY_ROOTS},819065.4, ModelConfig.STARCHY_ROOTS_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_STARCHYROOTS), - MONOGASTRICS("Monogastrics", "monogastrics", true, new CropType[]{CropType.MONOGASTRICS}, 455874.3, Double.NaN, ModelConfig.INITAL_DEMAND_PRICE_MONOGASTRICS), - RUMINANTS("Ruminants", "ruminants", true, new CropType[]{CropType.RUMINANTS}, 236969.8, Double.NaN, ModelConfig.INITAL_DEMAND_PRICE_RUMINANTS), - FRUITVEG("FruitVeg", "fruitveg", false, new CropType[]{CropType.FRUITVEG},334355.8, ModelConfig.FRUITVEG_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_FRUITVEG), - SUGAR("Sugar", "sugar", false, new CropType[]{CropType.SUGAR},3417804.4, ModelConfig.SUGAR_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_SUGAR), - NONFOOD("Nonfood", "nonfood", false, new CropType[]{},Double.NaN, Double.NaN, Double.NaN); + 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), + 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), + FRUITVEG("FruitVeg", "fruitveg", false, new CropType[]{CropType.FRUITVEG}, new Double[]{1.0}, 334355.8, ModelConfig.FRUITVEG_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_FRUITVEG), + SUGAR("Sugar", "sugar", false, new CropType[]{CropType.SUGAR}, new Double[]{1.0}, 3417804.4, ModelConfig.SUGAR_SUB_PROPORTION, ModelConfig.INITAL_DEMAND_PRICE_SUGAR), + NONFOOD("Nonfood", "nonfood", false, new CropType[]{}, new Double[]{}, Double.NaN, Double.NaN, Double.NaN); private String faoName; private String gamsName; @@ -25,9 +26,9 @@ public enum CommodityType { private Collection<CropType> cropTypes; private double kcalPerT; //in feed equivalent for animal types private double meatSubstitutionProportion; - private double initialPrice; + private double priceMarkupFactor; - CommodityType (String faoName, String gamsName, boolean isAnimalProduct, CropType[] cropTypeMapping, double energyPerTon, + CommodityType (String faoName, String gamsName, boolean isAnimalProduct, CropType[] cropTypeMapping, Double[] defaultDemandFract, double energyPerTon, double meatSubstitutionProportion, double initialPrice) { this.faoName = faoName; this.gamsName = gamsName; @@ -35,7 +36,13 @@ public enum CommodityType { this.cropTypes = Arrays.asList(cropTypeMapping); this.kcalPerT = energyPerTon; this.meatSubstitutionProportion = meatSubstitutionProportion; - this.initialPrice = initialPrice; + + double prodPrice = 0; + for (int i=0; i<cropTypeMapping.length; i++) + prodPrice += cropTypeMapping[i].getInitialPrice() * defaultDemandFract[i]; + + priceMarkupFactor = initialPrice / (prodPrice * getPlumPriceToKcalPriceConversion()); + LogWriter.println("priceMarkupFactor for " + gamsName + " is " + priceMarkupFactor); } private static final Map<String, CommodityType> faoNameCache = new HashMap<String, CommodityType>(); @@ -97,7 +104,11 @@ public enum CommodityType { return cropTypes; } - public double getInitialPrice() { - return initialPrice; + public double getPriceMarkupFactor() { + return priceMarkupFactor; + } + + public double getPlumPriceToKcalPriceConversion() { + return 1000 / getkcalPerT() * 2000 * 365; } } \ No newline at end of file diff --git a/src/ac/ed/lurg/types/CropType.java b/src/ac/ed/lurg/types/CropType.java index 7d64a86a..ec0241d7 100644 --- a/src/ac/ed/lurg/types/CropType.java +++ b/src/ac/ed/lurg/types/CropType.java @@ -6,38 +6,41 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.Map; +import ac.ed.lurg.ModelConfig; import ac.ed.lurg.utils.LogWriter; public enum CropType { - WHEAT("WheatBarleyOats", "wheat", true, false, 9.4), - MAIZE("MaizeMilletSorghum", "maize", true, false, 5.1), - RICE("Rice (Paddy Equivalent)", "rice", true, false, 8.4), - OILCROPS("Oilcrops", "oilcrops", true, false, 4.4), - PULSES("Pulses", "pulses", true, false, 11.2), - STARCHY_ROOTS("Starchy Roots", "starchyRoots", true, false, 14.2), - ENERGY_CROPS("Energy crops", "energycrops", true, false, 5), - SETASIDE("setaside", "setaside", false, false, 0), - MONOGASTRICS("Monogastrics", "monogastrics", true, true, 3.1), - RUMINANTS("Ruminants", "ruminants", true, true, 2.2), - FRUITVEG("FruitVeg", "fruitveg", true, false, 8.8), - SUGAR("Sugar", "sugar", true, false, 0.1), - PASTURE("pasture", "pasture", false, false, 0); // confusing having a land cover and a crop type. Needed here for yields (but not used for cropland area fractions). + WHEAT("WheatBarleyOats", "wheat", true, false, 9.4, ModelConfig.INITAL_PRICE_WHEAT), + MAIZE("MaizeMilletSorghum", "maize", true, false, 5.1, ModelConfig.INITAL_PRICE_MAIZE), + RICE("Rice (Paddy Equivalent)", "rice", true, false, 8.4, ModelConfig.INITAL_PRICE_RICE), + OILCROPS("Oilcrops", "oilcrops", true, false, 4.4, ModelConfig.INITAL_PRICE_OILCROPS), + PULSES("Pulses", "pulses", true, false, 11.2, ModelConfig.INITAL_PRICE_PULSES), + STARCHY_ROOTS("Starchy Roots", "starchyRoots", true, false, 14.2, ModelConfig.INITAL_PRICE_STARCHYROOTS), + ENERGY_CROPS("Energy crops", "energycrops", true, false, 5, ModelConfig.INITAL_PRICE_ENERGYCROPS), + SETASIDE("setaside", "setaside", false, false, 0, 0), + MONOGASTRICS("Monogastrics", "monogastrics", true, true, 3.1, ModelConfig.INITAL_PRICE_MONOGASTRICS), + RUMINANTS("Ruminants", "ruminants", true, true, 2.2, ModelConfig.INITAL_PRICE_RUMINANTS), + FRUITVEG("FruitVeg", "fruitveg", true, false, 8.8, ModelConfig.INITAL_PRICE_FRUITVEG), + SUGAR("Sugar", "sugar", true, false, 0.1, ModelConfig.INITAL_PRICE_SUGAR), + PASTURE("pasture", "pasture", false, false, 0, 0); // confusing having a land cover and a crop type. Needed here for yields (but not used for cropland area fractions). private String faoName; private String gamsName; private boolean importedCrop; private boolean isMeat; private double seedAndWasteRate; + private double initialPrice; private static Collection<CropType> importedCrops; - private CropType (String faoName, String gamsName, boolean importedCrop, boolean isMeat, double seedAndWastePercent) { + private CropType (String faoName, String gamsName, boolean importedCrop, boolean isMeat, double seedAndWastePercent, double initialPrice) { this.faoName = faoName; this.gamsName = gamsName; this.importedCrop = importedCrop; this.isMeat = isMeat; this.seedAndWasteRate = seedAndWastePercent/100; + this.initialPrice = initialPrice; } public static Collection<CropType> getCropsLessPasture() { @@ -133,4 +136,7 @@ public enum CropType { return seedAndWasteRate; } + public double getInitialPrice() { + return initialPrice; + } } -- GitLab