diff --git a/.classpath b/.classpath index fd645472..fb2341ef 100644 --- a/.classpath +++ b/.classpath @@ -1,15 +1,16 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/config/plotting/gnuplot.properties b/config/plotting/gnuplot.properties index 75c59ee3..889b275c 100644 --- a/config/plotting/gnuplot.properties +++ b/config/plotting/gnuplot.properties @@ -1,5 +1,5 @@ ## GENERAL PLOT SETTINGS ############### -GNUPLOT_PATH = /usr/bin/gnuplot +GNUPLOT_PATH = C:\\Users\\Maurice\\gnuplot\\bin\\gnuplot.exe GNUPLOT_TERMINAL = png large GNUPLOT_EXTENSION = png GNUPLOT_DIR = null @@ -39,4 +39,4 @@ GNUPLOT_DEFAULT_PLOTSTYLE = linespoint GNUPLOT_DEFAULT_NVL_ORDER = ascending GNUPLOT_DEFAULT_NVL_ORDERBY = average -GNUPLOT_DEFAULT_DIST_PLOTTYPE = distANDcdf \ No newline at end of file +GNUPLOT_DEFAULT_DIST_PLOTTYPE = distANDcdf diff --git a/src/dna/graph/generators/traffic/CardinalDirection.java b/src/dna/graph/generators/traffic/CardinalDirection.java new file mode 100644 index 00000000..53c6b19e --- /dev/null +++ b/src/dna/graph/generators/traffic/CardinalDirection.java @@ -0,0 +1,5 @@ +package dna.graph.generators.traffic; + +public enum CardinalDirection { + NORTH, EAST,SOUTH,WEST +} diff --git a/src/dna/graph/generators/traffic/Crossroad.java b/src/dna/graph/generators/traffic/Crossroad.java new file mode 100644 index 00000000..887c1402 --- /dev/null +++ b/src/dna/graph/generators/traffic/Crossroad.java @@ -0,0 +1,132 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +public class Crossroad { + private HashMap inputWays; + private HashMap outputWays; + private HashMap> inputToOutput; + private HashMap outputToInput; + private int crossroadID; + private DB db; + + public Crossroad(int crossroadID, DB db){ + this.inputToOutput=new HashMap<>(); + this.crossroadID=crossroadID; + this.db=db; + this.outputToInput = new HashMap<>(); + } + /** + * speichert die übergebene HashMap von Einfahrtswegen + * @param newInputWays + * @return Setzen = true, Ersetzen = False + */ + public boolean setInputWays(HashMap newInputWays) { + boolean wasNull = inputWays==null; + inputWays=newInputWays; + return wasNull; + } + /** + * speichert die übergebene HashMap von Ausfahrtswegen + * @param newOutputWays + * @return Setzen = true, Ersetzen = False + */ + public boolean setOutputWays(HashMap newOutputWays) { + boolean wasNull = outputWays==null; + outputWays=newOutputWays; + return wasNull; + } + /** + * Verbindet einen Einfahrtsweg mit einem Ausfahrtsweg + * @param inDir CardinalDirection des Einfahrtsweges + * @param outDir CardinalDirection des Ausfahrtsweges + * @return Wert neu gesetzt = true, Wert bereits vorhanden = false + */ + public boolean setOutputWay(CardinalDirection inDir, CardinalDirection outDir){ + if(!inputToOutput.containsKey(inDir)){ + inputToOutput.put(inDir, new HashSet()); + } + return inputToOutput.get(inDir).add(outDir); + } + /** + * liefert den Identifier eines Weges + * @param direction, Himmelsrichtung des Weges + * @param isInputWay, Einfahrtsweg = true, Ausfahrtsweg = false + * @return + */ + public Integer getWay(CardinalDirection direction, boolean isInputWay) { + if(isInputWay) + return (inputWays.containsKey(direction)) ? inputWays.get(direction) : -1; + else + return (outputWays.containsKey(direction)) ? outputWays.get(direction) : -1; + } + + /** + * verbindet die Ausfahrtswege mit den Einfahrtswegen benachbarter Kreuzungen + */ + public void connectWays () { + for (CardinalDirection outDir : outputWays.keySet()) { + List connectedWays = db.getConnectedInputWays(getWay(outDir,false), crossroadID); + for (InputWay integers : connectedWays) { + if(integers!=null) { + outputToInput.put(outDir, integers); + } + } + } + } + /** + * liefert eine Menge von Verbindungen von Einfahrtswegen zu benachbarten Einfahrtswegen + * @return + */ + public Set getConnections(){ + Set connectedOutputways; + Set connectedCrossroads = new HashSet<>(); + InputWay connection; + for (Map.Entry> innerConnection : inputToOutput.entrySet()) { + connectedOutputways = innerConnection.getValue(); + for (CardinalDirection outputDirection : connectedOutputways) { + if(outputToInput.containsKey(outputDirection)) { + connection = outputToInput.get(outputDirection); + connectedCrossroads.add(new InputWayConnection(this.crossroadID, inputWays.get(innerConnection.getKey()),innerConnection.getKey(), connection.getWayID() , connection.getCrossroadID() ,outputDirection)); + } + } + } + return connectedCrossroads; + } + + /** + * Kontrollausgabe für die Einfahrtswege + */ + public void printInputWays(){ + System.out.println("InputWays von:\t"+this.crossroadID); + for (Map.Entry inputWay : inputWays.entrySet()) { + System.out.println(inputWay.getKey() +"\t"+inputWay.getValue()); + } + } + /** + * Kontrollausgabe für die innere Verbindung von Wegen + */ + public void printInput2Output(){ + System.out.println("Input2Output von:\t"+this.crossroadID); + for (Map.Entry> inputWay : inputToOutput.entrySet()) { + System.out.println(inputWay.getKey()); + for (CardinalDirection outputWay : inputWay.getValue()) { + System.out.println("\t"+outputWay); + } + } + } + /** + * Kontrollausgabe für die Ausfahrtswege + */ + public void printOutputWays(){ + System.out.println("OutputWays von:\t"+this.crossroadID); + for (Map.Entry outputWay : outputWays.entrySet()) { + System.out.println(outputWay.getKey() +"\t"+outputWay.getValue()); + } + } +} diff --git a/src/dna/graph/generators/traffic/CrossroadWeight.java b/src/dna/graph/generators/traffic/CrossroadWeight.java new file mode 100644 index 00000000..fe26b6ae --- /dev/null +++ b/src/dna/graph/generators/traffic/CrossroadWeight.java @@ -0,0 +1,197 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.Map; + +public class CrossroadWeight { + public int crossroadID; + private String crossroadName; + public HashMap inputWayWeights; + private HashMap inputWayMaxWeights; + private double maxCount; + private double maxLoad; + private double threshold; + private long timestamp; + + public CrossroadWeight(int crossroadID,String crossroadName, double treshold){ + this.crossroadID = crossroadID; + this.crossroadName = crossroadName; + this.inputWayWeights = new HashMap<>(); + this.inputWayMaxWeights = new HashMap<>(); + this.threshold = treshold; + this.timestamp=0; + } + /** + * liefert den Schwellwert für die Überlastung + * @return + */ + public double getThreshold(){ + return threshold; + } + /** + * liefert den Namen der Kreuzung im Format "A ..." + * @return + */ + public String getCrossroadName(){ + return crossroadName; + } + /** + * fügt Gewichte zu einem Einfahrtsweg hinzu + * @param osmWayID, OSM-ID des Einfahrtsweges + * @param weights, Gewichte des Einfahrtsweges + */ + public void addWeightWay(int osmWayID, double[] weights) { + inputWayWeights.put(osmWayID, weights); + } + /** + * fügt die maximalen Gewichte des Einfahrtsweges hinzu + * @param osmWayID - OSM-ID des Einfahrtsweges + * @param maxWeights + */ + public void setMaxWeightWay(int osmWayID, double[] maxWeights) { + inputWayMaxWeights.put(osmWayID, maxWeights); + } + + /** + * liefert die maximalen Gewichte des Einfahrtsweges + * @param osmWayID, OSM-ID des Einfahrtsweges + * @return + */ + public double[] getMaxWeightWay(int osmWayID) { + return inputWayMaxWeights.get(osmWayID); + } + + /** + * setzt den Zeitstempel, für den das letzte Gewicht vorliegt + * @param timestampInit + */ + public void setTimestamp(long timestampInit){ + this.timestamp = timestampInit; + } + + /** + * liefert den Zeitstempel, für den das letzte Gewicht vorliegt + * @return + */ + public long getTimestamp(){ + return timestamp; + } + + /** + * setzt die maximalen Gewichte für die gesamte Kreuzung + * @param maxWeights + */ + public void setMaxWeight(double[] maxWeights) { + this.maxCount=maxWeights[0]; + this.maxLoad=maxWeights[1]; + } + + /** + * liefert die maximalen Werte für die gesamte Kreuzung + * @return + */ + public double[] getMaxWeight() { + return new double[] {maxCount,maxLoad}; + } + + /** + * verteilt das Knotengewicht gleichmäßig auf die Einfahrtswege, wird bei der Simulation verwendet + * @param count + * @param load + */ + public void resetInputWayWeight(double count, double load){ + double numOfInputWays = inputWayWeights.keySet().size(); + double count_value = count/numOfInputWays; + double load_value = load/numOfInputWays; + for (Map.Entry entry : inputWayWeights.entrySet()) { + entry.setValue(new double[]{count_value,load_value,(count_value/inputWayMaxWeights.get(entry.getKey())[0])*100}); + } + } + + /** + * berechnet das Gewicht des Kreuzungsknotens + * Index 0 - count + * Index 1 - load + * Index 2 - count/maxcount + * @return 3D-double + */ + public double[] getWeight(){ + double[] sum = new double[3]; + for (double[] entry : inputWayWeights.values()) { + sum[0]+=entry[0]; + sum[1]+=entry[1]; + } + int numOfinputWays = inputWayWeights.size(); + if(numOfinputWays>0){ + sum[1]/=numOfinputWays; + } + + // Normierte Werte + if(maxCount>0) + sum[2]=(sum[0]/maxCount)*100; + else + sum[2]=0; + + return sum; + } + + /** + * liefert alle Einfahrtswege, deren Gewicht den Schwellwert überschritten hat + * @return + */ + public HashMap getOverladedEdges() { + HashMap result = new HashMap<>(); + for (Map.Entry inputWay : inputWayWeights.entrySet()) { + if(inputWay.getValue()[2] >threshold){ + result.put(inputWay.getKey(), inputWay.getValue()); + } + } + return result; + } + + /** + * liefert alle Einfahrtswege mit ihren Gewichten + * @return + */ + public HashMap getWayWeights(){ + return inputWayWeights; + } + + /** + * addiert die übergebenen Gewichte auf die Gewichte der Einfahrtswege + * @param wayWeights + * @return + */ + public boolean addWeights(HashMap wayWeights){ + for (Integer keys : wayWeights.keySet()) { + if(!inputWayWeights.containsKey(keys)) + return false; + } + for (Map.Entry entry : wayWeights.entrySet()) { + double[] value = inputWayWeights.get(entry.getKey()); + double[] newValue = entry.getValue(); + for (int i = 0; i < value.length; i++) { + value[i]+=newValue[i]; + } + inputWayWeights.put(entry.getKey(), value); + } + return true; + } + + /** + * bildet den Durchschnitt der aufsummierten Gewichte + * @param divisor, Anzahl der Batches/Tage über die aggregiert wurde + */ + public void divWays(int divisor){ + if(divisor>0){ + for (Map.Entry entry : inputWayWeights.entrySet()) { + double[] value = entry.getValue(); + for (int i = 0; i < value.length; i++) { + value[i] = value[i]/divisor; + } + inputWayWeights.put(entry.getKey(), value); + } + } + } + +} diff --git a/src/dna/graph/generators/traffic/DB.java b/src/dna/graph/generators/traffic/DB.java new file mode 100644 index 00000000..1f2932f7 --- /dev/null +++ b/src/dna/graph/generators/traffic/DB.java @@ -0,0 +1,1545 @@ +package dna.graph.generators.traffic; + + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.joda.time.DateTime; + +import dna.graph.datastructures.GraphDataStructure; +import dna.graph.edges.Edge; +import dna.graph.nodes.INode; +import dna.graph.nodes.Node; + +public class DB { + private static Connection con = null; + private static String dbHost = "127.0.0.1"; // Hostname + private static String dbPort = "3306"; // Port -- Standard: 3306 + private static String dbName = "dbName"; // Datenbankname + private static String dbUser = "dbUser"; // Datenbankuser + private static String dbPass = "dbPass"; // Datenbankpasswort + + + private GraphDataStructure gds; + public DateTime initDateTime; + private HashMap maxValuesCrossroad; + private HashMap maxValuesInputWays; + private HashMap maxValuesSensors; + private HashMap sensorModelNodes; + private HashMap crossroadModelNodes; + public HashMap inputWays; + public HashMap inputWaysToID; + public HashMap> inputWayConnections; //Key: ToCrossroad,ToWay - Value: List + + private double treshold; + private HashMap disabledEdges; + private HashMap> disabledEdgesInputWay; + private boolean dummyMax; + private boolean backupWays = false; + private boolean improvedMax = true; + private boolean newMaxValues = false; + + /** + * Konstruktur der Datenbank, die Login-Daten werden entweder aus einer Txt-Datei gelesen, + * oder falls diese nicht vorhanden ist, aus den Parametern übernommen. + * @param gds, Datenstruktur, welcher der Verwendung von DNA zugrunde liegt (für Knotentypen, Kantentypen ..) + * @param initTDateTime, Startzeitpunkt für die Modi mit realen Daten + * @param daySelection, Boolean-Array mit 7 Einträgen für die Wochentage + * @param timeRange, Intervalllänge für den Tages und Aggregationsmodus + * @param treshold, Schwellwert für die Überlastungserkennung + * @param trafficUpdate, statische Daten für den Simulationsmodus + * @param dummyMax, Verwendung von synthetischen Max-Werten oder realen Max-Werten + */ + public DB(GraphDataStructure gds, DateTime initTDateTime, boolean[] daySelection, double treshold,boolean dummyMax, boolean newMaxValues) { + try { + FileReader fr = new FileReader("db.txt"); + BufferedReader br = new BufferedReader(fr); + String line = br.readLine(); + String[] values; + while (line != null) { + values = line.split(" "); + if(values.length != 2) + System.out.println("Falsche Anzahl an Parametern"); + switch (values[0]) { + case "dbHost": + dbHost = values[1]; + break; + case "dbPort": + dbPort = values[1]; + break; + case "dbName": + dbName = values[1]; + break; + case "dbUser": + dbUser = values[1]; + break; + case "dbPass": + dbPass = values[1]; + break; + default: + break; + } + line = br.readLine(); + } + br.close(); + System.out.println("Datenbank-Logindaten aus Datei gelesen"); + } catch (FileNotFoundException e1) { + System.out.println("Keine Daten für Datenbank gefunden - verwende Dummy-Daten"); + } catch (IOException e) { + e.printStackTrace(); + } + try { + System.out.println("Versuche zur Datenbank zu verbinden"); + Class.forName("com.mysql.jdbc.Driver"); + con = DriverManager.getConnection("jdbc:mysql://"+dbHost+":"+dbPort+"/"+dbName,dbUser,dbPass); + } catch (ClassNotFoundException e) { + System.out.println("Treiber nicht gefunden"); + } catch (SQLException e) { + System.out.println("Verbindung nicht moglich"); + System.out.println("SQLException: " + e.getMessage()); + System.out.println("SQLState: " + e.getSQLState()); + System.out.println("VendorError: " + e.getErrorCode()); + } + this.gds = gds; + this.initDateTime = initTDateTime; + + this.maxValuesInputWays = new HashMap<>(); + this.maxValuesCrossroad = new HashMap<>(); + this.maxValuesSensors = new HashMap<>(); + this.sensorModelNodes = new HashMap<>(); + this.crossroadModelNodes = new HashMap<>(); + this.inputWayConnections = new HashMap<>(); + this.inputWaysToID = new HashMap<>(); + this.inputWays= new HashMap<>(); + this.treshold = treshold; + this.disabledEdges = new HashMap<>(); + this.disabledEdgesInputWay = new HashMap<>(); + this.dummyMax = dummyMax; + this.newMaxValues = newMaxValues; + getInputWays(); + getMaximalWeightCrossroad(); + getMaximalWeightInputWay(); + getMaximalWeightSensor(); + loadFromWays(); + + } + /** + * schreibt das maximale Gewicht für eine Kreuzung in die Tabelle mw_MaxValues_Crossroad, + * die Daten sind auf 1x Stepsize berechnet, ACHTUNG: Datenbankabfrage nicht mehr durchführbar, da zu viele Daten + * @param crossroadID + * @return + */ + public double[] writeMaximalWeightsCrossroad(int crossroadID) { + System.out.println("Schreibe reale Maximalwerte (Dauer 1x stepSize) für Kreuzung mit ID " +crossroadID); + if(crossroadID==43 || crossroadID == 44 || crossroadID == 63 || crossroadID == 99 || crossroadID == 147 || crossroadID == 93) { + return new double[]{0.0,0.0}; + } + String crossroadName = getCrossroadName(crossroadID); + double count = 0; + double load = 0; + ResultSet rs; + String selectStmt = null; + try { + String sensorsOfCrossroad = "SELECT ID AS SENSOR_ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID="+crossroadID; + String sensorWaysOfCrossroad = "SELECT * FROM mw_SensorWays SW WHERE crossroadID = "+crossroadID+" AND wayID IS NOT NULL"; + String eventData = "SELECT DATETIME, ID AS EVENT_ID, cr_count AS COUNT_VALUE, cr_load AS LOAD_VALUE, RE.CSVOFFSET FROM jee_trafficlight_rawevents RE WHERE CROSSROAD = '"+crossroadName+"'"; + String crossroadWeight = "SELECT EVENT_ID,DATETIME,COUNT_VALUE, LOAD_VALUE,sensorName as SENSOR_NAME, sensorID as SENSOR_ID, SENSORS.CSVOFFSET, crossroadID as CROSSROAD_ID, crossroadName as CROSSROAD_NAME FROM (SELECT sensorID,sensorName, CSVOFFSET,crossroadID,crossroadName FROM ("+sensorsOfCrossroad+") SENSORS RIGHT JOIN ("+sensorWaysOfCrossroad+") SENSORS_MAPPED ON SENSORS.SENSOR_ID = SENSORS_MAPPED.sensorID) SENSORS LEFT JOIN ("+eventData+") EVENT_DATA on SENSORS.CSVOFFSET = EVENT_DATA.CSVOFFSET"; + selectStmt = "SELECT * FROM (SELECT SUM(COUNT_VALUE) AS ANZAHL, SUM(LOAD_VALUE)/COUNT(LOAD_VALUE) as BELEGUNG, DATETIME,CROSSROAD_ID, CROSSROAD_NAME FROM (SELECT CROSSROAD_WEIGHT.*,mw_SensorConnection.FRONT_BACK,mw_SensorConnection.FROM_DIRECTION, mw_SensorConnection.TO_LEFT,mw_SensorConnection.TO_STRAIGHT,mw_SensorConnection.TO_RIGHT FROM ("+crossroadWeight+") CROSSROAD_WEIGHT JOIN mw_SensorConnection ON CROSSROAD_WEIGHT.SENSOR_ID = mw_SensorConnection.SENSOR_ID) RESULT WHERE FRONT_BACK = 0 GROUP BY DATETIME ORDER BY ANZAHL DESC LIMIT 1) GROUPED"; + // COUNT + Statement stmt = con.createStatement(); + rs= stmt.executeQuery(selectStmt); + if(rs.first() && rs.getTime("DATETIME")!=null){ + String inserTableSQL = "REPLACE INTO mw_MaxValues_Crossroad VALUES (?,?,?,?,?,?,DEFAULT)"; + PreparedStatement insertStmt = con.prepareStatement(inserTableSQL); + insertStmt.setInt(1, rs.getInt("CROSSROAD_ID")); + insertStmt.setString(2, rs.getString("CROSSROAD_NAME")); + insertStmt.setInt(3, rs.getInt("ANZAHL")); + insertStmt.setInt(4, rs.getInt("BELEGUNG")); + insertStmt.setTimestamp(5, rs.getTimestamp("DATETIME")); + insertStmt.setInt(6, 0); + System.out.println(insertStmt); + insertStmt.executeUpdate(); + count = rs.getDouble("ANZAHL"); + return new double[]{count,load}; + } + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("SQLException bei " +crossroadID+"\t\t"+selectStmt); + } + return new double[]{0.0,0.0}; + } + + /** + * aktualisiert die maximalen Wert der Kreuzung, sofern dies nötig ist + * - wird nur ausgeführt, wenn newMaxValues auf TRUE gesetzt ist + * @param crossroadID - ID der Kreuzung + * @param count - neuer Count-Wert + * @param load - neuer Load-Wert + * @param time - Beginn der Aggregation + * @param timeRange - Zeitintervall der Aggregation + * @return + */ + public boolean setMaximalWeightsCrossroadImproved(int crossroadID, double count, double load, DateTime time, int timeRange){ + String inserTableSQL = "UPDATE mw_MaxValues_CrossroadImproved SET COUNT_VALUE = ?, LOAD_VALUE = ?, DATETIME = ?,timeRange = ? WHERE CROSSROAD_ID ="+crossroadID+" AND COUNT_VALUE<"+count; + try { + PreparedStatement insertStmt = con.prepareStatement(inserTableSQL); + insertStmt.setDouble(1,count); + insertStmt.setDouble(2, load); + insertStmt.setTimestamp(3, Timestamp.valueOf(toSql(time))); + insertStmt.setInt(4, timeRange*2); + if(newMaxValues) + insertStmt.execute(); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } + + /** + * Aktualisiert die maximalen Werte des Einfahrtsweges, sofern dies nötig ist + * - wird nur ausgeführt, wenn newMaxValues auf TRUE gesetzt ist + * @param inputWayID - globale ID des Einfahrtsweges + * @param count - neuer Count-Wert + * @param load - neuer Load-Wert + * @param time Beginn der Aggregation + * @param timeRange Zeitintervall der Aggregation + * @return + */ + public boolean setMaximalWeightsInputWayImproved(int inputWayID, double count, double load, DateTime time, int timeRange){ + String inserTableSQL = "UPDATE mw_MaxValues_InputWaysImproved SET COUNT_VALUE = ?, LOAD_VALUE = ?, DATETIME = ?, timeRange = ? WHERE INPUT_WAY_ID ="+inputWayID+" AND COUNT_VALUE<"+count; + try { + PreparedStatement insertStmt = con.prepareStatement(inserTableSQL); + insertStmt.setDouble(1,count); + insertStmt.setDouble(2, load); + insertStmt.setTimestamp(3, Timestamp.valueOf(toSql(time))); + insertStmt.setInt(4, timeRange*2); + if(newMaxValues) + insertStmt.execute(); + } catch (SQLException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return true; + } + + /** + * schreibt einen neuen Zufallswert für die Kreuzung in mw_MaxValues_Crossroad_Random + * @param crossroadID - globale ID der Kreuzung + * @param random - Count-Wert als Zufallswert + */ + public void writeMaximalWeightsCrossroadsRandom(int crossroadID,double random){ + java.sql.PreparedStatement stmt; + try { + String inserTableSQL = "REPLACE INTO mw_MaxValues_Crossroad_Random VALUES (?,?)"; + stmt = con.prepareStatement(inserTableSQL); + stmt.setInt(1, crossroadID); + stmt.setDouble(2, random); + stmt.execute(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * schreibt das maximale Gewicht (nur Count) für einen Einfahrtsweg in die Tabelle mw_MaxValues_InputWays, + * die Daten sind auf 1x Stepsize berechnet, ACHTUNG: Datenbankabfrage nicht mehr durchführbar, da zu viele Daten + * @param inputwayID globale ID des Einfahrtsweges + * @return + */ + public double[] writeMaximalWeightsInputWays(int inputwayID) { + System.out.println("Prüfe ID MaximalWeightsInputWays " +inputwayID); + int count = 0; + int load = 0; + ResultSet rs; + int[] inputData = inputWays.get(inputwayID); + int crossroadID = inputData[1]; + System.out.println("InputWay:\t"+inputwayID+"CrossroadID:\t"+crossroadID); + String selectStmt = null; + try { + selectStmt = "SELECT SUM(cr_count) as ANZAHL,SUM(cr_load)/COUNT(cr_load) AS BELEGUNG, DATETIME,SENSORS_ON_WAY.* FROM (SELECT * FROM (SELECT ID AS SENSOR_ID, REALNAME AS SENSOR_NAME, CSVOFFSET, wayID AS WAY_ID, CROSSROAD_ID, crossroadName AS CROSSROAD_NAME FROM (SELECT ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID='"+crossroadID+"') GLOBALSENSORS RIGHT JOIN (SELECT * FROM mw_SensorWays WHERE crossroadID = '"+crossroadID+"' AND wayID IS NOT NULL) SENSORS_MAPPED ON GLOBALSENSORS.ID = SENSORS_MAPPED.sensorID) SENSORS JOIN (SELECT * FROM mw_InputWaysGlobal IWG WHERE IWG.ID = '"+inputwayID+"') INPUT_WAYS ON SENSORS.WAY_ID = INPUT_WAYS.wayID) SENSORS_ON_WAY LEFT JOIN jee_trafficlight_rawevents RE ON RE.CSVOFFSET = SENSORS_ON_WAY.CSVOFFSET AND RE.CROSSROAD = SENSORS_ON_WAY.CROSSROAD_NAME GROUP BY DATETIME ORDER BY ANZAHL DESC LIMIT 1"; + // COUNT + Statement stmt = con.createStatement(); + rs= stmt.executeQuery(selectStmt); + if(rs.first() && rs.getTime("DATETIME")!=null){ + String inserTableSQL = "REPLACE INTO mw_MaxValues_InputWays VALUES (?,?,?,?,?,?,?,DEFAULT)"; + java.sql.PreparedStatement insertStmt = con.prepareStatement(inserTableSQL); + insertStmt.setInt(1,inputwayID); + insertStmt.setInt(2, rs.getInt("CROSSROAD_ID")); + insertStmt.setString(3, rs.getString("CROSSROAD_NAME")); + insertStmt.setInt(4, rs.getInt("ANZAHL")); + insertStmt.setInt(5, rs.getInt("BELEGUNG")); + insertStmt.setTimestamp(6, rs.getTimestamp("DATETIME")); + insertStmt.setInt(7, 0); + System.out.println(insertStmt); + insertStmt.executeUpdate(); + count = rs.getInt("ANZAHL"); + return new double[]{count,load}; + } + } catch (SQLException e) { + e.printStackTrace(); + System.out.println("SQLException in writeMaximalWeightsInputWays mit ID"+ inputwayID+"\t\t"+selectStmt); + } + return new double[]{count,load}; + } + + /** + * berechnet das Gewicht (als CrossroadWeight-Objekt) für die Kreuzung + * @param crossroadID - globale ID der Kreuzung + * @param from - Startzeitpunkt + * @param to - Endzeitpunkt + * @param timestampInit - Zeitstempel für den das Gewicht berechnet wird + * @return + */ + public CrossroadWeight getCrossroadWeight(int crossroadID, DateTime from, DateTime to,long timestampInit) { + String crossroadName = getCrossroadName(crossroadID); + if(!maxValuesCrossroad.containsKey(crossroadID)){ + maxValuesCrossroad.put(crossroadID, getMaximalWeightCrossroad(crossroadID) ); + } + CrossroadWeight crw = new CrossroadWeight(crossroadID, crossroadName,treshold); + try { + // Wählt alle Sensoren aus, die zur Kreuzung gehören + String sensors = "SELECT ID as SENSOR_ID, CSVOFFSET, REALNAME, CROSSROAD_ID FROM jee_crmodel_SensorDim S WHERE S.CROSSROAD_ID='"+crossroadID+"'"; + // Wählt die Wege der Kreuzung aus, um die Sensoren darauf zu mappen + String sensorWays = "SELECT * FROM mw_SensorWays SW WHERE crossroadID ='"+crossroadID+"' AND wayID IS NOT NULL"; + // Lädt die entsprechenden Sensordaten für den definierten Zeitraum + String eventData = "SELECT ID as EVENT_ID,cr_count as COUNT_VALUE, cr_load as LOAD_VALUE, RE.CSVOFFSET,DATETIME FROM jee_trafficlight_rawevents RE WHERE RE.DATETIME >= '"+toSql(from)+"'AND RE.DATETIME < '"+toSql(to)+"' AND CROSSROAD = '"+crossroadName+"'"; + // Filtert aus den Sensordaten die Daten für die Sensoren raus + String crossroadWeight ="SELECT EVENT_ID,DATETIME,COUNT_VALUE, LOAD_VALUE,sensorName as SENSOR_NAME, sensorID as SENSOR_ID, SENSORS.CSVOFFSET, crossroadID as CROSSROAD_ID, crossroadName as CROSSROAD_NAME FROM (SELECT sensorID,sensorName, CSVOFFSET,crossroadID,crossroadName FROM ("+sensors+") SENSORS RIGHT JOIN ("+sensorWays+") SENSORS_MAPPED ON SENSORS.SENSOR_ID = SENSORS_MAPPED.sensorID) SENSORS LEFT JOIN ("+eventData+") EVENT_DATA on SENSORS.CSVOFFSET = EVENT_DATA.CSVOFFSET"; + // Mapped die Sensoren auf die Richtung des Einfahrtsweges für die Gruppierung + String resultData = "SELECT CROSSROAD_WEIGHT.*,mw_SensorConnection.FRONT_BACK,mw_SensorConnection.FROM_DIRECTION, mw_SensorConnection.TO_LEFT,mw_SensorConnection.TO_STRAIGHT,mw_SensorConnection.TO_RIGHT FROM ("+crossroadWeight+") CROSSROAD_WEIGHT JOIN mw_SensorConnection ON CROSSROAD_WEIGHT.SENSOR_ID = mw_SensorConnection.SENSOR_ID"; + // Kombiniert die ermittelten Sensorwert mit den Einfahrtswegen (aus OSM) der Kreuzung und summiert die Werte auf + String selectStmt = "SELECT SUM(COUNT_VALUE)/COUNT(DISTINCT DATETIME) as ANZAHL, SUM(LOAD_VALUE)/COUNT(LOAD_VALUE) as BELEGUNG ,FROM_DIRECTION, OSMWAY_ID FROM ("+resultData+") RESULT LEFT JOIN (SELECT * FROM mw_CrossroadWays WHERE TYPE = '0')CRW on RESULT.FROM_DIRECTION = CRW.DIRECTION AND RESULT.CROSSROAD_ID = CRW.CROSSROAD_ID WHERE FRONT_BACK = 0 GROUP BY OSMWAY_ID"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + while (rs.next()) { + int wayID = rs.getInt("OSMWAY_ID"); + double[] maxValue = getMaximalWeightInputWayFromMap(wayID,crossroadID); //Index 0 = MaxCount, Index 1 = MaxLoad + if(maxValue == null){ + maxValue = new double[]{Double.MAX_VALUE,Double.MAX_VALUE}; + } + crw.setMaxWeightWay(wayID, maxValue); + double count = rs.getDouble("ANZAHL"); + double load = rs.getDouble("BELEGUNG"); + //TODO: Verbindung zur TimeRange, war zuvor als Parameter in Datenbank, nun nur noch im TrafficConfig + setMaximalWeightsInputWayImproved(getInputWay(crossroadID, wayID), count, load, from, 5); // aktualisiert den maximalen Count-Wert, sofern dies notwendig ist + crw.addWeightWay(wayID, new double[]{count,load,(count/maxValue[0])*100}); + crw.setTimestamp(timestampInit); + + } + } catch (SQLException e) { + e.printStackTrace(); + } + crw.setMaxWeight(maxValuesCrossroad.get(crossroadID)); + crossroadModelNodes.put(crossroadID, crw); + return crw; + } + + /** + * berechnet das synthetische InitialGewicht im Simulationsmodus, beinhaltet eine DB-Abfrage zur Erstellung des CrossroadWeight-Objekts + * @param crossroadID, globale KreuzungsID + * @param from Startzeitpunkt für DB-Abfrage + * @param to Entzeitpunkt für DB-Abfrage + * @param timestamp, Zeitstempel für die Definition im CrossroadWeightObjekt + * @param trafficUpdate, beinhaltet die synthetischen Daten + * @return + */ + public CrossroadWeight getCrossroadWeightStaticInit(int crossroadID,DateTime from, DateTime to, long timestampInit,TrafficUpdate trafficUpdate) { + CrossroadWeight crw = getCrossroadWeight(crossroadID, from, to,timestampInit); + crw.resetInputWayWeight(trafficUpdate.getInitCount(), trafficUpdate.getInitLoad()); + return crw; + } + + /** + * berechnet das synthetische Gewicht im Simulationsmodus für fortlaufende Batches + * @param crossroadID gloable KreuzungsID + * @param update beinhaltet die synthetischen Daten + * @return + */ + public CrossroadWeight getCrossroadWeightStaticBatch(int crossroadID,TrafficUpdate update) { + CrossroadWeight crw = crossroadModelNodes.get(crossroadID); + crw.setTimestamp(crw.getTimestamp()+1); + if(update.isAffected(crossroadID)){ + crw.resetInputWayWeight((update.getSleepTillUpdate()*update.getInitCount()+update.getUpdateCount())/(update.getSleepTillUpdate()+1), (update.getSleepTillUpdate()*update.getInitLoad()+update.getUpdateLoad())/(update.getSleepTillUpdate()+1)); + } + return crw; + } + + /** + * liest das maximale Gewicht aus der Tabelle mw_MaxValues_Crossroad (auf 1xTimestep berechnet) + * @param crossroadID + * @return + */ + public double[] getMaximalWeightCrossroad(int crossroadID) { + try { + String selectStmt = "SELECT * FROM mw_MaxValues_Crossroad WHERE CROSSROAD_ID = "+crossroadID+" AND COUNT_OR_LOAD =0"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + if(rs.first()){ + return new double[]{rs.getDouble("COUNT"),0}; + } + else + return writeMaximalWeightsCrossroad(crossroadID); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * liest Maximalwerte des Einfahrtsweges aus der HashMap (zwischengespeichert nach DB-Abfrage) + * @param wayID + * @param crossroadID + * @return + */ + private double[] getMaximalWeightInputWayFromMap(int wayID,int crossroadID){ + int inputWayID = getInputWay(crossroadID, wayID); + double[] result = maxValuesInputWays.get(inputWayID); + return result; + } + + /** + * liest den Maximalwert für einen Einfahrtsweg direkt aus der Datenbank (aus mw_MaxValues_InputWays) + * @param osmWayID + * @param crossroadRoad + * @return + */ + private double[] getMaximalWeightInputWay(int inputWayID) { + try { + String selectStmt = "SELECT * FROM mw_MaxValues_InputWays WHERE INPUT_WAY_ID = "+inputWayID+" AND COUNT_OR_LOAD =0"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + if(rs.first()){ + return new double[]{rs.getDouble("COUNT"),0}; + } + else + return writeMaximalWeightsInputWays(inputWayID); + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * liest den Maximalwert für einen Einfahrtsweg direkt aus der Datenbank + * @param osmWayID + * @param crossroadRoad + * @return + */ + private double[] getMaximalWeightInputWay(int osmWayID, int crossroadRoad) { + try { + String selectStmt = "SELECT IW.*,wayID FROM mw_MaxValues_InputWays IW LEFT JOIN mw_InputWaysGlobal IWG ON IW.INPUT_WAY_ID = IWG.ID WHERE wayID ='"+osmWayID+"' AND CROSSROAD_ID ="+crossroadRoad; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + if(rs.first()){ + return new double[]{rs.getDouble("COUNT"),0}; + } + else + return new double[]{Double.MAX_VALUE,Double.MAX_VALUE}; + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * liest die Maximalwerte der Einfahrtswege aus der, durch die Parameter festgelegten Tabelle + * Random-Werte wenn dummyMax=true, sonst die MaximalWerte für den Berufsverkehr + */ + public void getMaximalWeightInputWay() { + try { + String selectStmt = null; + if(dummyMax) + selectStmt = "SELECT * FROM mw_MaxValues_InputWay_Random JOIN mw_InputWaysGlobal on INPUTWAY_ID = ID"; + else + selectStmt = "SELECT * FROM mw_MaxValues_InputWaysImproved WHERE COUNT_OR_LOAD =0"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + while(rs.next()) { + if(dummyMax) + maxValuesInputWays.put(rs.getInt("INPUTWAY_ID"), new double[]{rs.getDouble("MAX_COUNT"),0}); + else{ + double maxCount = rs.getDouble("COUNT_VALUE"); + if(maxCount <1) + maxCount= 1; + maxValuesInputWays.put(rs.getInt(1), new double[]{maxCount,rs.getDouble("LOAD_VALUE")}); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + /** + * schreibt maximale Werte für die Einfahrtswege einer Kreuzung, die Werte orientieren sich dabei an den Maximalwerten der Kreuzung + */ + public void writeMaximalWeightInputWayRandom() { + Random rand = new Random(); + try { + String selectStmt = "SELECT ID, crossroadID,MAX_COUNT as MAX_COUNT_CROSSROAD FROM mw_InputWaysGlobal IWG LEFT JOIN mw_MaxValues_Crossroad_Random MAX_C_RANDOM ON IWG.crossroadID = MAX_C_RANDOM.CROSSROAD_ID"; + Statement stmt = con.createStatement(); + String insertString = "REPLACE INTO mw_MaxValues_InputWay_Random VALUES (?,?)"; + java.sql.PreparedStatement insertStmt = con.prepareStatement(insertString); + ResultSet rs = stmt.executeQuery(selectStmt); + while(rs.next()) { + double randMax = rand.nextDouble()*(rs.getDouble("MAX_COUNT_CROSSROAD")/2)+rs.getDouble("MAX_COUNT_CROSSROAD")/4; + insertStmt.setInt(1, rs.getInt("ID")); + insertStmt.setDouble(2, randMax); + insertStmt.addBatch(); + } + insertStmt.executeBatch(); + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + /** + * schreibt maximale Werte für die realen Sensoren in die Datenbank, welche sich grob an den Werten für den passenden virtuellen Sensor orientieren + */ + public void writeMaximalWeightSensorRandom() { + Random rand = new Random(); + try { + String selectStmt = "SELECT NODE_ID as REALSENSOR_INDEX , R2.* FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 0) R3 LEFT JOIN (SELECT R1.*,MAX_COUNT FROM (SELECT INPUTWAY_INDEX, ANZAHL_SENSORS,WAY_ID,CROSSROAD_ID,DIRECTION, ID as INPUTWAY_ID_GLOBAL FROM (SELECT NODE_ID as INPUTWAY_INDEX, COUNT(VS) as ANZAHL_SENSORS,WAY_ID,CROSSROAD_ID,DIRECTION FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 1) WAYS LEFT JOIN (SELECT SG2.NODE_ID as VS, SG1.NODE_ID as RS FROM (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 0) SG1 JOIN (SELECT * FROM mw_SensorGlobal WHERE SENSOR_TYPE = 1) SG2 ON SG1.WAY_ID = SG2.WAY_ID AND SG1.CROSSROAD_ID = SG2.CROSSROAD_ID AND SG1.DIRECTION = SG2.DIRECTION) VS_TO_RS ON WAYS.NODE_ID = VS_TO_RS.VS GROUP BY VS) ANZAHL LEFT JOIN mw_InputWaysGlobal IWG ON ANZAHL.WAY_ID = IWG.wayID AND ANZAHL.CROSSROAD_ID = IWG.crossroadID) R1 LEFT JOIN mw_MaxValues_InputWay_Random MWIWR ON R1.INPUTWAY_ID_GLOBAL=MWIWR.INPUTWAY_ID) R2 ON R3.WAY_ID = R2.WAY_ID AND R3.CROSSROAD_ID = R2.CROSSROAD_ID AND R3.DIRECTIOn = R2.DIRECTION"; + Statement stmt = con.createStatement(); + String insertString = "REPLACE INTO mw_MaxValues_Sensor_Random VALUES (?,?)"; + java.sql.PreparedStatement insertStmt = con.prepareStatement(insertString); + ResultSet rs = stmt.executeQuery(selectStmt); + while(rs.next()) { + double randMax = rand.nextDouble()*(rs.getDouble("MAX_COUNT")/rs.getDouble("ANZAHL_SENSORS"))+2; + if(rs.getDouble("MAX_COUNT")==0) + randMax = rand.nextDouble()*5+2; + insertStmt.setInt(1, rs.getInt("REALSENSOR_INDEX")); + insertStmt.setDouble(2, randMax); + insertStmt.addBatch(); + } + insertStmt.executeBatch(); + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + + /** + * liest die Maximalwerte der Kreuzungen aus der, durch die Parameter festgelegten Tabelle + * Random-Werte wenn dummyMax=true, sonst die MaximalWerte für den Berufsverkehr + */ + public void getMaximalWeightCrossroad() { + try { + String selectStmt; + + if(dummyMax) + selectStmt = "SELECT * FROM mw_MaxValues_Crossroad_Random"; + else + selectStmt = "SELECT * FROM mw_MaxValues_CrossroadImproved"; + + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + + while(rs.next()){ + if(dummyMax) + maxValuesCrossroad.put(rs.getInt("CROSSROAD_ID"), new double[] {rs.getDouble("MAX_COUNT"),0}); + else{ + double maxCount = rs.getDouble("COUNT_VALUE"); + if(maxCount <1) + maxCount = 1; + maxValuesCrossroad.put(rs.getInt("CROSSROAD_ID"), new double[] {maxCount,rs.getDouble("LOAD_VALUE")}); + } + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } + /** + * liest die hinterlegten, zufälligen Maximalwerte für die Sensoren + */ + public void getMaximalWeightSensor() { + try { + String selectStmt = "SELECT * FROM mw_MaxValues_Sensor_Random"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + while(rs.next()){ + maxValuesSensors.put(rs.getInt("SENSOR_ID"), new double[] {rs.getDouble("MAX_COUNT"),0}); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + + /** + * Aufruf von setID für Startknoten + * @param id - globale ID des Einfahrtsweges + * @return + */ + public int setFromID(int id) { + return setID(id,"from"); + } + + /** + * Aufruf von setID für Zielknoten + * @param id - globale ID des Einfahrtsweges + * @return + */ + public int setToID(int id) { + return setID(id,"to"); + } + + /** + * Hilfsmethode zur Generierung der Tabelle mw_InputWayConnection aus den Informationen der innerern Kreuzungsverbindung + * Einfahrtsweg -> Ausfahrtswege -> Einfahrtswege + * @param id globale ID des Einfahrtsweges + * @param mode from = Startknoten, to = Zielknoten + * @return + */ + public int setID(int id,String mode) { + try { + String selectStmtString = "SELECT * FROM mw_InputWaysGlobal WHERE ID = "+ id; + Statement selectStmt = con.createStatement(); + ResultSet rs = selectStmt.executeQuery(selectStmtString); + rs.first(); + String updateString = "UPDATE mw_InputWayConnection A SET "+mode+"ID = "+id+" WHERE A."+mode+"Way = "+rs.getInt(2) +" AND A."+mode+"Crossroad = " +rs.getInt(3); + Statement updateStmt = con.createStatement(); + return updateStmt.executeUpdate(updateString); + + } catch (SQLException e) { + e.printStackTrace(); + } + return 0; + } + + /** + * liest die Verbindungen der Kreuzungsknoten aus der Tabelle mw_CrossroadConnection + * @param nodesFilter Array von KnotenID, die als Startknoten oder Endknoten fungieren dürfen + * @return Liste von EdgeContainern mit (from,to) + */ + public List getCrossroadConnectionForDNA(int[] nodesFilter) { + List connection = new ArrayList<>(); + + String filterString =""; + if(nodesFilter!= null && nodesFilter.length>0){ + StringBuffer sb = new StringBuffer(" IN ("); + for (int i = 0; i < nodesFilter.length; i++) { + sb.append(nodesFilter[i]); + if(i getInputWays(int crossroadID) { + return getWays(crossroadID,0); + } + + /** + * liest alle Ausfahrtswege einer Kreuzung + * @param crossroadID - globale KreuzungsID + * @return + */ + public HashMap getOutputWays(int crossroadID) { + return getWays(crossroadID,1); + } + + /** + * liest alle Wege des übergebenen Typs aus der Tabelle mw_CrossroadWays + * @param crossroadID - globale KreuzungsID + * @param type - 0 = Einfahrtsweg, 1 = Ausfahrtsweg + * @return HashMap mit Himmelsrichtung als Key, und OSM-ID des Weges als Value + */ + private HashMap getWays(int crossroadID, int type) { + HashMap ways = new HashMap<>(); + + try { + Statement stmt = con.createStatement(); + String statementString = "SELECT DIRECTION , OSMWAY_ID FROM mw_CrossroadWays WHERE CROSSROAD_ID ="+crossroadID+" AND TYPE =" +type; + ResultSet rs = stmt.executeQuery(statementString); + + while(rs.next()){ + ways.put(CardinalDirection.valueOf(rs.getString("DIRECTION")), rs.getInt("OSMWAY_ID")); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + + return ways; + } + + /** + * liefert eine Liste von Ausfahrtswegen, von denen der übergebene Einfahrtsweg direkt zu erreichen ist + * @param crossroadID + * @param toWay + * @return + */ + public List getFromWays(int crossroadID, int toWay) { + return inputWayConnections.get(new InputWay(toWay, crossroadID)); + + } + + /** + * erstellt eine Hashmap mit Einfahrtswegen als Keys und Listen von Einfahrtswegen als Values + */ + public void loadFromWays(){ + InputWay key; + int[] value; + + try { + String selectStmt = "SELECT FROM_CROSSROAD,FROM_WAY,TO_CROSSROAD,TO_WAY FROM mw_CrossroadConnection"; + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + + while(rs.next()) { + key = new InputWay(rs.getInt("TO_WAY"),rs.getInt("TO_CROSSROAD")); + value = new int[]{rs.getInt("FROM_CROSSROAD"), rs.getInt("FROM_WAY")}; + if(!this.inputWayConnections.containsKey(key)){ + this.inputWayConnections.put(key,new ArrayList()); + } + this.inputWayConnections.get(key).add(value); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + + /** + * liest alle Sensoren, die auf den überlieferten Weg gemappt wurden + * @param crossroadID - globale KreuzungsID + * @param wayID - OSM-ID für den Weg + * @return, Liste von Sensoren + */ + public List getSensors(int crossroadID, int wayID) { + List sensors = new ArrayList<>(); + try { + Statement stmt = con.createStatement(); + String statementString = "SELECT * FROM mw_SensorWays WHERE crossroadID ="+crossroadID+" AND wayID =" +wayID; + ResultSet rs = stmt.executeQuery(statementString); + while(rs.next()){ + sensors.add(new Sensor(rs.getInt(1),rs.getString(2),rs.getInt(3),rs.getString(4),rs.getInt(5))); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return sensors; + } + + /** + * liefert ein Sensor-Objekt für einen modellierten Sensor + * @param sensorID - globale Sensor-ID + * @return + */ + public Sensor getSensor(int sensorID) { + Set directions= new HashSet<>(); + try { + Statement stmt = con.createStatement(); + String statementString = "SELECT * FROM mw_SensorConnection WHERE SENSOR_ID = "+sensorID; + ResultSet rs = stmt.executeQuery(statementString); + if(rs.first()) { + + // Abfrage der Abbiegemöglichkeiten + if(rs.getString("TO_LEFT")!=null) { + directions.add(CardinalDirection.valueOf(rs.getString("TO_LEFT"))); + } + if(rs.getString("TO_STRAIGHT")!=null) { + directions.add(CardinalDirection.valueOf(rs.getString("TO_STRAIGHT"))); + } + if(rs.getString("TO_RIGHT")!=null) { + directions.add(CardinalDirection.valueOf(rs.getString("TO_RIGHT"))); + } + + return new Sensor(rs.getInt("sensorID"), rs.getString("sensorName"), rs.getInt("crossroadID"), rs.getString("crossroadName"), rs.getInt("wayID"),directions); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return null; + } + + /** + * liefert alle Ausfahrtswege, die durch die Abbiegemöglichkeiten des Sensors erreichbar sind + * @param sensorID - globale SensorID + * @param crossroadID - globale KreuzungsID + * @return HashMap mit Abbiegerichtung und WegeID + */ + public HashMap getOutputWays(int sensorID, int crossroadID) { + HashMap outputDirection = new HashMap<>(); + try { + String[] direction = new String[] {"LEFT","STRAIGHT", "RIGHT"}; + Statement stmt = con.createStatement(); + int wayID; + String statementString; + + // Eine Abfrage je Abbiegemöglichkeit + for (int i = 0; i < direction.length; i++) { + statementString = "SELECT SC.CROSSROAD_ID, SC.CROSSROAD_NAME, SC.SENSOR_ID, SC.SENSOR_NAME, SC.FROM_WAY, SC.FROM_DIRECTION, SC.TO_LEFT, CW.OSMWAY_ID as OUT_WAYID, CW.DIRECTION as OUTDIRECTION FROM mw_SensorConnection SC , mw_CrossroadWays CW WHERE SC.CROSSROAD_ID = CW.CROSSROAD_ID AND SC.TO_"+direction[i]+" = CW.DIRECTION AND SC.CROSSROAD_ID = "+crossroadID+" AND CW.TYPE=1 AND SC.SENSOR_ID = "+sensorID; + ResultSet rs = stmt.executeQuery(statementString); + while(rs.next() ) { + wayID = rs.getInt("OUT_WAYID"); + if( wayID >0 ) + outputDirection.put(direction[i],wayID); + } + } + + } catch (SQLException e) { + e.printStackTrace(); + } + return outputDirection; + } + + /** + * liefert alle Einfahrtswege, die mit dem übergebenen Ausfahrtsweg verbunden sind + * @param outputOSM, OSM-ID des Weges + * @param outputCrossroad, ID der Kreuzung, zu der der Weg gehört + * @return + */ + public List getConnectedInputWays(int outputOSM, int outputCrossroad) { + List connections = new ArrayList<>(); + try { + Statement stmt = con.createStatement(); + int wayID; + String statementString; + statementString = "SELECT TO_CROSSROAD,TO_WAY FROM mw_CrossroadConnection CC WHERE CC.FROM_WAY = "+outputOSM+" AND CC.FROM_CROSSROAD = " +outputCrossroad; + ResultSet rs = stmt.executeQuery(statementString); + while(rs.next() ) { + wayID = rs.getInt("TO_WAY"); + if( wayID >0 ) { + connections.add(new InputWay(rs.getInt(1), rs.getInt(2))); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + return connections; + } + + /** + * liefert die IDs aller Sensoren, die auf dieser Kreuzung modelliert wurden + * @param crossroadID - globale ID der Kreuzung + * @return + */ + public List getSensorIDs(int crossroadID) { + List sensors = new ArrayList<>(); + try { + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT SENSOR_ID FROM mw_SensorConnection WHERE CROSSROAD_ID = "+crossroadID); + + while(rs.next()) { + sensors.add(rs.getInt(1)); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + return sensors; + } + + /** + * liest die Einfahrtswege für die interne Speicherung in der DB-Klasse + * erstellt daraus HashMaps für den schnellen Zugriff anhand der ID + */ + private void getInputWays(){ + try { + Statement stmt = con.createStatement(); + String statementString = "SELECT * FROM mw_InputWaysGlobal"; + ResultSet rs = stmt.executeQuery(statementString); + + while(rs.next() ) { + + int wayID = rs.getInt("wayID"); + int crossroadID = rs.getInt("crossroadID"); + + inputWays.put(rs.getInt("ID"), new int[]{wayID,crossroadID}); + inputWaysToID.put(new InputWay(wayID,crossroadID), rs.getInt(1)); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * liest die globale ID des Einfahrtsweges aus der HashMap + * @param crossroadID - globale KreuzungsID + * @param wayID - OSMWay-ID + * @return globale ID des Einfahrtsweges + */ + public int getInputWay(int crossroadID,int wayID){ + InputWay key = new InputWay(wayID, crossroadID); + if(inputWaysToID.containsKey(key)){ + return inputWaysToID.get(key); + } + else{ + return -1; + } + } + + /** + * liefert eine Liste von Knoten, die alle Einfahrtsweges für den Wegegraph beinhaltet + * @param nodesFilter - Array mit den zu berücksichtigenden Knoten + * @return + */ + public List getInputWaysForDNA(int[] nodesFilter) { + List nodes = new ArrayList(); + Node currentWeighted = null; + + String filterString = ""; + + // Filter aktiviert, baue Filterstring auf + if(nodesFilter != null && nodesFilter.length>0){ + StringBuffer sb = new StringBuffer("WHERE ID IN ("); + for (int i = 0; i < nodesFilter.length; i++) { + sb.append(nodesFilter[i]); + if(i getInputWaysConnectionForDNA(int[] nodesFilter) { + List edges = new ArrayList<>(); + + String filterString = ""; + + // Filter aktiviert, baue Filterstring auf + if(nodesFilter != null && nodesFilter.length>0){ + StringBuffer sb = new StringBuffer("IN ("); + for (int i = 0; i < nodesFilter.length; i++) { + sb.append(nodesFilter[i]); + if(i getCrossroadsForDNA(int[] nodesFilter) { + List nodes = new ArrayList(); + Node current = null; + + String filterString = ""; + + // Filter aktiviert, baue Filterstring auf + if(nodesFilter != null && nodesFilter.length>0){ + StringBuffer sb = new StringBuffer("WHERE CROSSROAD IN ("); + for (int i = 0; i < nodesFilter.length; i++) { + sb.append(nodesFilter[i]); + if(i connections) { + java.sql.PreparedStatement stmt; + try { + String inserTableSQL = "INSERT IGNORE INTO mw_InputWayConnection VALUES (?,?,?,?,?,?,DEFAULT)"; + stmt = con.prepareStatement(inserTableSQL); + for (InputWayConnection connection : connections) { + stmt.setInt(1, connection.getFromWayID()); + stmt.setInt(2, connection.getFromCrossroad()); + stmt.setString(3, getCrossroadName(connection.getFromCrossroad())); + stmt.setInt(4, connection.getToWayID()); + stmt.setInt(5, connection.getToCrossroad()); + stmt.setString(6, getCrossroadName(connection.getToCrossroad())); + stmt.addBatch(); + } + stmt.executeBatch(); + } catch (Exception e) { + e.printStackTrace(); + } + return connections.size(); + } + + /** + * erstellt das Modell einer Kreuzungs mit den internen Verbindungen zwischen Einfahrtswegen und Ausfahrtswegen + * @param crossroadID - globale KreuzungsID + * @return + */ + public Crossroad innerconnectionForCrossroad(int crossroadID){ + HashMap inputWays = getInputWays(crossroadID); + HashMap outputWays = getOutputWays(crossroadID); + + if(inputWays.size()==0){ + System.out.println("Keine Einfahrtswege"); + return null; + } + + Crossroad crossroad = new Crossroad(crossroadID,this); + crossroad.setInputWays(inputWays); + crossroad.setOutputWays(outputWays); + + // Verbindung innerhalb der Kreuzung + HashMap connectedOutputWays; + for (Map.Entry way : inputWays.entrySet()) { + connectedOutputWays = getConnectedOutputWays(crossroadID, way.getValue(), way.getKey()); + if(connectedOutputWays==null) { + continue; + } + for (Map.Entry outputWay : connectedOutputWays.entrySet()) { + crossroad.setOutputWay(way.getKey(), outputWay.getKey()); + } + } + return crossroad; + } + + /** + * liefert für einen Einfahrtsweg alle Ausfahrtswege die innerhalb der Kreuzung zu erreichen sind + * @param crossroadID - globale Kreuzungs-ID + * @param wayID - OSMWay-ID + * @param wayDirection - Direction des Einfahrtsweges + * @return + */ + public HashMap getConnectedOutputWays(int crossroadID, int wayID, CardinalDirection wayDirection) { + List sensors = getSensors(crossroadID, wayID); + HashMap outputWaysCrossroad = new HashMap<>(); + HashMap outputWaysSensor; + CardinalDirection cd; + + // Für alle Sensoren auf den Einfahrtsweg + for (Sensor sensor : sensors) { + outputWaysSensor = getOutputWays(sensor.getSensorID(), crossroadID); // Abbiegemöglichkeiten des Sensors + for (Map.Entry integer : outputWaysSensor.entrySet()) { + cd = transposeDirection(wayDirection, integer.getKey()); + if(!outputWaysCrossroad.containsKey(cd)) + outputWaysCrossroad.put(cd, integer.getValue()); + } + } + return (outputWaysCrossroad.size()>0) ? outputWaysCrossroad : null; + } + + /** + * übersetzt Himmelsrichtung und Abbiegemöglickeiten in neue Himmelsrichtung + * @param inDir - eigende Himmelsrichtung + * @param goDir - Abbiegerichtung + * @return - ausgehende Himmelsrichtung + */ + public CardinalDirection transposeDirection (CardinalDirection inDir, String goDir) { + String[] directions = new String[]{"LEFT","STRAIGHT"}; + switch (inDir) { + case NORTH: + if(goDir.equals(directions[0])) + return CardinalDirection.EAST; + else if(goDir.equals(directions[1])) + return CardinalDirection.SOUTH; + else + return CardinalDirection.WEST; + case EAST: + if(goDir.equals(directions[0])) + return CardinalDirection.SOUTH; + else if(goDir.equals(directions[1])) + return CardinalDirection.WEST; + else + return CardinalDirection.NORTH; + case SOUTH: + if(goDir.equals(directions[0])) + return CardinalDirection.WEST; + else if(goDir.equals(directions[1])) + return CardinalDirection.NORTH; + else + return CardinalDirection.EAST; + default: + if(goDir.equals(directions[0])) + return CardinalDirection.NORTH; + else if(goDir.equals(directions[1])) + return CardinalDirection.EAST; + else + return CardinalDirection.SOUTH; + } + } + + /** + * liefert den Name den Kreuzung mit übergebener ID in der Datenbank + * @param crossroadID + * @return + */ + public String getCrossroadName(int crossroadID) { + String selectStmt = "SELECT REALNAME FROM jee_crmodel_CrossroadDim WHERE ID = " + crossroadID; + Statement stmt; + try { + stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery(selectStmt); + while(rs.next()){ + return rs.getString("REALNAME"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return "Not Found"; + } + + /** + * wandelt ein DateTime in eine SQL-konforme Stringrepräsentation um. + * @param dateTime + * @return + */ + public static String toSql(DateTime dateTime) { + return new Timestamp( dateTime.getMillis() ).toString(); + } + + /** + * schließt die Verbindung zur Datenbank + */ + public void disconnect() { + try { + con.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * liefert die Knoten für das SensorModell, speichert diese für weitere Abfragen in HashMap sensorModelNodes + * @return Liste von Knoten mit NODE_ID als Label und Key in sensorModelNodes + */ + public List getSensorsForDNA() { + System.out.println("Erstelle den Graph ... "); + List nodes = new ArrayList(); + try { + Statement stmt = con.createStatement(); + String statementString; + statementString = "SELECT SG.*, ID as INPUT_WAY_ID FROM (SELECT * FROM mw_SensorGlobal_bak) SG LEFT JOIN (SELECT * FROM mw_InputWaysGlobal) IWG ON SG.WAY_ID = IWG.wayID AND SG.CROSSROAD_ID = IWG.crossroadID"; + ResultSet rs = stmt.executeQuery(statementString); + int label; + + while (rs.next()) { + label = rs.getInt("NODE_ID"); + nodes.add(gds.newNodeInstance(label)); + sensorModelNodes.put(label, new SensorModelNode(label, !rs.getBoolean("SENSOR_TYPE"),rs.getInt("INPUT_WAY_ID"),CardinalDirection.valueOf(rs.getString("DIRECTION")))); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + return nodes; + } + + /** + * liefert das Gewicht für einen Knoten mit Sensormodell + * @param nodeID - globale KnotenID im Sensormodel (kann realer oder virtueller Sensor sein) + * @param from - Startzeitpunkt der Aggregation + * @param to - Endzeitpunkt der Aggregation + * @param timestemp - Zeitstempel für den das Gewicht berechnet wird + * @return + */ + public double[] getSensorModelWeight(int nodeID,DateTime from, DateTime to,int timestemp){ + + if(sensorModelNodes.containsKey(nodeID)){ + SensorModelNode sensorModelNode = sensorModelNodes.get(nodeID); + // Sensorknoten ist ein realer Sensor, Gewicht wurde bereits für alle realen Sensoren vorberechnet + if(sensorModelNode.isReal()){ + if(sensorModelNode.getTimestep()==timestemp){ + return sensorModelNode.getWeight(); + } + else{ + System.out.println("Not found"); + double[] weight = new double[]{0,0,0}; + sensorModelNode.setWeight(weight, timestemp); + return weight; + } + } + //Sensorknoten ist virtueller Sensor, Gewicht wird wie beim Wegemodell abgefragt und in SensorModelNode zwischengespeichert + else { + int inputWayID = sensorModelNode.getInputWayID(); + if(inputWayID>0){ + double[] weight = getInputWayWeight(inputWayID, from, to); + sensorModelNode.setWeight(weight, timestemp); + return weight; + } + else + return new double[]{0,0,0}; + } + } + else + return new double[]{0,0,0}; + } + + /** + * liefert die Gewichte für den Einfahrtsweg + * @param inputWayID + * @param timestamp + * @return [0] = count, [1] = load, [2] = count/maxCount + */ + public double[] getInputWayWeight(int inputWayID, DateTime timestamp) { + return getInputWayWeight(inputWayID, timestamp, timestamp.plusMinutes(5)); + } + + /** + * liefert die Gewichte für den Einfahrtsweg + * @param inputWayID + * @param timestamp + * @return Index 0: count/maxCount, Index 1: load + */ + public double[] getInputWayWeight(int inputWayID, DateTime from, DateTime to) { + //leeres Intervall auf Minimallänge setzen + if(from.equals(to)){ + to = from.plusMinutes(1); + } + + double count =0; + double load = 0; + + // Nachladen von Maximalwerten + if(!maxValuesInputWays.containsKey(inputWayID)){ + maxValuesInputWays.put(inputWayID, getMaximalWeightInputWay(inputWayID) ); + } + String statementString = null; + try { + int[] inputData = inputWays.get(inputWayID); + int crossroadID = inputData[1]; + Statement stmt = con.createStatement(); + // Selection des Einfahrtsweges (neueste Tabelle) + String inputWay = "SELECT * FROM mw_InputWaysGlobal_bak2 IWG WHERE IWG.ID ='"+inputWayID+"'"; + // Selection der Sensordaten für den vorgegebenen Zeitraum + String rawData = "SELECT * FROM jee_trafficlight_rawevents RE WHERE DATETIME < '"+toSql(to)+"' AND DATETIME>='"+toSql(from)+"'"; + // Selection der für die Gewichtsberechnung relevanten Sensoren + String rawSensors = "SELECT * FROM jee_crmodel_SensorDim SENSOR_DIM WHERE CROSSROAD_ID ='"+crossroadID+"'"; + // Selection der frontSensoren + String frontSensors = "SELECT * FROM mw_SensorConnection FR WHERE FR.FRONT_BACK = 0"; + // Selection aller benätigten Sensoren + String sensors = "SELECT SENSORS.*,DATETIME,cr_count,cr_load FROM (SELECT FRONT_AND_BACK.* FROM (SELECT S1.*, CSVOFFSET FROM (SELECT ID AS INPUTWAY_ID, IWG.wayID AS OSMWAY_ID, IWG.crossroadID AS CROSSROAD_ID, crossroadName AS CROSSROAD_NAME, sensorID AS SENSOR_ID, sensorName AS SENSOR_NAME FROM ("+inputWay+") IWG LEFT JOIN mw_SensorWays_bak SW ON IWG.wayID = SW.wayID AND IWG.crossroadID= SW.crossroadID) S1 JOIN ("+rawSensors+") S2 ON S1.SENSOR_ID = S2.ID) FRONT_AND_BACK JOIN ("+frontSensors+") ONLY_FRONT ON FRONT_AND_BACK.SENSOR_ID = ONLY_FRONT.SENSOR_ID"; + // Abfrage des Gewichts aus den zuvor selektierten Daten + statementString = "SELECT SUM(ANZAHL)/COUNT(ANZAHL),SUM(BELEGUNG)/COUNT(BELEGUNG) FROM (SELECT SUM(cr_count) as ANZAHL, SUM(cr_load)/COUNT(cr_load) as BELEGUNG, DATETIME FROM ("+sensors+") SENSORS LEFT JOIN ("+rawData+") EVENTS_DAY ON SENSORS.CROSSROAD_NAME = EVENTS_DAY.CROSSROAD AND SENSORS.CSVOFFSET=EVENTS_DAY.CSVOFFSET) FINAL GROUP BY DATETIME) GROUPED"; + ResultSet rs = stmt.executeQuery(statementString); + if(rs.first()){ + count=rs.getDouble(1); + load=rs.getDouble(2); + } + else + System.out.println("ERROR - " +statementString); + if(count == 0 && load == 0){ + System.out.println("InputWayWeight ist 0/0/0"); + } + } catch (SQLException e) { + e.printStackTrace(); + } + double savedMax = maxValuesInputWays.get(inputWayID)[0]; // maxCount + double countNorm = savedMax> 0 ? count/savedMax : 0; // keine Normierung wegen div0 + return new double[]{count,load,countNorm*100}; + } + + /** + * Liefert TRUE, wenn es sich um einen realen Sensor handel, sonst FALSE + * @param nodeID - globale KnotenID im Sensormodell + * @return + */ + public boolean getSensorType(int nodeID){ + return sensorModelNodes.get(nodeID).isReal(); + } + + /** + * liefert die Werte für alle tatsächlichen Sensoren + * @param from - Startzeitpunkt der Aggregation + * @param to - Endzeitpunkt der Aggreagtion + * @return + */ + public void getSensorWeights(DateTime from, DateTime to,int timestemp){ + try { + Statement stmt = con.createStatement(); + String statementString; + // Selection der betrachteten Sensordaten + String rawData = "SELECT * FROM jee_trafficlight_rawevents RE WHERE DATETIME < '"+toSql(to)+"' AND DATETIME >= '"+toSql(from)+"'"; + // Selection der betrachteten Sensoren aus dem Modell + String realSensors = "SELECT * FROM mw_SensorGlobal SG WHERE SG.SENSOR_TYPE=0"; + // Selection für die Berechnung des Gewichts + String endSelection = "NODE_ID,SUM(cr_count)/COUNT(cr_count) as ANZAHL, SUM(cr_load)/COUNT(cr_load) as BELEGUNG, SENSOR_ID,SENSOR_NAME,WAY_ID,CROSSROAD_ID,CROSSROAD_NAME,SENSOR_TYPE,CSVOFFSET"; + statementString = "SELECT "+endSelection+" FROM (SELECT NODE_ID,SENSOR_ID,SENSOR_NAME,WAY_ID,CROSSROAD_ID,CROSSROAD_NAME,SENSOR_TYPE,SENSORS.CSVOFFSET,cr_count,DATETIME,cr_load FROM (SELECT NODES.*,CSVOFFSET FROM ("+realSensors+") NODES JOIN jee_crmodel_SensorDim SD ON NODES.SENSOR_ID = SD.ID) SENSORS LEFT JOIN ("+rawData+") RE ON SENSORS.CSVOFFSET = RE.CSVOFFSET AND SENSORS.CROSSROAD_NAME = RE.CROSSROAD) RESULT GROUP BY NODE_ID "; + ResultSet rs = stmt.executeQuery(statementString); + while(rs.next()){ + if(!rs.getBoolean("SENSOR_TYPE")){ + double[] max = maxValuesSensors.get(rs.getInt("NODE_ID")); + if(max == null) + max = new double[]{10,0}; + sensorModelNodes.put(rs.getInt("NODE_ID"), new SensorModelNode(rs.getInt("NODE_ID"),true,new double[]{rs.getDouble("ANZAHL"), rs.getDouble("BELEGUNG"),(rs.getDouble("ANZAHL")/max[0])*100},timestemp)); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + /** + * liefert die Verbindungen für das Sensorenmodell (Zwischen Virtuellen Sensoren zu realen Sensoren + * und von realen Sensoren zu virtuellen Sensoren ) + * @return + */ + public List getSensorConnectionForDNA() { + List edges = new ArrayList<>(); + try { + Statement vStmt = con.createStatement(); + String statementString; + + statementString = "SELECT * FROM mw_SensorConnection_Global"; + ResultSet sensor_con = vStmt.executeQuery(statementString); + while(sensor_con.next() ) { + edges.add(new EdgeContainer(sensor_con.getInt("FROM_NODE"), sensor_con.getInt("TO_NODE"))); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return edges; + } + + /** + * schreibt eine Verbindung zwischen realem Sensor und virtuellem Sensor in die Datenbank + * @param s + */ + public void writeSensorConnection(Sensor s) { + try { + Statement stmt = con.createStatement(); + String insertString; + + int wayID; + int crossroadID; + for (InputWay connectedInputWay : s.getConnections().values()) { + + wayID = connectedInputWay.getWayID(); + crossroadID = connectedInputWay.getCrossroadID(); + + // realer Sensor + String from = "SELECT NODE_ID as FROM_NODE_ID FROM mw_SensorGlobal WHERE mw_SensorGlobal.SENSOR_ID ='"+s.getSensorID()+"' AND CROSSROAD_ID = '"+s.getCrossroadID()+"'"; + // virtueller Sensor + String to = "SELECT NODE_ID as TO_NODE_ID FROM mw_SensorGlobal SG WHERE SG.SENSOR_TYPE=1 AND SG.CROSSROAD_ID = '"+crossroadID+"' AND SG.WAY_ID = '"+wayID+"'"; + insertString="INSERT IGNORE INTO mw_SensorGlobalConnection SELECT * FROM ("+from+") A , ("+to+") B "; + stmt.executeUpdate(insertString); + } + } catch (SQLException e) { + e.printStackTrace(); + } + + } + + + /** + * setzt die temporär deaktiveren Kanten für die Zwischenspeicherung + * @param disabledEdges + */ + public void setDisabledEdges(HashMap disabledEdges){ + this.disabledEdges=disabledEdges; + } + /** + * setzt die temporär deaktiveren Kanten für die Zwischenspeicherung für das Wegemodell + * @param disabledEdges + */ + public void setDisabledEdgesInputWay(HashMap> disabledEdges){ + this.disabledEdgesInputWay=disabledEdges; + } + + /** + * liefert die temporär deaktiveren Kanten aus der Zwischenspeicherung + * @return + */ + public HashMap getDisabledEdges(){ + return disabledEdges; + } + + /** + * liefert die temporär deaktiveren Kanten aus der Zwischenspeicherung für das Wegemodell + * @return + */ + public HashMap> getDisabledEdgesInputWay(){ + return disabledEdgesInputWay; + } + + + /** + * liefert das statische Gewicht im Wegemodell für die Initialisierung + * @param index - Knotenindex + * @param trafficUpdate - beinhaltet die statischen Daten + * @return + */ + public double[] getInputWayWeightStaticInit(int index,TrafficUpdate trafficUpdate) { + double count = trafficUpdate.getInitCount(); + double load = trafficUpdate.getInitLoad(); + double savedMax = (maxValuesInputWays.containsKey(index)) ?(double) maxValuesInputWays.get(index)[0] : 0; + double countNorm = savedMax> 0 ? Double.valueOf(count)/savedMax : 0; + return new double[]{count,load,countNorm*100}; + } + + /** + * liefert das statische Gewicht im Wegemodell für den Batch + * @param index - Knotenindex + * @param trafficUpdate - beinhaltet die statischen Daten + * @return + */ + public double[] getInputWayWeightStaticBatch(int index,TrafficUpdate trafficUpdate) { + double count = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitCount()+trafficUpdate.getUpdateCount())/(trafficUpdate.getSleepTillUpdate()+1); + double load = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitLoad()+trafficUpdate.getUpdateLoad())/(trafficUpdate.getSleepTillUpdate()+1); + double savedMax = (maxValuesInputWays.containsKey(index)) ? maxValuesInputWays.get(index)[0] : 0; + double countNorm = savedMax> 0 ? count/savedMax : 0; + return new double[]{count,load,countNorm*100}; + } + + /** + * liefert das statische Gewicht im Sensormodell für die Initialisierung + * @param index - Knotenindex + * @param trafficUpdate - beinhaltet die statischen Daten + * @return + */ + public double[] getSensorModelWeightStaticInit(int index,TrafficUpdate trafficUpdate) { + if(trafficUpdate.getModus()==0){ + if(sensorModelNodes.containsKey(index)){ + SensorModelNode sensorModelNode = sensorModelNodes.get(index); + double count = trafficUpdate.getInitCount(); + double load = trafficUpdate.getInitLoad(); + double countNorm; + if(getSensorType(index)){ + if(maxValuesSensors.containsKey(index)) + countNorm = (count/maxValuesSensors.get(index)[0]); + else + countNorm = (count/50); + } + else{ + double savedMax = (maxValuesInputWays.containsKey(sensorModelNode.getInputWayID())) ? maxValuesInputWays.get(sensorModelNode.getInputWayID())[0] : 0; + countNorm = savedMax> 0 ? count/savedMax : 0; + } + return new double[]{count,load,countNorm*100}; + } + else + return new double[]{0,0,0}; + } + else{ + return new double[]{-1,-1,trafficUpdate.getInitUtilization()*100}; + } + } + + /** + * liefert das statische Gewicht im Sensormodell für den Batch + * @param index - Knotenindex + * @param trafficUpdate - beinhaltet die statischen Daten + * @return + */ + public double[] getSensorModelWeightStaticBatch(int index,TrafficUpdate trafficUpdate) { + if(trafficUpdate.getModus()==0){ + if(sensorModelNodes.containsKey(index)){ + SensorModelNode sensorModelNode = sensorModelNodes.get(index); + if(sensorModelNode.isReal()){ + // Count-Wert des Sensors + double count = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitCount()+trafficUpdate.getUpdateCount())/(trafficUpdate.getSleepTillUpdate()+1); + // Load-Wert des Sensors + double load = (trafficUpdate.getSleepTillUpdate()*trafficUpdate.getInitLoad()+trafficUpdate.getUpdateLoad())/(trafficUpdate.getSleepTillUpdate()+1); + // Maximalwert des sensors (hier statisch) + double savedMax = maxValuesSensors.get(sensorModelNode.getNodeID())[0]; + // Normierter Count-Wert + double countNorm = savedMax> 0 ? count/savedMax : 0; + return new double[]{count,load,countNorm*100}; + } + else + return getInputWayWeightStaticBatch(sensorModelNode.getInputWayID(), trafficUpdate); + } + else + return new double[]{0,0,0}; + } + else{ + return new double[]{-1,-1,trafficUpdate.getUpdateUtilization()*100}; + } + } + +} diff --git a/src/dna/graph/generators/traffic/EdgeContainer.java b/src/dna/graph/generators/traffic/EdgeContainer.java new file mode 100644 index 00000000..b17fda14 --- /dev/null +++ b/src/dna/graph/generators/traffic/EdgeContainer.java @@ -0,0 +1,67 @@ +package dna.graph.generators.traffic; + +import java.util.Arrays; + +/** + * Container-Klasse für Edge-Information + * @author Maurice + * + */ +public class EdgeContainer { + private int from; + private int to; + + /** + * Konstruktur für den EdgeContainer + * @param from - Startknoten der Kante + * @param to - Endknoten der Kante + */ + public EdgeContainer(int from, int to){ + this.from = from; + this.to = to; + } + + /** + * liefert den HashCode des Containers, abgeleitet aus der Array-Darstellung + */ + public int hashCode(){ + return Arrays.hashCode(new int[]{from,to}); + } + + /** + * vergleicht das Objekt mit einem übergebenen Objekt + * @return true, wenn Startknoten und Endknoten identisch, sonst false + */ + public boolean equals(Object obj) { + if( obj instanceof EdgeContainer){ + EdgeContainer ec = (EdgeContainer) obj; + return Arrays.equals(new int[]{from, to},new int[]{ec.from,ec.to}); + } + else + return false; + } + + /** + * Ausgabe für die manuelle Kontrolle + * @return + */ + public String toString(){ + return "FROM:"+from+"\tTO:"+to; + } + + /** + * liefert den Startknoten + * @return + */ + public int getFrom(){ + return from; + } + + /** + * liefert den Zielknoten + * @return + */ + public int getTo(){ + return to; + } +} diff --git a/src/dna/graph/generators/traffic/InputWay.java b/src/dna/graph/generators/traffic/InputWay.java new file mode 100644 index 00000000..3840e37a --- /dev/null +++ b/src/dna/graph/generators/traffic/InputWay.java @@ -0,0 +1,64 @@ +package dna.graph.generators.traffic; + +import java.util.Arrays; + +/** + * Containerklasse für einen Einfahrtsweg + * @author Maurice + * + */ +public class InputWay { + + private int wayID; // OSM-WayID + private int crossroadID; // globale Kreuzungs-ID + + public InputWay(int wayID, int crossroadID) { + this.wayID=wayID; + this.crossroadID=crossroadID; + } + + /** + * Kontrollausgbae + */ + public String toString(){ + return "Einfahrtsweg: wayID:"+String.valueOf(wayID) + "\t crossroadID:"+crossroadID; + } + + /** + * liefert den HashCode des Einfahrtsweges basierend auf der Array-Darstellung + */ + public int hashCode(){ + return Arrays.hashCode(new int[]{wayID,crossroadID}); + } + + /** + * liefert die OSM-ID für den Weg + * @return + */ + public int getWayID(){ + return wayID; + } + + /** + * liefert die KreuzungsID für den Weg + * @return + */ + public int getCrossroadID(){ + return crossroadID; + } + + /** + * vergleicht das Objekt mit dem übergebenen Objekt auf Gleichheit + * @param obj, zu vergleichendes Objekt + * @return true, wenn das übergebene Objekt den gleichen Einfahrtsweg repräsentiert + */ + public boolean equals(Object obj) { + if(obj instanceof InputWay){ + InputWay inputWay = (InputWay) obj; + return Arrays.equals(new int[]{wayID,crossroadID}, new int[]{inputWay.wayID,inputWay.crossroadID}); + } + else + return false; + } + +} diff --git a/src/dna/graph/generators/traffic/InputWayConnection.java b/src/dna/graph/generators/traffic/InputWayConnection.java new file mode 100644 index 00000000..b1abcc03 --- /dev/null +++ b/src/dna/graph/generators/traffic/InputWayConnection.java @@ -0,0 +1,78 @@ +package dna.graph.generators.traffic; + +/** + * Container-Klasse für Verbindungen zwischen Einfahrtswegen + * @author Maurice + * + */ +public class InputWayConnection { + private int fromCrossroad; + private int fromWayID; + private CardinalDirection fromWayDirection; + private int toCrossroad; + private int toWayID; + private CardinalDirection toWayDirection; + + + public InputWayConnection(int fromCrossroad, int fromWayID,CardinalDirection fromWayDirection, int toCrossroad, int toWayID,CardinalDirection toWayDirection) { + this.fromCrossroad=fromCrossroad; + this.fromWayID=fromWayID; + this.toCrossroad=toCrossroad; + this.toWayID=toWayID; + } + + /** + * liefert die Startkreuzung + * @return + */ + public int getFromCrossroad(){ + return fromCrossroad; + } + + /** + * liefert den Startweg + * @return + */ + public int getFromWayID(){ + return fromWayID; + } + + /** + * liefert die Startrichtung + * @return + */ + public CardinalDirection getFromWayDirection(){ + return fromWayDirection; + } + + /** + * liefert die Zielkreuzung + * @return + */ + public int getToCrossroad(){ + return toCrossroad; + } + + /** + * liefert den Zielweg + * @return + */ + public int getToWayID(){ + return toWayID; + } + + /** + * liefert die Richtung des Zielweges + * @return + */ + public CardinalDirection getToWayDirection(){ + return toWayDirection; + } + + /** + * Kontrollausgabe für die Verbindung von Wegen + */ + public String toString() { + return "Connected " + fromWayID + " on " +fromCrossroad + " with " +toWayID + " on " + toCrossroad; + } +} diff --git a/src/dna/graph/generators/traffic/Sensor.java b/src/dna/graph/generators/traffic/Sensor.java new file mode 100644 index 00000000..e2eb81a1 --- /dev/null +++ b/src/dna/graph/generators/traffic/Sensor.java @@ -0,0 +1,128 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * Container-Klasse für einen realen Sensor + * @author Maurice + * + */ +public class Sensor { + private int sensorID; + private String sensorName; + private int crossroadID; + private String crossroadName; + private int wayID; + private Set outputDiretions; + private HashMap connections; + + /** + * Konstruktur für die nachträgliche Berechnung + * @param sensorID + * @param sensorName + * @param crossroadID + * @param crossroadName + * @param wayID + * @param outputDirections + */ + public Sensor(int sensorID, String sensorName, int crossroadID, String crossroadName, int wayID,Set outputDirections){ + this.sensorID=sensorID; + this.sensorName=sensorName; + this.crossroadID=crossroadID; + this.crossroadName=crossroadName; + this.wayID=wayID; + this.outputDiretions=outputDirections; + } + + /** + * Konstruktur für die Nutzung als Container + * @param sensorID + * @param sensorName + * @param crossroadID + * @param crossroadName + * @param wayID + */ + public Sensor(int sensorID, String sensorName, int crossroadID, String crossroadName, int wayID){ + this.sensorID=sensorID; + this.sensorName=sensorName; + this.crossroadID=crossroadID; + this.crossroadName=crossroadName; + this.wayID=wayID; + } + /** + * liefert die globale ID des Sensors + * @return + */ + public int getSensorID(){ + return sensorID; + } + + /** + * liefert den Namen des Sensors + * @return + */ + public String getSensorName(){ + return sensorName; + } + + /** + * liefert die globale Kreuzungs-ID + * @return + */ + public int getCrossroadID(){ + return crossroadID; + } + + /** + * liefert den Namen der Kreuzung + * @return + */ + public String getCrossroadName(){ + return crossroadName; + } + + public int getWayID(){ + return wayID; + } + + /** + * berechnet die Verbindungen zwischen den Ausfahrtswegen des Sensors und den Einfahrtswegen benachbarter Kreuzungen + * @param outputConnection Abbiegemöglichkeiten des Sensors + * @return Verbindungen mit Einfahrtswegen + */ + public HashMap calculateConnections(HashMap outputConnection) { + HashMap connections = new HashMap<>(); + // Über alle Abbiegemöglichkeiten + for (CardinalDirection output : outputDiretions) { + // Ausfahrtsweg ist mit Einfahrtsweg benachbarter Kreuzung verbunden + if(outputConnection.containsKey(output)) + connections.put(output, outputConnection.get(output)); + } + this.connections=connections; + return connections; + } + + /** + * liefert die berechneten Verbindungen aus {@link #calculateConnections(HashMap)} + * @return + */ + public HashMap getConnections() { + return connections; + } + + + /** + * Kontrollausgabe + */ + public void printConnection() { + System.out.println("Verbindungen von:\t"+sensorID+"("+sensorName+") on " +crossroadID+"("+crossroadName+")"); + for (Map.Entry connection : connections.entrySet()) { + System.out.println("\t\t"+connection.getKey()+"\t"+connection.getValue()); + } + + } + + +} diff --git a/src/dna/graph/generators/traffic/SensorModelNode.java b/src/dna/graph/generators/traffic/SensorModelNode.java new file mode 100644 index 00000000..5d5659a3 --- /dev/null +++ b/src/dna/graph/generators/traffic/SensorModelNode.java @@ -0,0 +1,69 @@ +package dna.graph.generators.traffic; + + +public class SensorModelNode { + private double[] weight; + private boolean isReal; + private int nodeID; + private int timestep; + private int inputWayID; + private CardinalDirection direction; + + public SensorModelNode(int nodeID, boolean isReal){ + this.nodeID=nodeID; + this.isReal=isReal; + this.timestep=-1; + } + + public SensorModelNode(int nodeID, boolean isReal,double[] weight,int timestep){ + this.nodeID=nodeID; + this.isReal=isReal; + this.weight=weight; + this.timestep=timestep; + } + + public SensorModelNode(int nodeID, boolean isReal,double[] weight,int timestep,int inputWayID){ + this.nodeID=nodeID; + this.isReal=isReal; + this.weight=weight; + this.timestep=timestep; + this.inputWayID = inputWayID; + } + + public SensorModelNode(int nodeID, boolean isReal,int inputWayID, CardinalDirection direction){ + this.nodeID=nodeID; + this.isReal=isReal; + this.inputWayID = inputWayID; + this.direction = direction; + this.timestep=-1; + } + + public double[] getWeight(){ + return weight; + } + + public void setWeight(double[] weight, int timestep){ + this.weight=weight; + this.timestep=timestep; + } + + public boolean isReal(){ + return isReal; + } + + public int getNodeID(){ + return nodeID; + } + + public int getTimestep(){ + return timestep; + } + + public int getInputWayID(){ + return inputWayID; + } + + public CardinalDirection getDirection(){ + return direction; + } +} diff --git a/src/dna/graph/generators/traffic/TrafficConfig.java b/src/dna/graph/generators/traffic/TrafficConfig.java new file mode 100644 index 00000000..6b2b77c0 --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficConfig.java @@ -0,0 +1,223 @@ +package dna.graph.generators.traffic; + + +import org.joda.time.DateTime; + +import dna.updates.generators.traffic.Helpers; + +public class TrafficConfig { + + private DateTime initDateTime; + private int stepSize; + + // Auswahl des Modells und Modus + private TrafficModel model; + private String graphGeneratorName; + private String batchGeneratorName; + private TrafficModi modus; + private double treshold; // Schwellwert, ab dem ein Knoten �berlastet ist + + // Parameter f�r Tages-Modus + private boolean[] daySelection; + private int timeRange; + private DateTime holidayStart = new DateTime(2014,10,6,7,0,0); + private int observationWeeks = 1; + + private int[] nodesFilter; + + // Parameter f�r die Simulation + private TrafficUpdate trafficUpdate; + + /** + * Basis-Konstruktor + * @param modus + * @param nodesFilter + * @param initDateTime + */ + private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime ){ + this.modus = modus; + this.model = model; + this.treshold = treshold; + this.nodesFilter = nodesFilter; + this.initDateTime = initDateTime; + + // Namensgenerierung + + switch (model) { + case CrossroadModel: + graphGeneratorName = "CrossroadGraph"; + batchGeneratorName = "CrossroadBatch"; + break; + + case WayModel: + graphGeneratorName = "InputWayGraph"; + batchGeneratorName = "InputWayBatch"; + break; + + case SensorModel: + graphGeneratorName = "SensorGraph"; + batchGeneratorName = "SensorBatch"; + break; + + default: + graphGeneratorName = "DefaultTrafficGraph"; + batchGeneratorName = "DefaultTrafficBatch"; + break; + } + } + + /** + * Konstruktor für den Continuous-Modus + * @param modus + * @param nodesFilter + * @param initDateTime + * @param stepsize + */ + private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int stepsize){ + this(modus,model,treshold,nodesFilter,initDateTime); + this.stepSize = stepsize; + } + /** + * Konstruktor für den DayTimeRange-Modus und den Aggregation-Modus + * @param modus + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param timeRange + * @param daySelection + * @param holidayStart + */ + private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){ + this(modus,model,treshold,nodesFilter,initDateTime); + this.timeRange = timeRange; + this.daySelection = daySelection; + this.holidayStart = holidayStart; + } + + /** + * Konsruktor für den Simulations-Modus + * @param modus + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param trafficUpdate + */ + private TrafficConfig(TrafficModi modus, TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, TrafficUpdate trafficUpdate){ + this(modus,model,treshold,nodesFilter,initDateTime); + this.trafficUpdate = trafficUpdate; + } + + + /** + * liefert eine gültige TrafficConfig für die Verwendung des Continous-Modus + * @param model + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param stepsize + * @return + */ + public static TrafficConfig getContinousConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int stepSize){ + return new TrafficConfig(TrafficModi.Continuous,model,treshold, nodesFilter, initDateTime, stepSize); + } + + /** + * liefert eine gültige TrafficConfig für die Verwendung des DayTimeRange-Modus + * @param model + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param timeRange + * @param daySelection + * @param holidayStart + * @return + */ + public static TrafficConfig getDayTimeRangeConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){ + return new TrafficConfig(TrafficModi.DayTimeRange, model, treshold, nodesFilter, initDateTime, timeRange, daySelection, holidayStart); + } + + /** + * liefert eine gültige TrafficConfig für die Verwendung des Aggregations-Modus + * @param model + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param holidayStart2 + * @param daySelection2 + * @param timeRange2 + * @return + */ + public static TrafficConfig getAggregationConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, int timeRange, boolean[] daySelection, DateTime holidayStart){ + return new TrafficConfig(TrafficModi.Aggregation, model, treshold, nodesFilter,initDateTime, timeRange, daySelection,holidayStart); + } + + /** + * liefert eine gültige TrafficConfig für die Verwendung des Simulations-Modus + * @param model + * @param treshold + * @param nodesFilter + * @param initDateTime + * @param trafficUpdate + * @return + */ + public static TrafficConfig getSimulationConfig(TrafficModel model, double treshold, int[] nodesFilter, DateTime initDateTime, TrafficUpdate trafficUpdate){ + return new TrafficConfig(TrafficModi.Simulation, model, treshold, nodesFilter, initDateTime, trafficUpdate); + } + + public TrafficModel getModel(){ + return model; + } + + public TrafficModi getModus(){ + return modus; + } + + public String getGraphName(){ + return graphGeneratorName; + } + + public String getBatchName(){ + return batchGeneratorName; + } + + public DateTime getInitDateTime(){ + return initDateTime; + } + + public int getStepSize(){ + return stepSize; + } + + public int getTimeRange(){ + return timeRange; + } + + public TrafficUpdate getTrafficUpdate(){ + return trafficUpdate; + } + + public int[] getNodesFilter(){ + return nodesFilter; + } + + public double getTreshold(){ + return treshold; + } + + public DateTime getHolidayStart(){ + return holidayStart; + } + + public boolean[] getDaySelection(){ + return daySelection; + } + + public int getOberservationDays(){ + if(modus == TrafficModi.Aggregation) + return Helpers.weekToDay(observationWeeks, daySelection); + else + return 1; + + } + +} diff --git a/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java new file mode 100644 index 00000000..5b2d3070 --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficCrossroadGraphGenerator.java @@ -0,0 +1,165 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.List; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.datastructures.GraphDataStructure; +import dna.graph.edges.Edge; +import dna.graph.generators.GraphGenerator; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.nodes.INode; +import dna.graph.nodes.Node; +import dna.graph.weights.Double3dWeight; +import dna.util.parameters.Parameter; + +public class TrafficCrossroadGraphGenerator extends GraphGenerator{ + + private DB db; + + // Allgemeine Parameter + private TrafficModi modus; + private DateTime initDateTime; + private int[] nodesFilter; + + // Continuous + private int stepsize; + + // Daytime-Range Aggregation + private int timeRange; + + // Simulation + private TrafficUpdate trafficUpdate; + + + public TrafficCrossroadGraphGenerator(String name, GraphDataStructure gds, DB db,long timeStampInit,TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate, int[] nodesFilter) { + this(name, null, gds,timeStampInit, 0, 0,db,modus,initDateTime,stepsize,timeRange,trafficupdate,nodesFilter); + } + + public TrafficCrossroadGraphGenerator(String name, Parameter[] params, + GraphDataStructure gds, long timestampInit, int nodesInit, + int edgesInit,DB db,TrafficModi modus,DateTime initDateTime,int stepsize,int timeRange,TrafficUpdate trafficUpdate, int[] nodesFilter) { + super(name, params, gds, timestampInit, nodesInit, edgesInit); + this.db= db; + this.modus=modus; + this.initDateTime=initDateTime; + this.stepsize = stepsize; + this.timeRange = timeRange; + this.trafficUpdate = trafficUpdate; + this.nodesFilter = nodesFilter; + } + + public TrafficCrossroadGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){ + super(tc.getGraphName(), null, gds, timeStampInit,0,0); + this.db = db; + this.modus = tc.getModus(); + this.initDateTime = tc.getInitDateTime(); + this.stepsize = tc.getStepSize(); + this.timeRange = tc.getTimeRange(); + this.trafficUpdate = tc.getTrafficUpdate(); + this.nodesFilter = tc.getNodesFilter(); + } + + @Override + public Graph generate() { + + Graph g = this.newGraphInstance(); + List nodes = null; + HashMap disabledEdges = new HashMap<>(); + + // Lade abstrakte Knoten gemäß dem NodesFilter + nodes = db.getCrossroadsForDNA(nodesFilter); + + CrossroadWeight crossroadWeight = null; + Node currentNode = null; + DirectedWeightedNode currentWeighted = null; + + // Berechne das Gewicht des abstrakten Knoten gemäß definiertem Modus + for (int i = 0; i < nodes.size(); i++) { + + currentNode = (Node) nodes.get(i); + if(currentNode instanceof DirectedWeightedNode) + currentWeighted = (DirectedWeightedNode) currentNode; + else{ + continue; + } + + switch (modus) { + + case Continuous: + crossroadWeight = db.getCrossroadWeight(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(stepsize),timestampInit); + break; + + case DayTimeRange: case Aggregation: + crossroadWeight = db.getCrossroadWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),timestampInit); + break; + + case Simulation: + crossroadWeight = db.getCrossroadWeightStaticInit(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(1),timestampInit,trafficUpdate); + break; + + default: + System.out.println("error - Modus nicht definiert"); + break; + + } + + double[] weight = crossroadWeight.getWeight(); + + if(modus == TrafficModi.DayTimeRange) + db.setMaximalWeightsCrossroadImproved(currentWeighted.getIndex(), weight[0], weight[1], initDateTime, timeRange); + + currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2])); + + g.addNode(currentWeighted); + + // Entferne die ueberlasteten Kanten + EdgeContainer ec = null; + for (Integer wayId : crossroadWeight.getOverladedEdges().keySet()) { + List edgesToRemove = db.getFromWays(currentWeighted.getIndex(), wayId); + if(edgesToRemove != null){ + for (int[] way : edgesToRemove) { + ec = new EdgeContainer(way[0], currentNode.getIndex()); + disabledEdges.put(ec, null); + } + } + } + } + + // Kanten + + List connection = db.getCrossroadConnectionForDNA(nodesFilter); + EdgeContainer current = null; + + Node fromNode; + Node toNode; + Edge e; + for (int i = 0; i < connection.size(); i++) { + + current = connection.get(i); + fromNode = g.getNode(current.getFrom()); + toNode = g.getNode(current.getTo()); + + if(fromNode!= null && toNode!=null) + e = gds.newEdgeInstance(fromNode, toNode); + else + continue; + + if(disabledEdges.containsKey(current)){ + disabledEdges.put(current, e); + } + else{ + e.connectToNodes(); + g.addEdge(e); + } + + } + + // Speichere die deaktiverten Kanten für den Batch in die DB-Klasse + db.setDisabledEdges(disabledEdges); + return g; + } + +} diff --git a/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java new file mode 100644 index 00000000..5bdb888e --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficInputWayGraphGenerator.java @@ -0,0 +1,190 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.datastructures.GraphDataStructure; +import dna.graph.edges.Edge; +import dna.graph.generators.GraphGenerator; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.nodes.INode; +import dna.graph.nodes.Node; +import dna.graph.weights.Double3dWeight; +import dna.util.parameters.Parameter; + +public class TrafficInputWayGraphGenerator extends GraphGenerator{ + + private DB db; + + // Allgemeine Parameter + private TrafficModi modus; + private DateTime initDateTime; + private int[] nodesFilter; + + // Continuous-Modus + private int stepSize; + + // DayTimeRange / Aggregation + private int timeRange; + private double treshold; + + // Simulation + private TrafficUpdate trafficUpdate; + + + private HashMap> disabledEdges = new HashMap<>(); + + + public TrafficInputWayGraphGenerator(String name, GraphDataStructure gds, DB db, long timeStamp, TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold, int[] nodesFilter) { + this(name, null, gds,timeStamp, 0, 0,db, modus,initDateTime,stepsize,timeRange,trafficupdate,treshold, nodesFilter); + } + + public TrafficInputWayGraphGenerator(String name, Parameter[] params, + GraphDataStructure gds, long timestampInit, int nodesInit, + int edgesInit,DB db,TrafficModi modus, DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold, int[] nodesFilter) { + super(name, params, gds, timestampInit, nodesInit, edgesInit); + this.db= db; + this.modus = modus; + this.initDateTime = initDateTime; + this.stepSize = stepsize; + this.timeRange = timeRange; + this.trafficUpdate = trafficupdate; + this.treshold = treshold; + this.nodesFilter = nodesFilter; + } + + /** + * Erstellt einen GraphGenerator für das WayModel für die übergebene TrafficConfig + * @param tc + * @param gds + * @param db + * @param timeStampInit + */ + public TrafficInputWayGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){ + super(tc.getGraphName(), null, gds, timeStampInit,0,0); + this.db = db; + this.modus = tc.getModus(); + this.initDateTime = tc.getInitDateTime(); + this.stepSize = tc.getStepSize(); + this.timeRange = tc.getTimeRange(); + this.trafficUpdate = tc.getTrafficUpdate(); + this.treshold = tc.getTreshold(); + this.nodesFilter = tc.getNodesFilter(); + } + + @Override + public Graph generate() { + Graph g = this.newGraphInstance(); + + + List nodes = null; + Set overloaded = new HashSet<>(); + + + // Knoten + + // Lade abstrakte Knoten gemäß NodesFilter + nodes = db.getInputWaysForDNA(nodesFilter); + + Node currentNode = null; + DirectedWeightedNode currentWeighted = null; + double[] weight = null; + + // Berechne für jeden abstrakten Knoten das Gewicht gemäß des ausgewählten Modus + for (int i = 0; i < nodes.size(); i++) { + currentNode = (Node) nodes.get(i); + + if(currentNode instanceof DirectedWeightedNode) + currentWeighted = (DirectedWeightedNode) currentNode; + else{ + continue; + } + + switch (modus) { + case Continuous: + weight = db.getInputWayWeight(currentWeighted.getIndex(), initDateTime, initDateTime.plusMinutes(stepSize)); + break; + + case DayTimeRange: case Aggregation: + weight = db.getInputWayWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange)); + break; + + case Simulation: + weight = db.getInputWayWeightStaticInit(currentWeighted.getIndex(),trafficUpdate); + break; + + default: + System.out.println("error - Modus nicht definiert @ TrafficInputwayGraphGenerator"); + break; + + } + + // Knoten ist überlastet + if(weight[2] > treshold){ + overloaded.add(currentWeighted.getIndex()); + } + + currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2])); + g.addNode(currentWeighted); + + } + + // Kanten + + // Lade die Kanten für die durch NodesFilter definierten Knoten + List connection = db.getInputWaysConnectionForDNA(nodesFilter); + + DirectedWeightedNode fromNode = null; + DirectedWeightedNode toNode = null; + Edge e = null; + EdgeContainer ec = null; + + // Prüfe für jede Kante, ob sie gültig oder überlastet ist, sortiere dementsprechend ein + for (int i = 0; i < connection.size(); i++) { + ec = connection.get(i); + fromNode = (DirectedWeightedNode) g.getNode(ec.getFrom()); + toNode = (DirectedWeightedNode) g.getNode(ec.getTo()); + + if(fromNode != null && toNode != null) + e = gds.newEdgeInstance(fromNode,toNode); + else + continue; + + // einer der Enknoten ist ueberlastet + if(overloaded.contains(fromNode.getIndex()) || overloaded.contains((toNode.getIndex()))){ + addEdge(fromNode.getIndex(),ec,e); + addEdge(toNode.getIndex(),ec,e); + } + // Gültige Kante + else{ + g.addEdge(e); + e.connectToNodes(); + } + } + // Zwischenspeichern der überlasteten Kanten in der DB + db.setDisabledEdgesInputWay(disabledEdges); + return g; + } + + /** + * fügt eine Kante in den Zwischenspeicher ein, der über die DB-Klasse an den Batch übergeben wird. + * @param index Knotenindex des Endknoten + * @param ec ContainerKlasse der Kante + * @param e Kante + */ + public void addEdge(int index,EdgeContainer ec, Edge e){ + if(disabledEdges.containsKey(index)) + disabledEdges.get(index).put(ec,e); + else{ + HashMap newEdgeList = new HashMap<>(); + newEdgeList.put(ec,e); + disabledEdges.put(index,newEdgeList); + } + } + +} diff --git a/src/dna/graph/generators/traffic/TrafficModel.java b/src/dna/graph/generators/traffic/TrafficModel.java new file mode 100644 index 00000000..82345aff --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficModel.java @@ -0,0 +1,5 @@ +package dna.graph.generators.traffic; + +public enum TrafficModel { + CrossroadModel, WayModel, SensorModel +} diff --git a/src/dna/graph/generators/traffic/TrafficModi.java b/src/dna/graph/generators/traffic/TrafficModi.java new file mode 100644 index 00000000..8d41c8a0 --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficModi.java @@ -0,0 +1,26 @@ +package dna.graph.generators.traffic; + +public enum TrafficModi { + /** + * Kontinuierlicher Modus, bei dem ausgehend von einem Startzeitpunkt, + * in jedem Batch ein Zeitschritt festgelegter Dauer addiert wird + */ + Continuous, + /** + * Tagesmodus, bei dem ausgehend von einem Startzeitpunkt und eines + * Zeitintervall, für jeden der durch daySelection ausgewählten Tage + * das entsprechende Intervall berechnet wird + */ + DayTimeRange, + /** + * Statischer Simulationsmodus, bei dem die Daten anhand des TrafficUpdate- + * Objekt geändert werden + */ + Simulation, + /** + * Aggregationmodus für den Vergleich, bei dem für den Batch die Tage eines + * festgelegten Zeitraums aggregiert werden, und dann ein Vergleichsmaß (z.b. + * Durchschnitt) berechnet wird + */ + Aggregation +} diff --git a/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java b/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java new file mode 100644 index 00000000..96433d33 --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficSensorGraphGenerator.java @@ -0,0 +1,186 @@ +package dna.graph.generators.traffic; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.datastructures.GraphDataStructure; +import dna.graph.edges.Edge; +import dna.graph.generators.GraphGenerator; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.nodes.INode; +import dna.graph.nodes.Node; +import dna.graph.weights.Double3dWeight; + +import dna.util.parameters.Parameter; + +public class TrafficSensorGraphGenerator extends GraphGenerator{ + + private DB db; + + // Allgemeine Parameter + private TrafficModi modus; + private DateTime initDateTime; + private double treshold; + + // Continous + private int stepsize; + + // DayTimeRange + private int timeRange; + + // Simulation + private TrafficUpdate trafficUpdate; + + + private HashMap> disabledEdges = new HashMap<>(); + + public TrafficSensorGraphGenerator(String name, GraphDataStructure gds, DB db,long timeStamp,TrafficModi modus,DateTime initDateTime, int stepsize,int timeRange,TrafficUpdate trafficupdate,double treshold) { + this(name, null, gds,timeStamp, 0, 0,db,modus,initDateTime,stepsize,timeRange,trafficupdate,treshold); + } + + public TrafficSensorGraphGenerator(String name, Parameter[] params, + GraphDataStructure gds, long timestampInit, int nodesInit, + int edgesInit,DB db, TrafficModi modus,DateTime initDateTime,int stepsize,int timeRange,TrafficUpdate trafficUpdate,double treshold) { + super(name, params, gds, timestampInit, nodesInit, edgesInit); + this.db= db; + this.modus = modus; + this.initDateTime=initDateTime; + this.stepsize = stepsize; + this.timeRange = timeRange; + this.trafficUpdate = trafficUpdate; + this.treshold = treshold; + } + + public TrafficSensorGraphGenerator(TrafficConfig tc, GraphDataStructure gds, DB db, long timeStampInit){ + super(tc.getGraphName(), null, gds, timeStampInit,0,0); + this.db = db; + this.modus = tc.getModus(); + this.initDateTime=tc.getInitDateTime(); + this.stepsize = tc.getStepSize(); + this.timeRange = tc.getTimeRange(); + this.trafficUpdate = tc.getTrafficUpdate(); + this.treshold = tc.getTreshold(); + } + + @Override + public Graph generate() { + Graph g = this.newGraphInstance(); + Set overloaded = new HashSet<>(); + + // Lade Sensoren aus der Datenbank + List nodes = db.getSensorsForDNA(); + + double[] weight = null; + Node currentNode = null; + DirectedWeightedNode currentWeighted = null; + + // Vorabberechnung der Knotengewichte für alle realen Sensoren + switch (modus) { + + case Continuous: + db.getSensorWeights(initDateTime, initDateTime.plusMinutes(stepsize), 0); + break; + + case DayTimeRange: + db.getSensorWeights(initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),0); + break; + + default: + break; + } + + // Berechne das Knotengewicht für alle Knoten + for (int i = 0; i < nodes.size(); i++) { + + currentNode = (Node) nodes.get(i); + if(currentNode instanceof DirectedWeightedNode) + currentWeighted = (DirectedWeightedNode) currentNode; + else{ + continue; + } + + switch (modus) { + + case Continuous: + weight = db.getSensorModelWeight(currentWeighted.getIndex(),initDateTime,initDateTime.plusMinutes(stepsize),0); + break; + + case DayTimeRange: + weight = db.getSensorModelWeight(currentWeighted.getIndex(),initDateTime.minusMinutes(timeRange),initDateTime.plusMinutes(timeRange),0); + break; + + case Simulation: + weight = db.getSensorModelWeightStaticInit(currentWeighted.getIndex(),trafficUpdate); + break; + + default: + System.out.println("error - TrafficSensorGraphGenerator- Modus nicht definiert"); + break; + } + + if(weight== null){ + weight = new double[]{0,0,0}; + } + + // Knoten überlastet + if(weight[2] > treshold){ + overloaded.add(currentWeighted.getIndex()); + } + currentWeighted.setWeight(new Double3dWeight(weight[0],weight[1],weight[2])); + g.addNode(currentWeighted); + } + + // Kanten + List connection = db.getSensorConnectionForDNA(); + DirectedWeightedNode fromNode; + DirectedWeightedNode toNode; + Edge e = null; + EdgeContainer ec = null; + + // Prüfe ob Kante gültig ist + for (int i = 0; i < connection.size(); i++) { + ec = connection.get(i); + fromNode = (DirectedWeightedNode) g.getNode(ec.getFrom()); + toNode = (DirectedWeightedNode) g.getNode(ec.getTo()); + try { + e = gds.newEdgeInstance(fromNode,toNode); + } catch (Exception e2) { + System.out.println("Problem: \t" +ec.getFrom()+"\t"+ec.getTo()); + } + + if(overloaded.contains(fromNode.getIndex()) || overloaded.contains((toNode.getIndex()))){ + addEdge(fromNode.getIndex(),ec,e); + addEdge(toNode.getIndex(),ec,e); + } + else{ + g.addEdge(e); + e.connectToNodes(); + } + + } + db.setDisabledEdgesInputWay(disabledEdges); + return g; + } + + /** + * Füge Kante zum Zwischenspeicher hinzu + * @param index Kontenindex eines Endknotens + * @param ec ContainerKlasse der Kante + * @param e Kante + */ + private void addEdge(int index,EdgeContainer ec, Edge e){ + if(disabledEdges.containsKey(index)) + disabledEdges.get(index).put(ec,e); + else{ + HashMap newEdgeList = new HashMap<>(); + newEdgeList.put(ec,e); + disabledEdges.put(index,newEdgeList); + } + } + +} diff --git a/src/dna/graph/generators/traffic/TrafficUpdate.java b/src/dna/graph/generators/traffic/TrafficUpdate.java new file mode 100644 index 00000000..43c4950e --- /dev/null +++ b/src/dna/graph/generators/traffic/TrafficUpdate.java @@ -0,0 +1,144 @@ +package dna.graph.generators.traffic; + +import java.util.List; + +public class TrafficUpdate { + + // Werte für die Initialiserung in NORMALIZATION + private double initCount; + private double initLoad; + + // Werte für das UPDATE in NORMALIZATION + private double updateCount; + private double updateLoad; + + // Werte in FINAL_VALUE + private double initUtilization; + private double updateUtilization; + + // Knoten für die im Update ein neuer Wert übernommen wird + private List nodesToUpdate; + + public final static int NORMALIZATION = 0; // für jeden Knoten werden getrennt Count- und Load-Werte bestimmt, aus denen das Knotengewicht durch Normalisierung bestimmt werden kann + public final static int FINAL_VALUE = 1; // für jeden Knoten wird ein Knotengewicht als Auslastung übergeben + + private int modus; // Entweder NORMALITAT oder Final-Value + private int sleeptillUpdate; // Anzahl der vergangenen Batches bis das Update angewendet wird + + /** + * Konstruktur für den Modus mit festgelegten Count und Load-Wert, + * die Berechnung des Knotengewichts erfolgt als normierter Wert mit dem maximalen Count-Wert + * @param initCount Count-Wert für die Initialisierung + * @param initLoad Load-Wert für die Initialisierung + * @param updateCount - Count-Wert für das Update + * @param updateLoad - Load-Wert für das Update + * @param sleeptillUpdate - Dauer des Aggregationszeitraums (Anzahl Batches) + * @param affectedNodes - Knoten für die eine Aktualisierung vorgenommen werden soll + */ + public TrafficUpdate(double initCount,double initLoad,double updateCount,double updateLoad,int sleeptillUpdate, List affectedNodes){ + this.initCount=initCount; + this.initLoad=initLoad; + this.updateCount=updateCount; + this.updateLoad=updateLoad; + this.nodesToUpdate = affectedNodes; + this.modus=NORMALIZATION; + this.sleeptillUpdate = sleeptillUpdate; + } + + /** + * Konstruktur für den Modus mit übergebenen normalisierten Werten, + * es erfolgte keine weitere Normalisierung mittels Count-Werten + * count und load werden als Dummy auf den Knoten mitgeführt + * @param initUtilization - Knotengewicht bei der Initialisierung + * @param updateUtilization - Knotengewicht für das Update + * @param sleepTilleTimestamp - Dauer des Aggregationszeitraums (Anzahl Batches) + * @param affectedNodes - Knoten für die eine Aktualisierung vorgenommen werden soll + */ + public TrafficUpdate(double initUtilization, double updateUtilization,int sleepTilleTimestamp,List affectedNodes){ + this.initUtilization = initUtilization; + this.updateUtilization = updateUtilization; + this.nodesToUpdate = affectedNodes; + this.modus=FINAL_VALUE; + } + + /** + * liefert den Modus für den das Objekt erstellt wurde + * @return 0 = Normalization, 1 = Final_Values als Konstanten + */ + public int getModus(){ + return modus; + } + + /** + * liefert den Count-Wert für die Initialisierung + * @return + */ + public double getInitCount(){ + return initCount; + } + + /** + * liefert den Load-Wert für die Initialisierung + * @return + */ + public double getInitLoad(){ + return initLoad; + } + + /** + * liefert den Count-Wert für das Update + * @return + */ + public double getUpdateCount(){ + return updateCount; + } + + /** + * liefert den Load-Wert für das Update + * @return + */ + public double getUpdateLoad(){ + return updateLoad; + } + + /** + * prüft ob der übergebene Knoten für das Update berücksichtigt werden soll + * @param nodeID - globale ID des Knoten + * @return + */ + public boolean isAffected(int nodeID){ + return nodesToUpdate.contains(nodeID); + } + /** + * prüft ob das Update angewendet werden soll + * @param timeStamp - aktuelle Zeitschritt + * @return + */ + public boolean changeToUpdate(int timeStamp){ + return sleeptillUpdate<=timeStamp; + } + + /** + * liefert das initiale Knotengewicht + * @return + */ + public double getInitUtilization(){ + return initUtilization; + } + + /** + * liefert das Knotengewicht im Update + * @return + */ + public double getUpdateUtilization(){ + return updateUtilization; + } + + /** + * liefert den Zeitraum für die Aggregation + * @return + */ + public int getSleepTillUpdate(){ + return sleeptillUpdate; + } +} diff --git a/src/dna/graph/weights/Double3dWeight.java b/src/dna/graph/weights/Double3dWeight.java index a311cb4c..49701820 100644 --- a/src/dna/graph/weights/Double3dWeight.java +++ b/src/dna/graph/weights/Double3dWeight.java @@ -65,5 +65,16 @@ public String asString() { return this.x + Weight.WeightSeparator + this.y + Weight.WeightSeparator + this.z; } + + + public boolean equals(Object o){ + if (o == null) + return false; + if (!(o instanceof Double3dWeight)) + return false; + + Double3dWeight oCasted = (Double3dWeight) o; + return this.x == oCasted.getX() && this.y == oCasted.getY() && this.z == oCasted.getZ(); + } } diff --git a/src/dna/metrics/centrality/BetweennessCentrality.java b/src/dna/metrics/centrality/BetweennessCentrality.java index 72e204de..bd959c2d 100644 --- a/src/dna/metrics/centrality/BetweennessCentrality.java +++ b/src/dna/metrics/centrality/BetweennessCentrality.java @@ -46,7 +46,8 @@ public BetweennessCentrality(String name) { public Value[] getValues() { // Value v1 = new Value("median", getMedian()); Value v2 = new Value("avg_bc", bCSum / (double) g.getNodeCount()); - return new Value[] { v2 }; + Value v3 = new Value("sum_of_path", sumShortestPaths); + return new Value[] { v2,v3 }; } @Override diff --git a/src/dna/metrics/connectivity/StrongConnectivity.java b/src/dna/metrics/connectivity/StrongConnectivity.java index b1b636de..0b446d6e 100644 --- a/src/dna/metrics/connectivity/StrongConnectivity.java +++ b/src/dna/metrics/connectivity/StrongConnectivity.java @@ -121,7 +121,7 @@ protected int lookup(DirectedNode n) { @Override public Value[] getValues() { Value v1 = new Value("NumberofComponents", countComponents()); - Value v2 = new Value("average size", getaverageSize()); + Value v2 = new Value("averagesize", getaverageSize()); return new Value[] { v1, v2 }; } diff --git a/src/dna/metrics/paths/AllPairsShortestPathsDouble.java b/src/dna/metrics/paths/AllPairsShortestPathsDouble.java new file mode 100644 index 00000000..3d5a27df --- /dev/null +++ b/src/dna/metrics/paths/AllPairsShortestPathsDouble.java @@ -0,0 +1,74 @@ +package dna.metrics.paths; + +import dna.metrics.IMetric; +import dna.metrics.Metric; +import dna.series.data.BinnedDistributionDouble; +import dna.series.data.Distribution; +import dna.series.data.DistributionLong; +import dna.series.data.NodeNodeValueList; +import dna.series.data.NodeValueList; +import dna.series.data.Value; +import dna.util.ArrayUtils; + +/** + * works nearly similar to AllPairsShortestPathsDouble except it + * uses BinnedDistributionDouble instead of DistributionLong + * + * maybe this can be combined with the parent class distribution + * @author barracuda317 (Maurice Wendt) + * @date 25.10.2014 + */ +public abstract class AllPairsShortestPathsDouble extends Metric { + + // TODO INIT!!! + // this.apsp = new DistributionLong("APSP"); + double binsize; + + protected BinnedDistributionDouble apsp; + + public AllPairsShortestPathsDouble(String name) { + super(name); + } + public AllPairsShortestPathsDouble(String name,double binsize) { + super(name); + this.binsize = binsize; + } + + @Override + public Value[] getValues() { + this.apsp.truncate(); + + Value v1 = new Value("existingPaths", this.apsp.getDenominator()); + Value v2 = new Value("possiblePaths", this.g.getNodeCount() + * (this.g.getNodeCount() - 1)); + Value v3 = new Value("characteristicPathLength", + this.apsp.computeAverage()*binsize); + Value v4 = new Value("diameter", this.apsp.getMax()*binsize); + + return new Value[] { v1, v2, v3, v4 }; + } + + @Override + public Distribution[] getDistributions() { + return new Distribution[] { this.apsp }; + } + + @Override + public NodeValueList[] getNodeValueLists() { + return new NodeValueList[] {}; + } + + @Override + public NodeNodeValueList[] getNodeNodeValueLists() { + return new NodeNodeValueList[] {}; + } + + @Override + public boolean equals(IMetric m) { + return this.isComparableTo(m) + && ArrayUtils.equals(this.apsp.getDoubleValues(), + ((AllPairsShortestPathsDouble) m).apsp.getDoubleValues(), + "APSP"); + } + +} diff --git a/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java new file mode 100644 index 00000000..f4fb3a4b --- /dev/null +++ b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPaths.java @@ -0,0 +1,43 @@ +package dna.metrics.paths; + +import dna.graph.Graph; +import dna.graph.weights.Double3dWeight; +import dna.graph.weights.IWeightedEdge; +import dna.graph.weights.IWeightedNode; +import dna.graph.weights.IntWeight; +import dna.metrics.IMetric; +import dna.updates.batch.Batch; +/** + * + * Adaption of IntWeightedAllPairsShortestPath + * + * using NodeWeights and DoubleValues + * + * @author barracuda317 (Maurice Wendt) + * @date 25.10.2014 + */ +public abstract class DoubleWeightedAllPairsShortestPaths extends + AllPairsShortestPathsDouble { + + public DoubleWeightedAllPairsShortestPaths(String name,double binsize) { + super(name,binsize); + } + + @Override + public boolean isComparableTo(IMetric m) { + return m != null && m instanceof DoubleWeightedAllPairsShortestPaths; + } + + @Override + public boolean isApplicable(Graph g) { + return g.getGraphDatastructures().isNodeType(IWeightedNode.class) + && g.getGraphDatastructures().isNodeWeightType(Double3dWeight.class); //TODO fragt den Z-Wert von Double3dWeight ab + } + + @Override + public boolean isApplicable(Batch b) { + return b.getGraphDatastructures().isNodeType(IWeightedNode.class) + && b.getGraphDatastructures().isNodeWeightType(Double3dWeight.class); //TODO fragt den Z-Wert von Double3dWeight ab + } + +} diff --git a/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java new file mode 100644 index 00000000..979f3264 --- /dev/null +++ b/src/dna/metrics/paths/DoubleWeightedAllPairsShortestPathsR.java @@ -0,0 +1,130 @@ +package dna.metrics.paths; + +import java.util.Comparator; +import java.util.PriorityQueue; + +import dna.graph.IElement; +import dna.graph.edges.DirectedEdge; +import dna.graph.edges.UndirectedEdge; +import dna.graph.nodes.DirectedNode; +import dna.graph.nodes.Node; +import dna.graph.nodes.UndirectedNode; +import dna.graph.weights.Double3dWeight; +import dna.graph.weights.IWeighted; +import dna.graph.weights.IntWeight; +import dna.metrics.algorithms.IRecomputation; +import dna.series.data.BinnedDistributionDouble; +import dna.series.data.DistributionLong; +/** + * + * Adaption of IntWeightedAllPairsShortestPathR + * + * using NodeWeights and DoubleValues + * + * @author barracuda317 (Maurice Wendt) + * @date 25.10.2014 + */ +public class DoubleWeightedAllPairsShortestPathsR extends + DoubleWeightedAllPairsShortestPaths implements IRecomputation { + + + + public DoubleWeightedAllPairsShortestPathsR(double binsize) { + super("DoubleWeightedAllPairsShortestPathsR", binsize); + this.binsize=binsize; + } + + @Override + public boolean recompute() { + this.apsp = new BinnedDistributionDouble("APSP", binsize); + for (IElement source_ : this.g.getNodes()) { + Node source = (Node) source_; + + double[] dist = this.getInitialDist(this.g.getMaxNodeIndex() + 1); + Node[] previous = new Node[this.g.getMaxNodeIndex() + 1]; + boolean[] visited = new boolean[g.getMaxNodeIndex() + 1]; + PriorityQueue Q = new PriorityQueue(g.getNodeCount(), + new DistComparator(dist)); + + dist[source.getIndex()] = 0; + Q.add(source); + + while (!Q.isEmpty()) { + Node current = (Node) Q.remove(); + + if (visited[current.getIndex()]) { + continue; + } + visited[current.getIndex()] = true; + + if (current instanceof DirectedNode) { + for (IElement e : ((DirectedNode) current) + .getOutgoingEdges()) { + Node n = ((DirectedEdge) e).getDst(); + Double3dWeight w = (Double3dWeight) ((IWeighted) n).getWeight(); + this.process(source, current, n, w.getZ(), + dist, previous, visited, Q); + } + } else if (current instanceof UndirectedNode) { + for (IElement e : ((UndirectedNode) current).getEdges()) { + Node n = ((UndirectedEdge) e).getDifferingNode(current); + Double3dWeight w = (Double3dWeight) ((IWeighted) e).getWeight(); + this.process(source, current, n, w.getZ(), + dist, previous, visited, Q); + } + } + } + + for (double d : dist) { + if (d > 0 && d != Integer.MAX_VALUE) { + this.apsp.incr(d); + } + } + } + + return true; + } + + protected class DistComparator implements Comparator { + + private double[] dist; + + public DistComparator(double[] dist) { + this.dist = dist; + } + + @Override + public int compare(Node o1, Node o2) { + double diff = this.dist[o1.getIndex()] - this.dist[o2.getIndex()]; + if(diff > 0) + return 1; + else if (diff < 0) + return -1; + else + return 0; + } + } + + protected void process(Node source, Node current, Node n, double weight, + double[] dist, Node[] previous, boolean[] visited, + PriorityQueue Q) { + if (n.getIndex() == source.getIndex()) { + return; + } + double newDist = dist[current.getIndex()] + weight; + if (previous[n.getIndex()] == null || newDist < dist[n.getIndex()]) { + dist[n.getIndex()] = newDist; + previous[n.getIndex()] = current; + Q.add(n); + } + } + + protected double[] getInitialDist(int size) { + double[] dist = new double[size]; + for (int i = 0; i < dist.length; i++) { + dist[i] = Integer.MAX_VALUE; + } + return dist; + } + +} diff --git a/src/dna/metrics/weights/NodeWeights.java b/src/dna/metrics/weights/NodeWeights.java index 8329d708..bca0b896 100644 --- a/src/dna/metrics/weights/NodeWeights.java +++ b/src/dna/metrics/weights/NodeWeights.java @@ -3,6 +3,7 @@ import dna.graph.Graph; import dna.graph.IElement; import dna.graph.nodes.INode; +import dna.graph.weights.Double3dWeight; import dna.graph.weights.DoubleWeight; import dna.graph.weights.IWeightedNode; import dna.graph.weights.IntWeight; @@ -34,14 +35,14 @@ public boolean isComparableTo(IMetric m) { public boolean isApplicable(Graph g) { return g.getGraphDatastructures().isNodeType(IWeightedNode.class) && g.getGraphDatastructures().isNodeWeightType(IntWeight.class, - DoubleWeight.class); + DoubleWeight.class,Double3dWeight.class); } @Override public boolean isApplicable(Batch b) { return b.getGraphDatastructures().isNodeType(IWeightedNode.class) && b.getGraphDatastructures().isNodeWeightType(IntWeight.class, - DoubleWeight.class); + DoubleWeight.class,Double3dWeight.class); } protected double getWeight(INode n) { diff --git a/src/dna/metrics/weights/Weights.java b/src/dna/metrics/weights/Weights.java index b824a1f9..f442af59 100644 --- a/src/dna/metrics/weights/Weights.java +++ b/src/dna/metrics/weights/Weights.java @@ -1,5 +1,6 @@ package dna.metrics.weights; +import dna.graph.weights.Double3dWeight; import dna.graph.weights.DoubleWeight; import dna.graph.weights.IntWeight; import dna.graph.weights.Weight; @@ -62,6 +63,8 @@ protected double getWeight(Weight w) { return (double) ((IntWeight) w).getWeight(); } else if (w instanceof DoubleWeight) { return ((DoubleWeight) w).getWeight(); + } else if (w instanceof Double3dWeight) { + return ((Double3dWeight) w).getZ(); } else { return Double.NaN; } diff --git a/src/dna/series/data/DistributionDouble.java b/src/dna/series/data/DistributionDouble.java index d866a3f2..5e9b5846 100644 --- a/src/dna/series/data/DistributionDouble.java +++ b/src/dna/series/data/DistributionDouble.java @@ -21,6 +21,7 @@ public class DistributionDouble extends Distribution { // member variables private double[] values; + private long denominator; // values for comparison private double comparedSum; @@ -105,6 +106,7 @@ public double getComparedAvg() { */ public void incr(int index) { this.values = ArrayUtils.incr(this.values, index); + this.denominator++; } /** @@ -115,6 +117,7 @@ public void incr(int index) { */ public void decr(int index) { this.values = ArrayUtils.decr(this.values, index); + this.denominator--; } /** @@ -213,5 +216,17 @@ public static DistributionDouble read(String dir, String filename, public static boolean equals(DistributionDouble d1, DistributionDouble d2) { return ArrayUtils.equals(d1.getDoubleValues(), d2.getDoubleValues()); } + + public double getDenominator() { + return denominator; + } + + public double computeAverage() { + double avg = 0; + for (int i = 0; i < this.values.length; i++) { + avg += i * this.values[i]; + } + return avg / this.denominator; + } } diff --git a/src/dna/updates/generators/traffic/CrossroadWeightList.java b/src/dna/updates/generators/traffic/CrossroadWeightList.java new file mode 100644 index 00000000..bf460d9e --- /dev/null +++ b/src/dna/updates/generators/traffic/CrossroadWeightList.java @@ -0,0 +1,50 @@ +package dna.updates.generators.traffic; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import dna.graph.generators.traffic.CrossroadWeight; + +public class CrossroadWeightList { + int crossroadID; + String crossroadName; + double threshold; + List objects; + List weights; + CrossroadWeight sum; + + public CrossroadWeightList(int index, String crossroadName, double threshold){ + this.crossroadID=index; + this.crossroadName=crossroadName; + this.threshold = threshold; + this.objects = new ArrayList<>(); + this.weights = new ArrayList<>(); + } + + public boolean add(CrossroadWeight crw){ + if(crw.crossroadID != crossroadID || !crw.getCrossroadName().equals(crossroadName) ) + return false; + else{ + if(sum==null){ + sum = new CrossroadWeight(crossroadID, crossroadName, threshold); + for (Map.Entry entry : crw.getWayWeights().entrySet()) { + sum.addWeightWay(entry.getKey(), entry.getValue()); + sum.setMaxWeightWay(entry.getKey(), crw.getMaxWeightWay(entry.getKey())); + } + sum.setMaxWeight(crw.getMaxWeight()); + } + else{ + sum.addWeights(crw.inputWayWeights); + } + objects.add(crw); + weights.add(crw.getWeight()[2]); + return true; + } + } + + public CrossroadWeight getAverage(){ + sum.divWays(objects.size()); + return sum; + } +} diff --git a/src/dna/updates/generators/traffic/Days.java b/src/dna/updates/generators/traffic/Days.java new file mode 100644 index 00000000..193ba2f5 --- /dev/null +++ b/src/dna/updates/generators/traffic/Days.java @@ -0,0 +1,9 @@ +package dna.updates.generators.traffic; + +public enum Days { + MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY; + + static Days getDay(int i){ + return values()[i-1]; + } +} \ No newline at end of file diff --git a/src/dna/updates/generators/traffic/Helpers.java b/src/dna/updates/generators/traffic/Helpers.java new file mode 100644 index 00000000..6c6e874e --- /dev/null +++ b/src/dna/updates/generators/traffic/Helpers.java @@ -0,0 +1,56 @@ +package dna.updates.generators.traffic; + +import org.joda.time.DateTime; + +public class Helpers { + public static boolean isWorkDay(Days d) { + return !(d == Days.SATURDAY || d==Days.SUNDAY); + } + + /** + * berechnet ausgehend von "start" den nächsten Werktag in der Zukunft(forward) oder Vergangenheit (!forward) + * @param start - Startdatum + * @param l - Timestep + * @param forward - true = in der Zukunft, false = in der Vergangenheit + * @return + */ + public static DateTime calculateNextWorkDay(DateTime start,long l, boolean forward){ + return calculateNextDay(start, l, new boolean[]{true,true,true,true,true,false,false},null,forward); + } + + /** + * berechnet ausgehend von "start" den nächsten Tag in der Zukunft(forward) oder Vergangenheit (!forward) + * @param start - Startdatum + * @param timestep - Zeitschritt für den der nächste Tag berechnet werden soll + * @param daySelection - Array mit Wochentagen, die für die Berechnung berücksichtigt werden sollen + * @param ignoreTo - Zeitpunkt bis zu welchem die Berechnung ignoriert wird + * @param forward - true = in der Zukunft, false = in der Vergangenheit + * @return + */ + public static DateTime calculateNextDay(DateTime start, long timestep, boolean[] daySelection,DateTime ignoreTo, boolean forward){ + DateTime current = start; + int count = 0; + while(count <= timestep) { + current = forward ? current.plusDays(1) : current.minusDays(1); + if(daySelection[current.getDayOfWeek()-1] && (current.isBefore(ignoreTo) || forward)){ + count++; + } + } + return current; + } + /** + * Wandelt die Beobachtungswochen in die Beobachtungstage um (=#Batches) + * @param weeks, Wochen die beobachtet werden sollen + * @param daySelection , Tage die in einer Woche beobachtet werden sollen + * @return + */ + public static int weekToDay(int weeks, boolean[] daySelection){ + int i =0; + for (int j = 0; j < daySelection.length; j++) { + if(daySelection[j]) + i++; + } + return i*weeks; + } + +} diff --git a/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java new file mode 100644 index 00000000..2e308690 --- /dev/null +++ b/src/dna/updates/generators/traffic/TrafficCrossroadBatchGenerator.java @@ -0,0 +1,236 @@ +package dna.updates.generators.traffic; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.IElement; +import dna.graph.edges.Edge; +import dna.graph.generators.traffic.CrossroadWeight; +import dna.graph.generators.traffic.DB; +import dna.graph.generators.traffic.EdgeContainer; +import dna.graph.generators.traffic.TrafficConfig; +import dna.graph.generators.traffic.TrafficModi; +import dna.graph.generators.traffic.TrafficUpdate; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.weights.Double3dWeight; +import dna.updates.batch.Batch; +import dna.updates.generators.BatchGenerator; +import dna.updates.update.EdgeAddition; +import dna.updates.update.EdgeRemoval; +import dna.updates.update.NodeWeight; +import dna.util.parameters.IntParameter; +import dna.util.parameters.ObjectParameter; + +public class TrafficCrossroadBatchGenerator extends BatchGenerator{ + + private DB db; + + //Allgemeine Parameter + private DateTime initDateTime; + private TrafficModi modus; + + // Continous + private int stepSize; + + //DayTimeRange - Aggregation + private DateTime holidayStart; + private boolean[] daySelection; + private int timeRange; + + //Aggregation + private int observationDays; + + //Simulation + private TrafficUpdate trafficUpdate; + + private HashMap disabledEdges = new HashMap<>(); + private HashMap nodeHistory; + + + public TrafficCrossroadBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection,TrafficUpdate trafficUpdate,int timeRange, int observationDays) { + super(name, new IntParameter("NA", 0), new IntParameter("NR", + 0), new IntParameter("NW", 0), + new ObjectParameter("NWS", 0), new IntParameter("EA", 0), + new IntParameter("ER", 0)); + this.db = db; + this.initDateTime = initDateTime; + this.stepSize = stepSize; + this.modus = modus; + this.holidayStart = holidayStart; + this.daySelection = daySelection; + this.trafficUpdate = trafficUpdate; + this.timeRange = timeRange; + this.observationDays = observationDays; + } + + /** + * Erstellt einen TrafficCrossroadBatchGeneratur unter Verwendung der Paramtere auf TrafficConfig + * @param db + * @param tc + */ + public TrafficCrossroadBatchGenerator(DB db, TrafficConfig tc){ + super(tc.getBatchName(), new IntParameter("NA", 0), new IntParameter("NR", + 0), new IntParameter("NW", 0), + new ObjectParameter("NWS", 0), new IntParameter("EA", 0), + new IntParameter("ER", 0)); + this.db = db; + this.initDateTime = tc.getInitDateTime(); + this.stepSize = tc.getStepSize(); + this.modus = tc.getModus(); + this.holidayStart = tc.getHolidayStart(); + this.daySelection = tc.getDaySelection(); + this.trafficUpdate = tc.getTrafficUpdate(); + this.timeRange = tc.getTimeRange(); + this.observationDays = tc.getOberservationDays(); + } + + @Override + public Batch generate(Graph g) { + + Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(), + g.getTimestamp() + 1, 0, 0, 0, 0, + 0, 0); + + // Infos aus Initialisierungsschritt holen + if(g.getTimestamp()==0){ + disabledEdges = db.getDisabledEdges(); + } + + HashMap newDisabled = new HashMap<>(); + Iterable nodes = g.getNodes(); + CrossroadWeight crossroadWeight = null; + DateTime time = null; + + + // Spezialkonfigurationen für bestimmte Modi + switch (modus) { + + case DayTimeRange: + time = initDateTime; + time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true); + break; + + case Aggregation: + nodeHistory = new HashMap<>(); + break; + + default: + break; + } + + // neuer Timestamp durch Batch-Generierung + long newTimeStamp = (int) g.getTimestamp() + 1; + + // Berechne neues Gewicht für jeden Knoten + for (IElement currentNode : nodes) { + DirectedWeightedNode n = (DirectedWeightedNode) currentNode; + double[] update = null; + + // Gewichts-Update + switch (modus) { + + case Continuous: + crossroadWeight =db.getCrossroadWeight(n.getIndex(), initDateTime.plusMinutes((int) (g.getTimestamp()*stepSize)),initDateTime.plusMinutes((int) (g.getTimestamp()+stepSize)*stepSize),newTimeStamp); + break; + + case DayTimeRange: + crossroadWeight = db.getCrossroadWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange),newTimeStamp); + break; + + case Simulation: + crossroadWeight = db.getCrossroadWeightStaticBatch(n.getIndex(),trafficUpdate); + break; + + case Aggregation: + //Initialisierung auf Starttag + time = initDateTime; + int index = n.getIndex(); + long start = g.getTimestamp(); + + // Aggregiere für observationDays-viele Tage + for (int i = 0; i < observationDays; i++) { + + // Gehe einen Tag zurück (gemäß daySelection) und berechne den entsprechenden Wert + time = Helpers.calculateNextDay(initDateTime, start++,daySelection,holidayStart,false); + CrossroadWeight weightOfDay = db.getCrossroadWeight(n.getIndex(),time.minusMinutes(timeRange*2),time.plusMinutes(timeRange*2),newTimeStamp); + + // Sammler für jeden Knoten die Gewichte der einzelnen Tage + if(nodeHistory.containsKey(index)){ + nodeHistory.get(index).add(weightOfDay); + } + else{ + CrossroadWeightList weightList = new CrossroadWeightList(weightOfDay.crossroadID,weightOfDay.getCrossroadName(),weightOfDay.getThreshold()); + weightList.add(weightOfDay); + nodeHistory.put(index, weightList); + } + + } + + // Nach der Aggregation, berechne den Average + crossroadWeight = nodeHistory.get(index).getAverage(); + break; + + default: + System.out.println("error - Modus nicht definiert"); + break; + } + + update = crossroadWeight.getWeight(); + Double3dWeight oldWeight = (Double3dWeight) n.getWeight(); + Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]); + + db.setMaximalWeightsCrossroadImproved(n.getIndex(), update[0], update[1], time, timeRange); + if(!oldWeight.equals(newWeight)) + b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,newWeight)); + + //Edge-Removal + Edge disabledEdge = null; + for (Integer wayId : crossroadWeight.getOverladedEdges().keySet()) { + List edgesToRemove = db.getFromWays(n.getIndex(), wayId); + if(edgesToRemove != null){ + for (int[] edge : edgesToRemove) { + disabledEdge = g.getEdge(g.getNode(edge[0]), n); + EdgeContainer ec = new EdgeContainer(edge[0], n.getIndex()); + if(disabledEdge==null){ + disabledEdge = disabledEdges.remove(ec); + if(disabledEdge==null){ + for (EdgeContainer e : disabledEdges.keySet()) { + System.out.println(e); + } + } + } + else + b.add(new EdgeRemoval(disabledEdge)); + newDisabled.put(ec, disabledEdge); + } + } + } + } + + //Edge-Addition, falls diese wieder frei sind + for (Map.Entry oldDeletedEdge : disabledEdges.entrySet()) { + b.add(new EdgeAddition(oldDeletedEdge.getValue())); + } + + disabledEdges=newDisabled; + + return b; + } + + @Override + public void reset() { + // TODO Auto-generated method stub + + } + + @Override + public boolean isFurtherBatchPossible(Graph g) { + // TODO Auto-generated method stub + return true; + } + +} diff --git a/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java new file mode 100644 index 00000000..442d549c --- /dev/null +++ b/src/dna/updates/generators/traffic/TrafficInputWayBatchGenerator.java @@ -0,0 +1,292 @@ +package dna.updates.generators.traffic; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map.Entry; +import java.util.Set; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.IElement; +import dna.graph.edges.Edge; +import dna.graph.generators.traffic.DB; +import dna.graph.generators.traffic.EdgeContainer; +import dna.graph.generators.traffic.TrafficConfig; +import dna.graph.generators.traffic.TrafficModi; +import dna.graph.generators.traffic.TrafficUpdate; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.weights.Double3dWeight; +import dna.updates.batch.Batch; +import dna.updates.generators.BatchGenerator; +import dna.updates.update.EdgeAddition; +import dna.updates.update.EdgeRemoval; +import dna.updates.update.NodeWeight; +import dna.util.parameters.IntParameter; +import dna.util.parameters.ObjectParameter; + +public class TrafficInputWayBatchGenerator extends BatchGenerator{ + + private DB db; + + // Allgemeine Parameter + private DateTime initDateTime; + private TrafficModi modus; + private double treshold; + + // Continous + private int stepSize; + + // DayTimeRange / Aggregation + private DateTime holidayStart; + private boolean[] daySelection; + private int timeRange; + + // Aggregation + private int observationDays; + + // Simulation + private TrafficUpdate trafficUpdate; + + private HashMap> nodeHistory = new HashMap<>(); + private HashMap> disabledEdges = new HashMap<>(); + private HashMap> newDisabledEdges = new HashMap<>(); + + + public TrafficInputWayBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection, double treshold, TrafficUpdate trafficUpdate, int timeRange, int observationDays) { + super(name, new IntParameter("NA", 0), new IntParameter("NR", + 0), new IntParameter("NW", 10), + new ObjectParameter("NWS", 0), new IntParameter("EA", 0), + new IntParameter("ER", 0)); + this.db = db; + this.initDateTime = initDateTime; + this.stepSize = stepSize; + this.modus = modus; + this.holidayStart = holidayStart; + this.daySelection = daySelection; + this.treshold = treshold; + this.trafficUpdate = trafficUpdate; + this.timeRange = timeRange; + this.observationDays = observationDays; + } + + public TrafficInputWayBatchGenerator(DB db, TrafficConfig tc){ + super(tc.getBatchName(), new IntParameter("NA", 0), new IntParameter("NR", + 0), new IntParameter("NW", 0), + new ObjectParameter("NWS", 0), new IntParameter("EA", 0), + new IntParameter("ER", 0)); + this.db = db; + this.initDateTime = tc.getInitDateTime(); + this.stepSize = tc.getStepSize(); + this.modus = tc.getModus(); + this.holidayStart = tc.getHolidayStart(); + this.daySelection = tc.getDaySelection(); + this.treshold = tc.getTreshold(); + this.trafficUpdate = tc.getTrafficUpdate(); + this.timeRange = tc.getTimeRange(); + this.observationDays = tc.getOberservationDays(); + } + + @Override + public Batch generate(Graph g) { + Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(), + g.getTimestamp() + 1, 0, 0, 0, 0, + 0, 0); + + Set toDisable = new HashSet<>(); + + // Knoten + + Iterable nodes = g.getNodes(); + DateTime time = null; + + if(modus == TrafficModi.DayTimeRange){ + time = initDateTime; + time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true); + } + + // Aktualisiere das Gewicht für jeden Knoten, gemäß dem aktuellen Modus + for (IElement currentNode : nodes) { + + DirectedWeightedNode n = (DirectedWeightedNode) currentNode; + double[] update =null; + + //WeightUpdate + switch (modus) { + + case Continuous: + update = db.getInputWayWeight(n.getIndex(),initDateTime.plusMinutes((int) (g.getTimestamp()+1)*stepSize),initDateTime.plusMinutes((int) (g.getTimestamp()+2)*stepSize)); + break; + + case DayTimeRange: + update = db.getInputWayWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange)); + break; + + case Simulation: + update = (trafficUpdate.isAffected(n.getIndex()))? db.getInputWayWeightStaticBatch(n.getIndex(),trafficUpdate) : null; + break; + + case Aggregation: + time = initDateTime; + int index = n.getIndex(); + long start = g.getTimestamp(); + + // Summiere für alle Beobachtungstage auf + for (int i = 0; i < observationDays; i++) { + time = Helpers.calculateNextDay(initDateTime, start++, daySelection, holidayStart, false); + double[] weightOfDay = db.getInputWayWeight(n.getIndex(),time.minusMinutes(timeRange),time.plusMinutes(timeRange)); + if(nodeHistory.containsKey(index)){ + nodeHistory.get(index).add(weightOfDay[2]); + } + else { + List weightList = new ArrayList<>(); + weightList.add(weightOfDay[2]); + nodeHistory.put(index, weightList); + } + } + + //Berechne das Knotengewicht aus der Aggregation + double sum = 0; + List values = nodeHistory.get(index); + for (int i = 0; i < values.size(); i++) { + sum+=values.get(i); + } + double value = (values.isEmpty())? 0 : sum/values.size(); + update = new double[]{0,0,value}; + + break; + default: + System.out.println("error - Modus nicht definiert"); + break; + } + + // Wende das Update des Gewichts auf den Knoten an + Double3dWeight oldWeight = (Double3dWeight) n.getWeight(); + if(update!=null){ + Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]); + if(!oldWeight.equals(newWeight)) + b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,new Double3dWeight(update[0],update[1],update[2]))); + } + else{ + update = new double[]{oldWeight.getX(),oldWeight.getY(),oldWeight.getZ()}; + } + + EdgeContainer ec = null; + Integer newKey = null; + Edge edge = null; + + // Infos aus Initialisierungsschritt holen + if(g.getTimestamp()==0){ + disabledEdges=db.getDisabledEdgesInputWay(); + } + newDisabledEdges = new HashMap<>(); + + // Knoten ist ueberlastet + if(update[2] > treshold) { + + newKey = n.getIndex(); + int from; + int to; + + // Verhindere das Hinzufügen bereits gelöschter Kante + if(disabledEdges.containsKey(newKey)){ + HashMap oldMap = disabledEdges.get(newKey); + for (Entry entry : oldMap.entrySet()) { + EdgeContainer key = entry.getKey(); + Edge value = entry.getValue(); + if(key.getFrom()==newKey){ + removeEdge(key.getTo(),key,value); + addEdge(key.getTo(), key, value); + } + else{ + removeEdge(key.getFrom(),key,value); + addEdge(key.getFrom(),key,value); + } + } + disabledEdges.remove(newKey); + } + + // Lösche neue Kanten + for (IElement elem : n.getEdges()) { + edge = (Edge) elem; + from = edge.getN1Index(); + to = edge.getN2Index(); + ec = new EdgeContainer(from, to); + removeEdge(from,ec,edge); + removeEdge(to, ec, edge); + addEdge(from,ec,edge); + addEdge(to, ec, edge); + toDisable.add(edge); + } + } + + } + + // Füge die Löschoperation in den Batch hinzu + for (Edge e : toDisable) { + b.add(new EdgeRemoval(e)); + } + + // Füge nicht mehr ueberlastet Knoten wieder dem Graph hinzu + for (Entry> freeEdges : disabledEdges.entrySet()) { + int node = freeEdges.getKey(); + for (Entry elem : freeEdges.getValue().entrySet()) { + if(node == elem.getKey().getFrom()) + b.add(new EdgeAddition(elem.getValue())); + } + } + + disabledEdges=newDisabledEdges; + + return b; + } + + @Override + public void reset() { + // TODO Auto-generated method stub + } + + @Override + public boolean isFurtherBatchPossible(Graph g) { + // TODO Auto-generated method stub + return true; + } + + /** + * Entfernt eine Kante aus dem Zwischenspeicher + * @param index + * @param ec + * @param e + */ + private void removeEdge(int index, EdgeContainer ec, Edge e){ + if(disabledEdges.containsKey(index)){ + HashMap oldMap = disabledEdges.get(index); + oldMap.remove(ec); + if(oldMap.isEmpty()){ + disabledEdges.remove(index); + } + } + } + + /** + * fügte eine Kante zum Zwischenspeicher hinzu + * @param index + * @param ec + * @param e + */ + private void addEdge(int index, EdgeContainer ec, Edge e){ + if(newDisabledEdges.containsKey(index)){ + HashMap oldMap = newDisabledEdges.get(index); + oldMap.put(ec, e); + } + else { + HashMap newMap = new HashMap<>(); + newMap.put(ec, e); + newDisabledEdges.put(index,newMap); + } + } + + +} diff --git a/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java b/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java new file mode 100644 index 00000000..0cd11183 --- /dev/null +++ b/src/dna/updates/generators/traffic/TrafficSensorBatchGenerator.java @@ -0,0 +1,229 @@ +package dna.updates.generators.traffic; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.Map.Entry; + +import org.joda.time.DateTime; + +import dna.graph.Graph; +import dna.graph.IElement; +import dna.graph.edges.Edge; +import dna.graph.generators.traffic.DB; +import dna.graph.generators.traffic.EdgeContainer; +import dna.graph.generators.traffic.TrafficModi; +import dna.graph.generators.traffic.TrafficUpdate; +import dna.graph.nodes.DirectedWeightedNode; +import dna.graph.weights.Double3dWeight; +import dna.io.GraphWriter; +import dna.updates.batch.Batch; +import dna.updates.generators.BatchGenerator; +import dna.updates.update.EdgeAddition; +import dna.updates.update.EdgeRemoval; +import dna.updates.update.NodeWeight; +import dna.util.parameters.IntParameter; +import dna.util.parameters.ObjectParameter; + +public class TrafficSensorBatchGenerator extends BatchGenerator{ + private DB db; + private DateTime initDateTime; + private int stepSize; + private int step=0; + private TrafficModi modus; + private DateTime holidayStart; + private boolean[] daySelection; + private double treshold; + private int timeRange; + + private HashMap> disabledEdges; + private HashMap> newDisabledEdges; + private TrafficUpdate trafficUpdate; + + public TrafficSensorBatchGenerator(String name,DB db, DateTime initDateTime, int stepSize, TrafficModi modus, DateTime holidayStart, boolean [] daySelection, double treshold,int timeRange,TrafficUpdate trafficUpdate) { + super(name, new IntParameter("NA", 0), new IntParameter("NR", + 0), new IntParameter("NW", 0), + new ObjectParameter("NWS", 0), new IntParameter("EA", 0), + new IntParameter("ER", 0)); + this.db = db; + this.initDateTime = initDateTime; + this.stepSize = stepSize; + this.modus=modus; + this.holidayStart=holidayStart; + this.daySelection = daySelection; + this.treshold = treshold; + this.timeRange = timeRange; + this.trafficUpdate = trafficUpdate; + disabledEdges=new HashMap<>(); + newDisabledEdges = new HashMap<>(); + } + + @Override + public Batch generate(Graph g) { + Batch b = new Batch(g.getGraphDatastructures(), g.getTimestamp(), + g.getTimestamp() + 1, 0, 0, 0, 0, + 0, 0); + if(g.getTimestamp()==0){ + disabledEdges = db.getDisabledEdgesInputWay(); + } + GraphWriter.write(g, "SensorGraph/", "batch"+step+++".txt"); + Integer newKey = null; + int newTimestamp = (int)g.getTimestamp() + 1; + + DateTime time = initDateTime; + time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true); + DateTime fromTime = null; + DateTime toTime = null; + + Set toDisable = new HashSet<>(); + Edge edge = null; + + switch (modus) { + case Continuous: + fromTime = initDateTime.plusMinutes((int) (g.getTimestamp()+1)*stepSize); + toTime = initDateTime.plusMinutes((int) (g.getTimestamp()+2)*stepSize); + break; + case DayTimeRange: + time = Helpers.calculateNextDay(time, g.getTimestamp(),daySelection,holidayStart,true); + fromTime = time.minusMinutes(timeRange); + toTime = time.plusMinutes(timeRange); + break; + + default: + break; + } + // Vorabberechnung aller Gewichte der Realen Sensoren + if(modus == TrafficModi.Continuous || modus == TrafficModi.DayTimeRange){ + db.getSensorWeights(fromTime,toTime, newTimestamp); + } + + double[] update = null; + for (IElement currentNode : g.getNodes()) { + + // Get Node + DirectedWeightedNode currentWeighted = null; + if(currentNode instanceof DirectedWeightedNode) + currentWeighted= (DirectedWeightedNode) currentNode; + else + continue; + + // Get Weight + switch (modus) { + case Continuous: + update = db.getSensorModelWeight(currentWeighted.getIndex(),fromTime,toTime,newTimestamp); + break; + case DayTimeRange: + update = db.getSensorModelWeight(currentWeighted.getIndex(),fromTime,toTime,newTimestamp); + break; + case Simulation: + update = trafficUpdate.isAffected(currentWeighted.getIndex()) ? db.getSensorModelWeightStaticBatch(currentWeighted.getIndex(),trafficUpdate) : null; + break; + default: + System.out.println("error - Modus nicht definiert @ TrafficSensorBatchGenerator"); + break; + } + Double3dWeight oldWeight = (Double3dWeight) currentWeighted.getWeight(); + if(update!=null){ + Double3dWeight newWeight = new Double3dWeight(update[0],update[1],update[2]); + + // Set Weight + if(!oldWeight.equals(newWeight)) + b.add(new NodeWeight((dna.graph.weights.IWeightedNode) currentNode,newWeight)); + } + else{ + update = new double[]{oldWeight.getX(),oldWeight.getY(),oldWeight.getZ()}; + } + + + // Edge Removal + EdgeContainer ec = null; + if(update[2] > treshold) { + newKey = currentWeighted.getIndex(); + int from; + int to; + // Verhindere das Hinzufügen bereits gelöschter Kante + if(disabledEdges.containsKey(newKey)){ + HashMap oldMap = disabledEdges.get(newKey); + for (Entry entry : oldMap.entrySet()) { + EdgeContainer key = entry.getKey(); + Edge value = entry.getValue(); + removeEdge(key.getTo(),key,value); + addEdge(key.getTo(), key, value); + removeEdge(key.getFrom(),key,value); + addEdge(key.getFrom(),key,value); + } + disabledEdges.remove(newKey); + } + + // Lösche neue Kanten + for (IElement elem : currentWeighted.getEdges()) { + edge = (Edge) elem; + from = edge.getN1Index(); + to = edge.getN2Index(); + ec = new EdgeContainer(from, to); + removeEdge(from,ec,edge); + removeEdge(to, ec, edge); + addEdge(from,ec,edge); + addEdge(to, ec, edge); + toDisable.add(edge); + } + } + } + + for (Edge e : toDisable) { + b.add(new EdgeRemoval(e)); + } + + for (Entry> freeEdges : disabledEdges.entrySet()) { + int node = freeEdges.getKey(); + for (Entry elem : freeEdges.getValue().entrySet()) { + if(node == elem.getKey().getFrom()) + b.add(new EdgeAddition(elem.getValue())); + } + } + + disabledEdges=newDisabledEdges; + + return b; + } + + @Override + public void reset() { + // TODO Auto-generated method stub + + } + + @Override + public boolean isFurtherBatchPossible(Graph g) { + // TODO Auto-generated method stub + return true; + } + + /** + * + * @param index + * @param ec + * @param e + */ + public void removeEdge(int index, EdgeContainer ec, Edge e){ + if(disabledEdges.containsKey(index)){ + HashMap oldMap = disabledEdges.get(index); + oldMap.remove(ec); + if(oldMap.isEmpty()){ + disabledEdges.remove(index); + } + } + } + public void addEdge(int index, EdgeContainer ec, Edge e){ + if(newDisabledEdges.containsKey(index)){ + HashMap oldMap = newDisabledEdges.get(index); + oldMap.put(ec, e); + } + else { + HashMap newMap = new HashMap<>(); + newMap.put(ec, e); + newDisabledEdges.put(index,newMap); + } + } + +}