using System; using System.Collections.Generic; using System.Text; using OpenTraffic.Model.Route; namespace OpenTraffic.Model.Simulator { public class RouteGenerator { private Dictionary> routes; private List times; private bool first = true; private float[] sumDemands; private Random rand; private class ODPairRouteInformation { // private float MinTravelTime = float.PositiveInfinity; private List routes; private float totalCars; private const int MAX_ROUTES_PER_CARS = 2; private const int MAX_ROUTES = 20; public Demand demand; public bool WantsMoreRoutes = true; public void UpdateMoreRoutes() { WantsMoreRoutes = routes.Count < Math.Min(MAX_ROUTES, totalCars * MAX_ROUTES_PER_CARS); // WantsMoreRoutes = true; } public ODPairRouteInformation(Demand d, List times) { this.demand = d; routes = new List(); totalCars = 0.0f; int i = 0; foreach (TimeSlice t in times) { if (i >= d.Demands.Length) break; totalCars += d.Demands[i] * (t.Time); i++; } } public int CountParallell { get { int c = 0; foreach (RouteContainer rc in routes) { c += rc.Count; } return c; } } public int Count { get { return routes.Count; } } public bool ContainsRoute(RouteContainer nr) { // If the free flow traveltime is small than the rest it // has to be unique // Seem to help alot but if it has the minumum freeflowtraveltime // We should have found it much earlier. // xxx //if (nr.FreeFlowTravelTime < MinTravelTime) return false; foreach (RouteContainer or in routes) if (nr.Compare(or)) return true; return false; } public bool ShouldBeAdded(RouteContainer nr) { // xxx //if (nr.FreeFlowTravelTime > MinTravelTime * 1.3) return false; return !ContainsRoute(nr); } public void Add(RouteContainer r) { // xxxx // MinTravelTime = Math.Min(MinTravelTime, r.FreeFlowTravelTime); r.FillInId(); r.FillInParallellRoutes(); routes.Add(r); } public RouteContainer this[RouteContainer r] { get { foreach (RouteContainer nr in routes) { if (r.Compare(nr)) return nr; } throw new KeyNotFoundException(); } } public override string ToString() { string str = "*** " + demand.Origin + " -> " + demand.Destination + "****" + System.Environment.NewLine; ; foreach (RouteContainer r in routes) { str += r + System.Environment.NewLine; ; } return str; } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] public RouteGenerator( List demands, List initialRoutes, List times) { this.times = times; routes = new Dictionary>(); sumDemands = new float[times.Count]; float totDemand = 0; rand = new Random(33); foreach (Demand dem in demands) { if (!routes.ContainsKey(dem.Origin)) routes.Add(dem.Origin, new Dictionary()); if (!routes[dem.Origin].ContainsKey(dem.Destination)) routes[dem.Origin].Add(dem.Destination, new ODPairRouteInformation(dem, times)); for (int i = 0; i < dem.Demands.Length; i++) { sumDemands[i] += dem.Demands[i]; totDemand += dem.Demands[i]; } } for (int i = 0; i < sumDemands.Length; i++) sumDemands[i] = sumDemands[i] / totDemand; foreach (RouteContainer r in initialRoutes) { TrafficZone o = r.Source.Source as TrafficZone; TrafficZone d = r.Target.Target as TrafficZone; if (routes.ContainsKey(o) && routes[o].ContainsKey(d)) { routes[o][d].Add(r); } } } public List AddRoutes(List routesToAdd) { if (routesToAdd != null) { // Assume that we do not have so many "doublets?" List routesAdded = new List(routesToAdd.Count); foreach (RouteContainer r in routesToAdd) { if (routes.ContainsKey((TrafficZone)r.Source.Source) && routes[(TrafficZone)r.Source.Source].ContainsKey((TrafficZone)r.Target.Target)) { ODPairRouteInformation opri = routes[(TrafficZone)r.Source.Source][(TrafficZone)r.Target.Target]; if (opri.ContainsRoute(r)) { // Mark it by negating the iud. // Just some debug things that should be removed. // foreach (Route nr in opri.routes) nr.Id = nr.Compare(r) ? -nr.Id : nr.Id; RouteContainer nr = opri[r]; nr.Id = r.Id; nr.RouteGeneratorId = 3; } else { if (r.Source.Source.Id != r.Target.Target.Id) { r.RouteGeneratorId = 2; routesAdded.Add(r); opri.Add(r); } } } } return routesAdded; } return new List(); } // this algorithm only works good if you have called FindParallellRoutes before. public List GenerateAsManyRoutesAsPosible(RouteFactory rf, int tries, List classes) { TrafficProfile.GetProfile().Start("generate"); List newRoutes = new List(); if (rf != null) { int dot = 0; int nc = classes == null ? 1 : classes.Count; for (int j = 0; j < nc; j++) { VehicleClass c = classes == null ? null : classes[j]; for (int i = 0; i < tries; i++) { foreach (KeyValuePair> startKv in routes) { if (dot > (routes.Count * tries * nc) / 60) { Console.Write("."); dot = 0; } dot++; // xxx // if (startKv.Key.Id == 105) for (int k = 0; k < this.times.Count; k++) { if (this.sumDemands[k] != 0) { TimeSlice ts = times[k]; float t = ts.StartTime + (float)rand.NextDouble() * (ts.StopTime - ts.StartTime); foreach (KeyValuePair stopKv in startKv.Value) { if (stopKv.Value.demand.Demands[k] != 0.0f && stopKv.Value.WantsMoreRoutes) { TrafficProfile.GetProfile().Start("getroute"); RouteContainer nr = rf.GetRoute(startKv.Key, stopKv.Key, t, true, c); if (nr != null) { TrafficProfile.GetProfile().SStart("should be added + cache values"); if (!stopKv.Value.ContainsRoute(nr)) { TrafficProfile.GetProfile().SStart("Add routes"); newRoutes.Add(nr); TrafficProfile.GetProfile().SStart("parallell"); stopKv.Value.Add(nr); } } TrafficProfile.GetProfile().Stop(); } } } } } } } foreach (KeyValuePair> startKv in routes) { foreach (KeyValuePair stopKv in startKv.Value) { stopKv.Value.UpdateMoreRoutes(); } } TrafficProfile.GetProfile().Stop(); } Console.WriteLine(); Console.WriteLine("Found " + newRoutes.Count); Console.WriteLine(TrafficProfile.GetProfile()); return newRoutes; } public List GenerateMoreRoutes(RouteFactory rf) { step = 0.0f; bool makeNewRoutes = true; List newRoutes = new List(); if (first) { newRoutes.AddRange(GenerateFreeFlowRoutes(rf)); } // Be aware. Can use a lot of memory if (makeNewRoutes) { if (!first) { for (int i = 0; i < times.Count; i++) { TimeSlice t = times[i]; float prob = sumDemands[i]; // 100 procent of all od-pair GeneratePaths(rf, newRoutes, prob, (t.StartTime + t.StopTime) / 2); } } else { GeneratePaths(rf, newRoutes, 1.0f, 0.0f); } } first = false; return newRoutes; } public List GenerateFreeFlowRoutes(RouteFactory rf) { List newRoutes = new List(); if (rf != null) { foreach (KeyValuePair> startKv in routes) { foreach (KeyValuePair stopKv in startKv.Value) { // xxx // if (startKv.Key.Id == 105) if (stopKv.Value.Count == 0) { RouteContainer nr = rf.GetRoute(startKv.Key, stopKv.Key); if (nr != null) { stopKv.Value.Add(nr); newRoutes.Add(nr); } } } } } return newRoutes; } float step; private void GeneratePaths(RouteFactory rf, List newRoutes, float prob, float t) { foreach (KeyValuePair> startKv in routes) { step += 50 * prob / routes.Count; if (step > 1) { step--; Console.Write("."); } if (rand.NextDouble() < prob) { TrafficZone v1 = startKv.Key; foreach (KeyValuePair stopKv in startKv.Value) { TrafficZone v2 = stopKv.Key; if (v1 != v2) { RouteContainer nr = rf.GetRoute(v1, v2, t, true); if (stopKv.Value.ShouldBeAdded(nr)) { stopKv.Value.Add(nr); newRoutes.Add(nr); } } } } } } public string ToString(List compRoutes, bool detailed) { if (compRoutes != null) { int nExists = 0; int nLoops = 0; foreach (RouteContainer r in compRoutes) { ODPairRouteInformation opri = routes[(TrafficZone)r.Source.Source][(TrafficZone)r.Target.Target]; if (r.Source.Source == r.Target.Target) { nLoops++; } if (opri.ContainsRoute(r)) { nExists++; } } return ToString(detailed) + System.Environment.NewLine + "Has " + nExists + "common routes " + " with " + nLoops + "loops" + " missing " + (compRoutes.Count - nExists) + "routes" + System.Environment.NewLine; } return "compRoutes is 'null'"; } public override string ToString() { return ToString(false); } public string ToString(bool detailed) { string str = "RouteGenerator: "; Dictionary numberOfRoutesInEachPair = new Dictionary(); int nPara = 0; foreach (KeyValuePair> startKv in routes) { foreach (KeyValuePair stopKv in startKv.Value) { nPara += stopKv.Value.CountParallell; int c = stopKv.Value.Count; if (detailed) str += stopKv.Value; if (!numberOfRoutesInEachPair.ContainsKey(c)) { numberOfRoutesInEachPair.Add(c, 1); } else { numberOfRoutesInEachPair[c]++; } } } int tot = 0; foreach (KeyValuePair kv in numberOfRoutesInEachPair) { tot += kv.Key * kv.Value; ; str += kv.Key + ": " + kv.Value + " "; } str += "= " + tot + " (" + nPara + ")"; return str; } } }