package org.opentrafficsim.demo.ntm;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Random;
import org.djunits.unit.DurationUnit;
import org.djunits.unit.LengthUnit;
import org.djunits.unit.SpeedUnit;
import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.FloydWarshallShortestPaths;
import org.opentrafficsim.core.network.LinkEdge;
import org.opentrafficsim.demo.ntm.NTMNode.TrafficBehaviourType;
/**
*
* Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* $LastChangedDate$, @version $Revision$, by $Author$,
* initial version 22 Jan 2015
* @author Alexander Verbraeck
* @author Hans van Lint
* @author Peter Knoppers
* @author Guus Tamminga
* @author Yufei Yuan
*/
public class Routes
{
public final static long seed = 100;
public static Random fRandom = new Random(seed);
/**
* @param model NTMModel;
* @param numberOfRoutes int;
* @param weight_newRoutes double;
* @param VARIANCE double;
* @param initiateSimulation boolean;
* @param steps int;
* @param MAXSTEPS int;
* @throws IOException
*/
public static void createRoutes(NTMModel model, int numberOfRoutes, double weight_newRoutes, double VARIANCE,
final boolean initiateSimulation, int steps, int MAXSTEPS) throws IOException
{
// every route receives a fixed share
java.lang.Double addShare = (double) (1.0 / numberOfRoutes);
/** */
BufferedWriter dataRoutesNTMOut = null;
String fileName = "/ALLroutes";
File file = new File(model.getSettingsNTM().getPath() + model.getInputNTM().getOutputMap() + fileName + steps + ".txt");
dataRoutesNTMOut = WriteOutput.createWriter(file);
for (int i = 0; i < numberOfRoutes; i++)
{
// create stochastic link edge weights
for (LinkEdge le : model.getAreaGraph().edgeSet())
{
double rateCongestedVersusFreeTravelTime = 1.0;
BoundedNode startNode = (BoundedNode) model.getNodeAreaGraphMap().get(le.getLink().getStartNode().getId());
BoundedNode endNode = (BoundedNode) model.getNodeAreaGraphMap().get(le.getLink().getEndNode().getId());
if (!initiateSimulation)
{
if (startNode.getBehaviourType() == TrafficBehaviourType.NTM
&& endNode.getBehaviourType() == TrafficBehaviourType.NTM)
{
CellBehaviourNTM cellBehaviourStart = (CellBehaviourNTM) startNode.getCellBehaviour();
if (cellBehaviourStart.getAccumulatedCars() > 0)
{
double currentSpeedStart =
cellBehaviourStart
.retrieveCurrentSpeed(cellBehaviourStart.getAccumulatedCars(),
cellBehaviourStart.getArea().getRoadLength())
.getInUnit(SpeedUnit.KM_PER_HOUR);
double freeSpeedStart =
cellBehaviourStart.getParametersNTM().getFreeSpeed().getInUnit(SpeedUnit.KM_PER_HOUR);
rateCongestedVersusFreeTravelTime = 0.5 * freeSpeedStart / currentSpeedStart;
CellBehaviourNTM cellBehaviourEnd = (CellBehaviourNTM) endNode.getCellBehaviour();
double currentSpeedEnd =
cellBehaviourEnd
.retrieveCurrentSpeed(cellBehaviourEnd.getAccumulatedCars(),
cellBehaviourStart.getArea().getRoadLength())
.getInUnit(SpeedUnit.KM_PER_HOUR);
double freeSpeedEnd =
cellBehaviourEnd.getParametersNTM().getFreeSpeed().getInUnit(SpeedUnit.KM_PER_HOUR);
rateCongestedVersusFreeTravelTime += 0.5 * freeSpeedEnd / currentSpeedEnd;
}
}
else if (startNode.getBehaviourType() == TrafficBehaviourType.FLOW
&& endNode.getBehaviourType() == TrafficBehaviourType.FLOW)
{
// the endNode of this edge is the "Neighbour" area
LinkCellTransmission ctmLink = (LinkCellTransmission) le.getLink();
double freeTime = ctmLink.getDuration().getInUnit(DurationUnit.SECOND);
double currrentTime = ctmLink.retrieveActualTime().getInUnit(DurationUnit.SECOND);
rateCongestedVersusFreeTravelTime = currrentTime / freeTime;
if (rateCongestedVersusFreeTravelTime > 10000)
{
System.out.println("Start: " + startNode.getId() + " End node: " + endNode.getId()
+ " currentTime: " + currrentTime + " freeTime: " + currrentTime);
double testCurrrentTime = ctmLink.retrieveActualTime().getInUnit(DurationUnit.SECOND);
}
}
}
if (startNode.getBehaviourType() == TrafficBehaviourType.CORDON
|| endNode.getBehaviourType() == TrafficBehaviourType.CORDON)
{
rateCongestedVersusFreeTravelTime = 999999;
}
double speed = le.getLink().getFreeSpeed().getInUnit(SpeedUnit.METER_PER_SECOND);
double length = le.getLink().getLength().getInUnit(LengthUnit.METER);
double travelTime = length / speed;
// double weight =
// rateCongestedVersusFreeTravelTime * model.getAreaGraph().getEdgeWeight(le) * Gaussian(VARIANCE, 100);
double weight = rateCongestedVersusFreeTravelTime * travelTime * Gaussian(fRandom, VARIANCE);
model.getAreaGraph().setEdgeWeight(le, weight);
}
FloydWarshallShortestPaths> allPaths =
new FloydWarshallShortestPaths<>(model.getAreaGraph());
Collection>> sp1 = new LinkedHashSet<>();
for (NTMNode source : model.getAreaGraph().vertexSet())
{
for (NTMNode sink : model.getAreaGraph().vertexSet())
{
sp1.add(allPaths.getPath(source, sink));
}
}
// assign a share to every route (i)
for (GraphPath> path : sp1)
{
BoundedNode origin = (BoundedNode) path.getStartVertex();
BoundedNode destination = (BoundedNode) path.getEndVertex();
// only generate to "real" destinations
if (destination.getBehaviourType() == TrafficBehaviourType.NTM
|| destination.getBehaviourType() == TrafficBehaviourType.CORDON)
{
// determine the start and end node of the first edge that starts from the origin
// the endNode of this edge is the "Neighbour" area
BoundedNode startNode = (BoundedNode) path.getEdgeList().get(0).getLink().getStartNode();
BoundedNode endNode = (BoundedNode) path.getEdgeList().get(0).getLink().getEndNode();
// the order of endNode and startNode of the edge seems to be not consistent!!!!!!
if (origin.equals(endNode))
{
endNode = startNode;
}
double weightNew = 0.0;
if (origin.getId().equals("1"))
{
System.out.println("dest " + destination.getId() + " neighbour: " + endNode.getId());
}
// only at first step of the simulation: initiate variables
if (initiateSimulation)
{
weightNew = 1.0;
if (i == 0)
{
LinkedHashMap neighbours = new LinkedHashMap();
LinkedHashMap accumulatedCarsToNeighbour =
new LinkedHashMap();
LinkedHashMap demandToNeighbour =
new LinkedHashMap();
TripInfoByDestination tripInfoByNode = new TripInfoByDestination(neighbours,
accumulatedCarsToNeighbour, demandToNeighbour, destination);
origin.getCellBehaviour().getTripInfoByDestinationMap().put(destination, tripInfoByNode);
}
}
// during the simulation: reset the weight of the old routes (1-weight_newRoutes) and add the new
// routes
else
{
weightNew = weight_newRoutes;
// reset the "old" shares with the weight_newRoutes
if (i == 0)
{
for (BoundedNode node : origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination)
.getRouteFractionToNeighbours().keySet())
{
java.lang.Double oldShare = origin.getCellBehaviour().getTripInfoByDestinationMap()
.get(destination).getRouteFractionToNeighbours().get(node);
origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination)
.getRouteFractionToNeighbours().put(node, (1 - weightNew) * oldShare);
}
}
}
// for all node - destination pairs add information on their first neighbour on the shortest path
BoundedNode neighbour = (BoundedNode) model.getNodeAreaGraphMap().get(endNode.getId());
java.lang.Double share = 0.0;
if (origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination).getRouteFractionToNeighbours()
.containsKey(neighbour))
{
share = origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination)
.getRouteFractionToNeighbours().get(neighbour);
if (share > 0.0)
{
System.out.println("Share: " + share);
}
}
origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination).getRouteFractionToNeighbours()
.put(neighbour, share + weightNew * addShare);
// create a field to store accumulated cars to a certain neighbour on its path to a destination
if (!origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination)
.getAccumulatedCarsToNeighbour().containsKey(neighbour))
{
origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination).getAccumulatedCarsToNeighbour()
.put(neighbour, 0.0);
origin.getCellBehaviour().getTripInfoByDestinationMap().get(destination).getDemandToNeighbour()
.put(neighbour, 0.0);
}
if (startNode == null || neighbour == null || destination == null)
{
System.out.println("Floyd");
}
WriteOutput.writeOutputRoutesNTM(model, steps, i, origin, neighbour, destination, MAXSTEPS,
dataRoutesNTMOut, share, weightNew * addShare, path.getWeight());
// only for initialisation of routes over the flow Links;
if (path.getEdgeList().get(0).getLink().getBehaviourType() == TrafficBehaviourType.FLOW)
{
// for the flow links we create the trip info by Node also for the flow cells
LinkCellTransmission ctmLink =
(LinkCellTransmission) model.getAreaGraph().getEdge(origin, neighbour).getLink();
// Loop through the cells and do transmission
for (FlowCell cell : ctmLink.getCells())
{
// only at first step: initiate variables
if (initiateSimulation)
{
LinkedHashMap neighbours =
new LinkedHashMap();
LinkedHashMap accumulatedCarsToNeighbour =
new LinkedHashMap();
LinkedHashMap demandToNeighbour =
new LinkedHashMap();
TripInfoByDestination tripInfoByNode = new TripInfoByDestination(neighbours,
accumulatedCarsToNeighbour, demandToNeighbour, destination);
cell.getCellBehaviourFlow().getTripInfoByDestinationMap().put(destination, tripInfoByNode);
}
else
{
if (cell.getCellBehaviourFlow().getTripInfoByDestinationMap().get(destination) == null)
{
LinkedHashMap neighbours =
new LinkedHashMap();
LinkedHashMap accumulatedCarsToNeighbour =
new LinkedHashMap();
LinkedHashMap demandToNeighbour =
new LinkedHashMap();
TripInfoByDestination tripInfoByNode = new TripInfoByDestination(neighbours,
accumulatedCarsToNeighbour, demandToNeighbour, destination);
cell.getCellBehaviourFlow().getTripInfoByDestinationMap().put(destination, tripInfoByNode);
}
}
cell.getCellBehaviourFlow().getTripInfoByDestinationMap().get(destination)
.getRouteFractionToNeighbours().put(neighbour, 1.0);
}
}
}
}
}
dataRoutesNTMOut.close();
}
/**
* @param fRandom
* @param VARIANCE double;
* @return
*/
public static double Gaussian(Random random, double VARIANCE)
{
double MEAN = 100.0f;
double number = MEAN + random.nextGaussian() * VARIANCE;
return number / 100;
}
}