diff --git a/hindcast/hind_config.properties b/hindcast/hind_config.properties index f61c966e2daf0af226828556001de519e7fb6e47..26d3f0711130e7ac5b5a8c25f70011686c69d4e7 100644 --- a/hindcast/hind_config.properties +++ b/hindcast/hind_config.properties @@ -2,13 +2,12 @@ BASE_DIR=./hindcast INITAL_LAND_COVER_FILENAME=netfract_hurtt_1990.txt BASE_YEAR=1990 SSP_SCENARIO=HINDCAST -YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/IPSL/LPJG_PLUM_expt1.1_1966-2005_ipsl_lessIO_forED +YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/19Jan2017/LPJG_PLUM_expt1.1_1971-2005_forED +#YIELD_DIR=/Users/peteralexander/Documents/LURG/LPJ/IPSL/LPJG_PLUM_expt1.1_1966-2005_ipsl_lessIO_forED # irritatingly the gams file is also found under the BASE_DIR, and don't want to duplicate so need to specify exactly GAMS_MODEL=./GAMS/IntExtOpt.gms - - IS_CALIBRATION_RUN = false END_TIMESTEP=20 diff --git a/src/ac/ed/lurg/ModelConfig.java b/src/ac/ed/lurg/ModelConfig.java index 9dc548c35d756d5691a0e3552008f37c2f7040b2..db28705226a49965915c5e38b989ee9b361a68d6 100644 --- a/src/ac/ed/lurg/ModelConfig.java +++ b/src/ac/ed/lurg/ModelConfig.java @@ -25,7 +25,7 @@ public class ModelConfig { } } - public static String getSetupDetails() { + public static String getSetupDetails() { String buildVerion = System.getProperty("BUILDVER"); StringBuffer sb = new StringBuffer("Build version: " + buildVerion + "\n"); @@ -206,7 +206,7 @@ public class ModelConfig { public static final double DOMESTIC_PRICE_MARKUP = getDoubleProperty("DOMESTIC_PRICE_MARKUP", 2.0); public static final double TRANSPORT_LOSSES = getDoubleProperty("TRANSPORT_LOSSES", 0.05); // in international trade - public static final double TRANSPORT_COST = getDoubleProperty("TRANSPORT_COST", 0.1); // 100 $/t see Wheat Transportation Profile - USDA + public static final double TRANSPORT_COST = getDoubleProperty("TRANSPORT_COST", 0.2); // 100 $/t see Wheat Transportation Profile - USDA public static final double TRADE_BARRIER_FACTOR_DEFAULT = getDoubleProperty("TRADE_BARRIER_FACTOR_DEFAULT", 0.4); // price factor in international trade, transport cost and real trade barriers public static final double TRADE_BARRIER_ADJ = getDoubleProperty("TRADE_BARRIER_ADJ", 1.0); public static final boolean ACTIVE_TRADE_BARRIERS = getBooleanProperty("ACTIVE_TRADE_BARRIERS", false); // if set to true read in barrier information from file, otherwise use default as above diff --git a/src/ac/ed/lurg/ModelMain.java b/src/ac/ed/lurg/ModelMain.java index 961d9d404fd5095d147f287e2fa0f53b9c28fb69..a1af2620d2dd97ca053eafa96eed7212b8b1b063 100644 --- a/src/ac/ed/lurg/ModelMain.java +++ b/src/ac/ed/lurg/ModelMain.java @@ -42,7 +42,6 @@ import ac.ed.lurg.types.CommodityType; import ac.ed.lurg.types.CropToDoubleMap; import ac.ed.lurg.types.CropType; import ac.ed.lurg.types.LandCoverType; -import ac.ed.lurg.types.ModelFitType; import ac.ed.lurg.utils.LogWriter; import ac.ed.lurg.yield.LPJYieldResponseMapReader; import ac.ed.lurg.yield.YieldRaster; diff --git a/src/ac/ed/lurg/utils/LogWriter.java b/src/ac/ed/lurg/utils/LogWriter.java index 8403e1b34a359d47ba192737edcaff49b65da7d1..e754cf136d0da836dd53b353c3ffa31492928d08 100644 --- a/src/ac/ed/lurg/utils/LogWriter.java +++ b/src/ac/ed/lurg/utils/LogWriter.java @@ -43,17 +43,23 @@ public class LogWriter { private LogWriter(String outputFileName) { try { - logFile = new PrintWriter(new BufferedWriter(new FileWriter(outputFileName,false))); + File f = new File(outputFileName); + if(f.exists()) + logFile = new PrintWriter(new BufferedWriter(new FileWriter(outputFileName,false))); + else + System.err.println("LogWriter: outputFileName: " + outputFileName + " not found. Perhaps not set config file properly"); } catch (IOException e) { - LogWriter.print(e); + System.err.print(e); } } private void print(String s, PrintStream stream, boolean newLine) { - logFile.write(s); - if (newLine) logFile.write(System.lineSeparator()); - logFile.flush(); + if (logFile != null) { + logFile.write(s); + if (newLine) logFile.write(System.lineSeparator()); + logFile.flush(); + } if (!ModelConfig.SUPPRESS_STD_OUTPUT) { stream.print(s); diff --git a/src/ac/ed/lurg/utils/cluster/CentriodPoint.java b/src/ac/ed/lurg/utils/cluster/CentriodPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..22a1e1227ecceb185f04d223fe1fc022d2178007 --- /dev/null +++ b/src/ac/ed/lurg/utils/cluster/CentriodPoint.java @@ -0,0 +1,29 @@ +package ac.ed.lurg.utils.cluster; + +import java.util.Collection; +import java.util.Map; + +public class CentriodPoint implements ClusteringPoint { + + private Map<String, Double> valueMap; + + public CentriodPoint(Map<String, Double> valueMap) { + this.valueMap = valueMap; + } + + public double getClusteringValue(String key) { + return valueMap.get(key); + } + + public Collection<String> getAllClusteringKeys() { + return valueMap.keySet(); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (Map.Entry<String, Double> e : valueMap.entrySet()) { + sb.append(e.getKey() + "=" + e.getValue() + " "); + } + return sb.toString(); + } +} diff --git a/src/ac/ed/lurg/utils/cluster/Cluster.java b/src/ac/ed/lurg/utils/cluster/Cluster.java new file mode 100644 index 0000000000000000000000000000000000000000..91293201851297a896d7915e0e922b8d3fe7d8ea --- /dev/null +++ b/src/ac/ed/lurg/utils/cluster/Cluster.java @@ -0,0 +1,68 @@ +package ac.ed.lurg.utils.cluster; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +public class Cluster { + + private Collection<ClusteringPoint> points = new HashSet<ClusteringPoint>(); + private ClusteringPoint centroid; + + public Cluster(ClusteringPoint centroid) { + this.centroid = centroid; + } + + public Collection<ClusteringPoint> getPoints() { + return points; + } + + protected void addPoint(ClusteringPoint point) { + points.add(point); + } + + public ClusteringPoint getCentroid() { + return centroid; + } + + protected double calculateCentroid() { + int n_points = points.size(); + if(n_points == 0) return 0; + + Map<String, Double> centroidValues = new HashMap<String, Double>(); + + for(ClusteringPoint p : points) { + for (String key : p.getAllClusteringKeys()) { + Double soFar = centroidValues.get(key); + Double pointVal = p.getClusteringValue(key); + Double updated = soFar==null ? pointVal : pointVal + soFar; + centroidValues.put(key, updated); + } + } + + for (Map.Entry<String, Double> e : centroidValues.entrySet()) + centroidValues.put(e.getKey(), e.getValue()/n_points); + + ClusteringPoint updatedCentroid = new CentriodPoint(centroidValues); + double distanceMoved = distanceFromCentroid(updatedCentroid); + + centroid = updatedCentroid; + return distanceMoved; + } + + //Calculates the distance between two points. + protected double distanceFromCentroid(ClusteringPoint p) { + double squaredTotal=0; + for (String key : centroid.getAllClusteringKeys()) { + squaredTotal += Math.pow(p.getClusteringValue(key)-centroid.getClusteringValue(key), 2); + } + + return Math.sqrt(squaredTotal); + } + + + protected void clearPoints() { + points.clear(); + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/utils/cluster/ClusteringPoint.java b/src/ac/ed/lurg/utils/cluster/ClusteringPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..ca300134f7ca0a5734ebdddd0069cd3833111723 --- /dev/null +++ b/src/ac/ed/lurg/utils/cluster/ClusteringPoint.java @@ -0,0 +1,11 @@ +package ac.ed.lurg.utils.cluster; + +import java.util.Collection; + +/** Interface that give information used in clustering */ +public interface ClusteringPoint { + + public double getClusteringValue(String key); + public Collection<String> getAllClusteringKeys(); + +} \ No newline at end of file diff --git a/src/ac/ed/lurg/utils/cluster/KMeans.java b/src/ac/ed/lurg/utils/cluster/KMeans.java new file mode 100644 index 0000000000000000000000000000000000000000..e49a52302e6da53a8af5c7847e6c64ad9055d450 --- /dev/null +++ b/src/ac/ed/lurg/utils/cluster/KMeans.java @@ -0,0 +1,131 @@ +package ac.ed.lurg.utils.cluster; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; + +import ac.ed.lurg.utils.LogWriter; + +public class KMeans { + + private Collection<ClusteringPoint> points; + private Collection<Cluster> clusters; + + public KMeans(Collection<ClusteringPoint> points, int numClusters) { + this.points = points; + this.clusters = new HashSet<Cluster>(); + + Map<String, Double> minValueMap = new HashMap<String, Double>(); + Map<String, Double> maxValueMap = new HashMap<String, Double>(); + + for (ClusteringPoint p : points) { + for (String key : p.getAllClusteringKeys()) { + double currentVal = p.getClusteringValue(key); + Double minV = minValueMap.get(key); + Double maxV = maxValueMap.get(key); + double minSoFar = minV==null ? Double.POSITIVE_INFINITY : minV; + double maxSoFar = maxV==null ? Double.NEGATIVE_INFINITY : maxV; + + if (currentVal < minSoFar) + minValueMap.put(key, currentVal); + + if (currentVal > maxSoFar) + maxValueMap.put(key, currentVal); + } + } + + Random r = new Random(); + double min, max, rand, v; + //Create Clusters, with random centroids + for (int i = 0; i < numClusters; i++) { + + Map<String, Double> randomCentroid = new HashMap<String, Double>(); + + for (Map.Entry<String, Double> e : minValueMap.entrySet()) { + min = e.getValue(); + max = maxValueMap.get(e.getKey()); + rand = r.nextDouble(); + v = min + (max - min) * rand; + randomCentroid.put(e.getKey(), v); + } + + ClusteringPoint p = new CentriodPoint(randomCentroid); + LogWriter.println("Creating cluster at " + p); + Cluster cluster = new Cluster(p); + clusters.add(cluster); + } + } + + protected void printClusters() { + int i=0; + for (Cluster c : clusters) { + i++; + LogWriter.println("[Cluster: " + i+"]"); + LogWriter.println("[Centroid: " + c.getCentroid() + "]"); + LogWriter.println("[Points:"); + for(ClusteringPoint p : c.getPoints()) + LogWriter.println(p.toString()); + + LogWriter.println("]\n"); + } + } + + public double calculateClusters(int maxIterations, double tolerance) { + int iteration = 0; + long startTime = System.currentTimeMillis(); + + while(true) { + iteration++; + double distance = 0; + + //Assign points to the closer cluster + assignCluster(); + + //Calculate new centroids, and total distance between new and old centroids + for(Cluster c : clusters) + distance += c.calculateCentroid(); + + LogWriter.println("#################"); + LogWriter.println("Iteration: " + iteration); + LogWriter.println("Centroid distances: " + distance); + printClusters(); + + if(distance <= tolerance || iteration > maxIterations) { + LogWriter.println("Finishing calculateClusters: Iteration " + iteration + ", centroid distances: " + distance); + LogWriter.println(" Took " + (System.currentTimeMillis() - startTime) + " ms to run"); + return distance; + } + } + } + + public Collection<Cluster> getClusters() { + return clusters; + } + + private void clearPointsFromAllClusters() { + for(Cluster cluster : clusters) { + cluster.clearPoints(); + } + } + + private void assignCluster() { + clearPointsFromAllClusters(); + + for(ClusteringPoint point : points) { + double min = Double.MAX_VALUE; + Cluster cluster = null; + double distance = 0.0; + + for(Cluster c : clusters) { + distance = c.distanceFromCentroid(point); + if(distance < min){ + min = distance; + cluster = c; + } + } + cluster.addPoint(point); + } + } +} \ No newline at end of file diff --git a/src/ac/ed/lurg/utils/cluster/KMeansTest.java b/src/ac/ed/lurg/utils/cluster/KMeansTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cbbd1cef11def6af9813b9fbd150258738038434 --- /dev/null +++ b/src/ac/ed/lurg/utils/cluster/KMeansTest.java @@ -0,0 +1,56 @@ +package ac.ed.lurg.utils.cluster; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +public class KMeansTest { + + //Number of Clusters. This metric should be related to the number of points + private int NUM_CLUSTERS = 3; + //Number of Points + private int NUM_POINTS = 10; + //Min and Max X and Y + private static final int MIN_COORDINATE = 0; + private static final int MAX_COORDINATE = 10; + private int MAX_ITERATIONS = 20; + + public static void main(String[] args) { + + KMeansTest kmeansTest = new KMeansTest(); + kmeansTest.doIt(); + } + + public void doIt() { + KMeans kmeans = new KMeans(createRandomPoints(MIN_COORDINATE,MAX_COORDINATE,NUM_POINTS), NUM_CLUSTERS); + kmeans.printClusters(); + kmeans.calculateClusters(MAX_ITERATIONS, 0.6); + } + + //Creates random point + protected static ClusteringPoint createRandomPoint(int min, int max) { + Random r = new Random(); + double x = min + (max - min) * r.nextDouble(); + double y = min + (max - min) * r.nextDouble(); + double z = min + (max - min) * r.nextDouble(); + + Map<String, Double> values = new HashMap<String, Double>(); + values.put("X", x); + values.put("Y", y); + values.put("Z", z); + + ClusteringPoint p = new CentriodPoint(values); + return p; + } + + protected static List<ClusteringPoint> createRandomPoints(int min, int max, int number) { + List<ClusteringPoint> points = new ArrayList<ClusteringPoint>(number); + for(int i = 0; i < number; i++) { + points.add(createRandomPoint(min,max)); + } + return points; + } + +}