Example #1
0
 /// <summary>
 /// Initializes the P array for the algorithm.
 /// </summary>
 /// <param name="startingNode">
 /// The node that has been designated the starting node for the entire algorithm.
 /// </param>
 /// <returns>
 /// The new P array.
 /// </returns>
 /// <remarks>
 /// A fresh P array will set every single node's source node to be
 /// the starting node, including the starting node itself.
 /// </remarks>
 protected virtual int[] GetStartingBestPath(int startingNode, DijkstraInfo di)
 {
     int[] p = new int[TotalNodeCount];
     for (int i = 0; i < p.Length; i++)
     {
         p[i] = startingNode;
     }
     return(p);
 }
Example #2
0
 /// <summary>
 /// Initializes the D array for the start of the algorithm.
 /// </summary>
 /// <param name="start">
 /// The starting node.
 /// </param>
 /// <returns>
 /// The contents of the new D array.
 /// </returns>
 /// <remarks>
 /// The traversal cost for every node will be set to impossible
 /// (int.MaxValue) unless a connecting edge is found between the
 /// <paramref name="start"/>ing node and the node in question.
 /// </remarks>
 protected virtual int[] GetStartingTraversalCost(int start, DijkstraInfo di)
 {
     int[] subset = new int[TotalNodeCount];
     for (int i = 0; i < subset.Length; i++)
     {
         subset[i] = int.MaxValue; // all are unreachable
     }
     subset[start] = 0;            // zero cost from start to start
     foreach (int nearby in Hint(start, di))
     {
         subset[nearby] = TraversalCost(start, nearby, di);
     }
     return(subset);
 }
Example #3
0
 private int getInternodeTraversalCost(int start, int finish, DijkstraInfo di)
 {
     //TODO: If Dijkstra gets slow
     //This is sloppy:
     //(1) It loops through all edges/arrows: could have pointers in the nodes themselves ('parents' and 'children')
     //    Then we could check the start node and see if it points to finish node. (Or make a hashtable of connections)
     //See also nearbyNodesHint()
     foreach (EdgeData ed in di.edges)
     {
         if (ed.to == start && ed.from == finish)
         {
             return(1);
         }
     }
     return(int.MaxValue);
 }
Example #4
0
        /// <summary>
        /// Performs the Dijkstra algorithm on the data provided when the
        /// <see cref="Dijkstra"/> object was instantiated.
        /// </summary>
        /// <param name="start">
        /// The node to use as a starting location.
        /// </param>
        /// <returns>
        /// A struct containing both the minimum distance and minimum path
        /// to every node from the given <paramref name="start"/> node.
        /// </returns>
        public virtual Results Perform(int start, DijkstraInfo di)
        {
            // Initialize the distance to every node from the starting node.
            int[] d = GetStartingTraversalCost(start, di);
            // Initialize best path to every node as from the starting node.
            int[]             p = GetStartingBestPath(start, di);
            ICollection <int> c = GetChoices();

            c.Remove(start); // take starting node out of the list of choices

            //Debug.WriteLine("Step v C D P");
            //Debug.WriteLine(string.Format("init - {{{0}}} [{1}] [{2}]",
            // ArrayToString<int>(",", c), ArrayToString<int>(",", d), ArrayToString<int>(",", p)));
            //int step = 0;

            // begin greedy loop
            while (c.Count > 1)
            {
                // Find element v in c, that minimizes d[v]
                int v = FindMinimizingDinC(d, c);
                c.Remove(v); // remove v from the list of future solutions
                // Consider all unselected nodes and consider their cost from v.
                foreach (int w in (Hint != null ? Hint(v, di) : c))
                {
                    if (!c.Contains(w))
                    {
                        continue;                 // discard pixels not in c
                    }
                    // At this point, relative(Index) points to a candidate pixel,
                    // that has not yet been selected, and lies within our area of interest.
                    // Consider whether it is now within closer reach.
                    int cost = TraversalCost(v, w, di);
                    if (cost < int.MaxValue && d[v] + cost < d[w]) // don't let wrap-around negatives slip by
                    {
                        // We have found a better way to get at relative
                        d[w] = d[v] + cost; // record new distance
                        // Record how we came to this new pixel
                        p[w] = v;
                    }
                }
                //Debug.WriteLine(string.Format("{4} {3} {{{0}}} [{1}] [{2}]",
                // ArrayToString<int>(",", c), ArrayToString<int>(",", d), ArrayToString<int>(",", p), v + 1, ++step));
            }

            return(new Results(p, d));
        }
