|
36 | 36 |
|
37 | 37 | namespace Numerics.Mathematics.Optimization |
38 | 38 | { |
39 | | - public struct Edge |
| 39 | + /// <summary> |
| 40 | + /// Struct that represents an edge in a network. |
| 41 | + /// </summary> |
| 42 | + /// <remarks> |
| 43 | + /// Create an edge structure object. An edge contains information on the start node, end node, edge weight, and edge index. |
| 44 | + /// </remarks> |
| 45 | + /// <param name="fromNodeIndex">Node index at start of edge.</param> |
| 46 | + /// <param name="toNodeIndex">Node index at end of edge.</param> |
| 47 | + /// <param name="edgeWeight">Weight (or Cost) of the edge.</param> |
| 48 | + /// <param name="edgeIndex">Index of the edge.</param> |
| 49 | + public struct Edge(int fromNodeIndex, int toNodeIndex, float edgeWeight, int edgeIndex) |
40 | 50 | { |
41 | | - public int FromIndex; |
42 | | - public int ToIndex; |
43 | | - public float Weight; |
44 | | - public int Index; |
45 | | - |
46 | | - public Edge(int fromNodeIndex, int toNodeIndex, float edgeWeight, int edgeIndex) |
47 | | - { |
48 | | - FromIndex = fromNodeIndex; |
49 | | - ToIndex = toNodeIndex; |
50 | | - Weight = edgeWeight; |
51 | | - Index = edgeIndex; |
52 | | - } |
53 | | - } |
54 | | - |
55 | | - public class Networks |
56 | | - { |
57 | | - private readonly List<Edge>[] _outgoingEdges; |
58 | | - private readonly List<Edge>[] _incomingEdges; |
59 | | - private readonly int _nodeCount; |
60 | | - private readonly int[] _destinationIndices; |
61 | | - //private readonly RoadSegment[] _segments; |
62 | | - private readonly Edge[] _edges; |
63 | | - |
64 | | - //public RoadSegment[] Segments { get => _segments; } |
65 | | - public int[] DestinationIndices { get => _destinationIndices; } |
66 | | - public List<Edge>[] IncomingEdges { get => _incomingEdges; } |
67 | | - public List<Edge>[] OutgoingEdges { get => _outgoingEdges; } |
68 | | - |
69 | | - public static void ResultsToCSV(float[,] result, string outputFilePath) |
70 | | - { |
71 | | - System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFilePath); |
72 | | - //Headers |
73 | | - sw.WriteLine($"From_Node, To_Node, Edge, Weight_To_Destination"); |
74 | | - //Data |
75 | | - for (Int32 i = 0; i < result.GetLength(0); i++) { sw.WriteLine($"{i}, {result[i, 0]}, {result[i, 1]}, {result[i, 2]}"); } |
76 | | - sw.Close(); sw.Dispose(); |
77 | | - } |
78 | | - |
79 | | - public static int[] PathEdges(float[,] result, int startNodeIndex) |
80 | | - { |
81 | | - List<int> edgeList = new List<int>(); |
82 | | - int nodeIndex = startNodeIndex; |
83 | | - // generate the shortest path list from the results table |
84 | | - while (result[nodeIndex, 2] != 0) |
85 | | - { |
86 | | - edgeList.Add((int)result[nodeIndex, 1]); |
87 | | - nodeIndex = (int)result[nodeIndex, 0]; |
88 | | - } |
89 | | - return edgeList.ToArray(); |
90 | | - } |
91 | | - |
92 | | - //public int[] PathRecords(float[,] result, int startNodeIndex) |
93 | | - //{ |
94 | | - // List<int> featureList = new List<int>(); |
95 | | - // int nodeIndex = startNodeIndex; |
96 | | - // // generate the shortest path list from the results table |
97 | | - // while (result[nodeIndex, 2] != 0) |
98 | | - // { |
99 | | - // featureList.Add(_segments[(int)result[nodeIndex, 1]].RecordIndex); |
100 | | - // nodeIndex = (int)result[nodeIndex, 0]; |
101 | | - // } |
102 | | - // return featureList.ToArray(); |
103 | | - //} |
104 | | - |
105 | | - //public int[] PathRecords(float[,] result, int startRecordIndex) |
106 | | - //{ |
107 | | - // List<int> featureList = new List<int>(); |
108 | | - // for (int i = 0; i < result.GetLength(0); i++) |
109 | | - // { |
110 | | - // if (_segments[(int)result[i, 1]].RecordIndex == startRecordIndex) |
111 | | - // { |
112 | | - // int nodeIndex = i; |
113 | | - // // generate the shortest path list from the results table |
114 | | - // while (result[nodeIndex, 2] != 0) |
115 | | - // { |
116 | | - // featureList.Add(_segments[(int)result[nodeIndex, 1]].RecordIndex); |
117 | | - // nodeIndex = (int)result[nodeIndex, 0]; |
118 | | - // } |
119 | | - // break; |
120 | | - // } |
121 | | - // } |
122 | | - |
123 | | - // return featureList.ToArray(); |
124 | | - //} |
| 51 | + /// <summary> |
| 52 | + /// Node index at start of edge. |
| 53 | + /// </summary> |
| 54 | + public int FromIndex = fromNodeIndex; |
| 55 | + /// <summary> |
| 56 | + /// Node index at end of edge. |
| 57 | + /// </summary> |
| 58 | + public int ToIndex = toNodeIndex; |
| 59 | + /// <summary> |
| 60 | + /// Weight (or Cost) of transversing the edge. |
| 61 | + /// </summary> |
| 62 | + public float Weight = edgeWeight; |
| 63 | + /// <summary> |
| 64 | + /// Index of the edge, often used as an index to the edge source (e.g., road segment). |
| 65 | + /// </summary> |
| 66 | + public int Index = edgeIndex; |
125 | 67 | } |
126 | 68 |
|
127 | | - |
| 69 | + //public class Networks |
| 70 | + //{ |
| 71 | + // private readonly List<Edge>[] _outgoingEdges; |
| 72 | + // private readonly List<Edge>[] _incomingEdges; |
| 73 | + // private readonly int _nodeCount; |
| 74 | + // private readonly int[] _destinationIndices; |
| 75 | + // //private readonly RoadSegment[] _segments; |
| 76 | + // private readonly Edge[] _edges; |
| 77 | + |
| 78 | + // //public RoadSegment[] Segments { get => _segments; } |
| 79 | + // public int[] DestinationIndices { get => _destinationIndices; } |
| 80 | + // public List<Edge>[] IncomingEdges { get => _incomingEdges; } |
| 81 | + // public List<Edge>[] OutgoingEdges { get => _outgoingEdges; } |
| 82 | + |
| 83 | + // public static void ResultsToCSV(float[,] result, string outputFilePath) |
| 84 | + // { |
| 85 | + // System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFilePath); |
| 86 | + // //Headers |
| 87 | + // sw.WriteLine($"From_Node, To_Node, Edge, Weight_To_Destination"); |
| 88 | + // //Data |
| 89 | + // for (int i = 0; i < result.GetLength(0); i++) { sw.WriteLine($"{i}, {result[i, 0]}, {result[i, 1]}, {result[i, 2]}"); } |
| 90 | + // sw.Close(); sw.Dispose(); |
| 91 | + // } |
| 92 | + |
| 93 | + // public static int[] PathEdges(float[,] result, int startNodeIndex) |
| 94 | + // { |
| 95 | + // List<int> edgeList = new List<int>(); |
| 96 | + // int nodeIndex = startNodeIndex; |
| 97 | + // // generate the shortest path list from the results table |
| 98 | + // while (result[nodeIndex, 2] != 0) |
| 99 | + // { |
| 100 | + // edgeList.Add((int)result[nodeIndex, 1]); |
| 101 | + // nodeIndex = (int)result[nodeIndex, 0]; |
| 102 | + // } |
| 103 | + // return edgeList.ToArray(); |
| 104 | + // } |
| 105 | + |
| 106 | + // //public int[] PathRecords(float[,] result, int startNodeIndex) |
| 107 | + // //{ |
| 108 | + // // List<int> featureList = new List<int>(); |
| 109 | + // // int nodeIndex = startNodeIndex; |
| 110 | + // // // generate the shortest path list from the results table |
| 111 | + // // while (result[nodeIndex, 2] != 0) |
| 112 | + // // { |
| 113 | + // // featureList.Add(_segments[(int)result[nodeIndex, 1]].RecordIndex); |
| 114 | + // // nodeIndex = (int)result[nodeIndex, 0]; |
| 115 | + // // } |
| 116 | + // // return featureList.ToArray(); |
| 117 | + // //} |
| 118 | + |
| 119 | + // //public int[] PathRecords(float[,] result, int startRecordIndex) |
| 120 | + // //{ |
| 121 | + // // List<int> featureList = new List<int>(); |
| 122 | + // // for (int i = 0; i < result.GetLength(0); i++) |
| 123 | + // // { |
| 124 | + // // if (_segments[(int)result[i, 1]].RecordIndex == startRecordIndex) |
| 125 | + // // { |
| 126 | + // // int nodeIndex = i; |
| 127 | + // // // generate the shortest path list from the results table |
| 128 | + // // while (result[nodeIndex, 2] != 0) |
| 129 | + // // { |
| 130 | + // // featureList.Add(_segments[(int)result[nodeIndex, 1]].RecordIndex); |
| 131 | + // // nodeIndex = (int)result[nodeIndex, 0]; |
| 132 | + // // } |
| 133 | + // // break; |
| 134 | + // // } |
| 135 | + // // } |
| 136 | + |
| 137 | + // // return featureList.ToArray(); |
| 138 | + // //} |
| 139 | + //} |
| 140 | + |
| 141 | + |
| 142 | + /// <summary> |
| 143 | + /// Dijkstra dynamic programming implementation for shortest path optimization. |
| 144 | + /// </summary> |
128 | 145 | public static class Dijkstra |
129 | 146 | { |
130 | 147 | /// <summary> |
@@ -255,7 +272,7 @@ public static class Dijkstra |
255 | 272 | resultTable[destinationIndex, 0] = destinationIndex; //Tail |
256 | 273 | resultTable[destinationIndex, 1] = -1; //edge index |
257 | 274 | resultTable[destinationIndex, 2] = 0; //Cumulative Weight |
258 | | - |
| 275 | + previousValue = destinationIndex; |
259 | 276 | if (edgesToNodes[previousValue] == null) { continue; } |
260 | 277 |
|
261 | 278 | //Add the nodes to the heap connected to the given destination node. |
|
0 commit comments