예제 #1
0
 public bool Equals(RouteMark <TEdge> other)
 {
     if (this.IsEmpty || other.IsEmpty)
     {
         throw new InvalidOperationException();
     }
     return(this.CompareTo(other) == 0);
 }
예제 #2
0
        public int CompareTo(RouteMark <TEdge> other)
        {
            if (this.IsEmpty || other.IsEmpty)
            {
                throw new InvalidOperationException();
            }

            if (this.Cost < other.Cost)
            {
                return(-1);
            }
            else if (this.Cost > other.Cost)
            {
                return(1);
            }
            else
            {
                return(0);
            }
        }
예제 #3
0
        private IReadOnlyDictionary <P, (P, IEnumerable <TEdge>)> Msmt(IEnumerable <P> sources, IEnumerable <P> targets, Func <TEdge, double> cost,
                                                                       Func <TEdge, double> bound, double max)
        {
            /*
             * Initialize map of edges to target points.
             */
            var targetEdges = new Dictionary <TEdge, ICollection <P> >();

            foreach (var target in targets)
            {
                if (this.Logger.IsEnabled(LogLevel.Debug))
                {
                    this.Logger.LogDebug("initialize target {0} with edge {1} and fraction {2}",
                                         target, target.Edge.Id, target.Fraction);
                }

                if (!targetEdges.ContainsKey(target.Edge))
                {
                    targetEdges[target.Edge] = new HashSet <P> {
                        target
                    };
                }
                else
                {
                    targetEdges[target.Edge].Add(target);
                }
            }

            /*
             * Setup data structures
             */
            var priorities = new PriorityQueue <RouteMark <TEdge> >();
            var entries    = new Dictionary <TEdge, RouteMark <TEdge> >();
            var finishs    = new Dictionary <P, RouteMark <TEdge> >();
            var reaches    = new Dictionary <RouteMark <TEdge>, P>();
            var starts     = new Dictionary <RouteMark <TEdge>, P>();

            /*
             * Initialize map of edges with start points
             */
            foreach (var source in sources)
            {
                // initialize sources as start edges
                var startcost  = source.Edge.ComputeCost(1.0 - source.Fraction, cost);                     //cost.cost(source.Edge, 1 - source.Fraction);
                var startbound = bound != null?source.Edge.ComputeCost(1.0 - source.Fraction, bound) : 0D; //bound.cost(source.Edge.Cost(), 1 - source.Fraction) : 0.0;

                if (this.Logger.IsEnabled(LogLevel.Debug))
                {
                    this.Logger.LogDebug("init source {0} with start edge {1} and fraction {2} with {3} cost",
                                         source, source.Edge.Id, source.Fraction, startcost);
                }

                //On the same edge
                if (targetEdges.TryGetValue(source.Edge, out var targetsMap))
                {
                    // start edge reaches target edge
                    foreach (var target in targetsMap)
                    {
                        if (target.Fraction < source.Fraction)
                        {
                            continue;
                        }
                        var reachcost  = startcost - source.Edge.ComputeCost(1.0 - target.Fraction, cost);                       // cost.cost(source.Edge, 1 - target.Fraction);
                        var reachbound = bound != null ? startcost - source.Edge.ComputeCost(1.0 - target.Fraction, bound) : 0D; //, // bound.cost(source.Edge, 1 - target.Fraction) : 0.0;

                        if (this.Logger.IsEnabled(LogLevel.Debug))
                        {
                            this.Logger.LogDebug("reached target {0} with start edge {1} from {2} to {3} with {4} cost",
                                                 target, source.Edge.Id, source.Fraction, target.Fraction, reachcost);
                        }

                        var reach = new RouteMark <TEdge>(source.Edge, null, reachcost, reachbound);
                        reaches.Add(reach, target);
                        starts.Add(reach, source);
                        priorities.Enqueue(reach);
                    }
                }

                if (!entries.TryGetValue(source.Edge, out var start))
                {
                    if (this.Logger.IsEnabled(LogLevel.Debug))
                    {
                        this.Logger.LogDebug("add source {0} with start edge {1} and fraction {2} with {3} cost",
                                             source, source.Edge.Id, source.Fraction, startcost);
                    }
                    start = new RouteMark <TEdge>(source.Edge, null, startcost, startbound);
                    entries[source.Edge] = start;
                    starts[start]        = source;
                    priorities.Enqueue(start);
                }
                else
                {
                    if (startcost < start.Cost)
                    {
                        if (this.Logger.IsEnabled(LogLevel.Debug))
                        {
                            this.Logger.LogDebug("update source {0} with start edge {1} and fraction {2} with {3} cost",
                                                 source, source.Edge.Id, source.Fraction, startcost);
                        }
                        start = new RouteMark <TEdge>(source.Edge, null, startcost, startbound);
                        entries[source.Edge] = start;
                        starts[start]        = source;
                        priorities.Remove(start);
                        priorities.Enqueue(start);
                    }
                }
            }

            /*
             * Dijkstra algorithm.
             */
            while (priorities.Count > 0)
            {
                var current = priorities.Dequeue();

                if (targetEdges.Count == 0)
                {
                    if (this.Logger.IsEnabled(LogLevel.Debug))
                    {
                        this.Logger.LogDebug("finshed all targets");
                    }
                    break;
                }

                if (!double.IsNaN(max) && current.BoundingCost > max)
                {
                    if (this.Logger.IsEnabled(LogLevel.Debug))
                    {
                        this.Logger.LogDebug("reached maximum bound");
                    }
                    continue;
                }

                /*
                 * Finish target if reached.
                 */
                {
                    if (reaches.TryGetValue(current, out var target))
                    {
                        if (finishs.ContainsKey(target))
                        {
                            continue;
                        }
                        else
                        {
                            if (this.Logger.IsEnabled(LogLevel.Debug))
                            {
                                this.Logger.LogDebug("finished target {0} with edge {1} and fraction {2} with {3} cost",
                                                     target, current.MarkedEdge, target.Fraction, current.Cost);
                            }

                            finishs[target] = current;

                            var edges = targetEdges[current.MarkedEdge];
                            edges.Remove(target);

                            if (edges.Count == 0)
                            {
                                targetEdges.Remove(current.MarkedEdge);
                            }
                            continue;
                        }
                    }
                }

                if (this.Logger.IsEnabled(LogLevel.Debug))
                {
                    this.Logger.LogDebug("succeed edge {0} with {1} cost", current.MarkedEdge.Id, current.Cost);
                }

                var successors = current.MarkedEdge.Successors;

                foreach (var successor in successors)
                {
                    var succcost  = current.Cost + cost(successor);
                    var succbound = bound != null ? current.BoundingCost + bound(successor) : 0.0;

                    if (targetEdges.ContainsKey(successor))
                    {
                        // reach target edge
                        foreach (var targetEdge in targetEdges[successor])
                        {
                            var reachcost  = succcost - successor.ComputeCost(1.0 - targetEdge.Fraction, cost);
                            var reachbound = bound != null ? succbound - successor.ComputeCost(1.0 - targetEdge.Fraction, bound) : 0.0;    /// bound(successor, 1 - target.Fraction) : 0.0;
                            if (this.Logger.IsEnabled(LogLevel.Debug))
                            {
                                this.Logger.LogDebug("reached target {0} with successor edge {1} and fraction {2} with {3} cost",
                                                     targetEdge, successor.Id, targetEdge.Fraction, reachcost);
                            }

                            var reach = new RouteMark <TEdge>(successor, current.MarkedEdge, reachcost, reachbound);
                            reaches.Add(reach, targetEdge);
                            priorities.Enqueue(reach);
                        }
                    }

                    if (!entries.ContainsKey(successor))
                    {
                        if (this.Logger.IsEnabled(LogLevel.Debug))
                        {
                            this.Logger.LogDebug("added successor edge {0} with {1} cost", successor.Id, succcost);
                        }
                        var mark = new RouteMark <TEdge>(successor, current.MarkedEdge, succcost, succbound);
                        entries.Add(successor, mark);
                        priorities.Enqueue(mark);
                    }
                }
            }

            var paths = new Dictionary <P, (P, IEnumerable <TEdge>)>();

            foreach (P targetPoint in targets)
            {
                if (finishs.ContainsKey(targetPoint))
                {
                    var path     = new List <TEdge>();
                    var iterator = finishs[targetPoint];
                    var start    = RouteMark <TEdge> .Empty;
                    while (!iterator.IsEmpty)
                    {
                        path.Add(iterator.MarkedEdge);
                        start = iterator;
                        if (iterator.PredecessorEdge != null)
                        {
                            if (entries.TryGetValue(iterator.PredecessorEdge, out var pem))
                            {
                                iterator = pem;
                            }
                            else
                            {
                                iterator = RouteMark <TEdge> .Empty;
                            }
                        }
                        else
                        {
                            iterator = RouteMark <TEdge> .Empty;
                        }
                    }
                    path.Reverse();
                    var tp = (starts[start], path);
                    paths.Add(targetPoint, tp);
                }
            }

            /*
             * entries.Clear();
             * finishs.Clear();
             * reaches.Clear();
             * priorities.Clear();
             */

            return(paths);
        }