Example #5
0
        private IEnumerable <int> nearbyNodesHint(int startingNode, DijkstraInfo di)
        {
            //TODO: If Dijkstra gets slow
            //This is sloppy in two ways:
            //(1) It loops through all edges/arrows: could have pointers in the nodes themselves ('parents' and 'children')
            //(2) It creates a new List<int>. If the above is done, we could just point to the 'children' list.
            //See also getInternodeTraversalCost()
            List <int> nearbyNodes = new List <int>();

            foreach (EdgeData ed in di.edges)
            {
                if (ed.to == startingNode)
                {
                    nearbyNodes.Add(ed.from);                         //there should be no dublets in this list
                }
            }
            return(nearbyNodes);
        }
Example #6
0
        public DataModel(int iterations, double weightMax, bool firstTime)
        {
            if (FruchtermanReingoldLayout.h == null)
            {
                return;
            }
            //
            // Populate the data model with some example data.
            //
            if (firstTime || FlowGlobals.rectangles == null)
            {
                FlowGlobals.rectangles = new ObservableCollection <RectangleData>();
                FlowGlobals.arrows     = new ObservableCollection <ArrowData>();
            }
            else
            {
                FlowGlobals.rectangles.Clear();
                FlowGlobals.arrows.Clear();
            }
            ObservableCollection <RectangleData> rectangles = FlowGlobals.rectangles;
            ObservableCollection <ArrowData>     arrows     = FlowGlobals.arrows;

            double width  = 90;
            double height = 70;

            Random r = new Random(12345);

            r = new Random(54321);
            r = new Random(11111);
            List <EdgeData> edges = new List <EdgeData>();
            List <NodeData> nodes = new List <NodeData>();

            NodeData startNode = null;

            foreach (FlowArrow fa in FruchtermanReingoldLayout.h.flowArrows)
            {
                if (!double.IsNaN(weightMax) && Math.Abs(fa.weight) < weightMax)
                {
                    continue;
                }
                EdgeData ed = new EdgeData {
                    from = fa.counter1, to = fa.counter2, weight = fa.weight
                };
                edges.Add(ed);
            }

            foreach (FlowNode fa in FruchtermanReingoldLayout.h.flowNodes)
            {
                NodeData nd = new NodeData {
                    x = r.Next((int)(0.005d * contentWidth), (int)contentWidth), y = r.Next((int)(0.005d * contentWidth), (int)contentWidth), name = fa.varName, labelBig = fa.labelBig, isExogenous = fa.isExogenous, isStartNode = fa.isStartNode, id = fa.id
                };
                nodes.Add(nd);
                if (nd.isStartNode)
                {
                    startNode = nd;
                }
            }

            Dictionary <int, NodeData> d = new Dictionary <int, NodeData>();

            foreach (NodeData nd in nodes)
            {
                d.Add(nd.id, nd);
            }

            //TODO: The Dijkstra algorithm is a bit sloppy, for instance using List<int> and removing items from this list (use Dictionary instead)
            DijkstraInfo di = new DijkstraInfo();

            di.nodes = nodes;
            di.edges = edges;
            Dijkstra dijkstra = new Dijkstra(nodes.Count, new Dijkstra.InternodeTraversalCost(getInternodeTraversalCost), new Dijkstra.NearbyNodesHint(nearbyNodesHint), di);

            Dijkstra.Results results = dijkstra.Perform(startNode.id, di);
            //int[] minimumPath = dijkstra.GetMinimumPath(0, 102, di);

            //Now we filter out

            List <EdgeData> edges2 = new List <EdgeData>();
            List <NodeData> nodes2 = new List <NodeData>();

            int large = 1000000000;
            Dictionary <int, int> rename = new Dictionary <int, int>();

            foreach (NodeData nd in nodes)
            {
                int value = results.MinimumDistance[nd.id];
                if (value < 0)
                {
                    value = large;  //do not minus it: -int.MinValue gives a strange result!
                }
                if (value < large)  //it seems these distances can become = int.MinValue, maybe int.MaxValue+1. So this is to identify those.
                {
                    int number = nodes2.Count;
                    rename.Add(nd.id, number);
                    nd.id = number;  //now id numbers in List 'nodes' are inconsistent, but never mind that
                    nodes2.Add(nd);
                }
            }

            foreach (EdgeData ed in edges)
            {
                if (rename.ContainsKey(ed.from) && rename.ContainsKey(ed.to))
                {
                    ed.from = rename[ed.from];
                    ed.to   = rename[ed.to];
                    edges2.Add(ed); //now id numbers in List 'edges' are inconsistent, but never mind that
                }
            }

            SolveInfo si = new SolveInfo();

            si.width      = width;
            si.height     = height;
            si.rectangles = rectangles;
            si.arrows     = arrows;
            si.edges      = edges2;
            si.nodes      = nodes2;
            si.iterations = iterations;
            if (si.iterations == -12345)
            {
                si.iterations = 200;
            }
            si.useSmartRepulse = true;
            si.useWeight       = true;
            FruchtermanReingoldLayout.Solve(si);
        }
Example #7
0
 /// <summary>
 /// Creates an instance of the <see cref="Dijkstra"/> class.
 /// </summary>
 /// <param name="totalNodeCount">
 /// The total number of nodes in the graph.
 /// </param>
 /// <param name="traversalCost">
 /// The delegate that can provide the cost of a transition between
 /// any two nodes.
 /// </param>
 /// <param name="hint">
 /// An optional delegate that can provide a small subset of nodes
 /// that a given node may be connected to.
 /// </param>
 public Dijkstra(int totalNodeCount, InternodeTraversalCost traversalCost, NearbyNodesHint hint, DijkstraInfo di)
 {
     if (totalNodeCount < 3)
     {
         throw new ArgumentOutOfRangeException("totalNodeCount", totalNodeCount, "Expected a minimum of 3.");
     }
     if (traversalCost == null)
     {
         throw new ArgumentNullException("traversalCost");
     }
     Hint           = hint;
     TraversalCost  = traversalCost;
     TotalNodeCount = totalNodeCount;
 }
Example #8
0
        /// <summary>
        /// Finds an array of nodes that provide the shortest path
        /// from one given node to another.
        /// </summary>
        /// <param name="start">
        /// The starting node.
        /// </param>
        /// <param name="finish">
        /// The finishing node.
        /// </param>
        /// <param name="shortestPath">
        /// The P array of the completed algorithm.
        /// </param>
        /// <returns>
        /// The list of nodes that provide the one step at a time path
        /// from <paramref name="start"/> to <paramref name="finish"/> nodes.
        /// </returns>
        protected virtual int[] GetMinimumPath(int start, int finish, int[] shortestPath, DijkstraInfo di)
        {
            Stack <int> path = new Stack <int>();

            do
            {
                path.Push(finish);
                finish = shortestPath[finish]; // step back one step toward the start point
            }while (finish != start);
            return(path.ToArray());
        }
Example #9
0
        /// <summary>
        /// Uses the Dijkstra algorithhm to find the minimum path
        /// from one node to another.
        /// </summary>
        /// <param name="start">
        /// The node to use as a starting location.
        /// </param>
        /// <param name="finish">
        /// The node to use as a finishing location.
        /// </param>
        /// <returns>
        /// A struct containing both the minimum distance and minimum path
        /// to every node from the given <paramref name="start"/> node.
        /// </returns>
        public virtual int[] GetMinimumPath(int start, int finish, DijkstraInfo di)
        {
            Results results = Perform(start, di);

            return(GetMinimumPath(start, finish, results.MinimumPath, di));
        }