public List<string> lines; // what lines is this station part of (ie a train line and a bus route) #endregion Fields #region Constructors public GraphNode(station station, string line, station next, station prev) { name = station.name; // set the name of the node to the name of the station lines = new List<string>(); // this list is kinda redundant, but you can see what lines exist in the graph if you access it lines.Add(line); // add this line/route to the list of lines/routes that this station is part of adjacency_list = new Dictionary<string, Dictionary<string, station>>(); // <line, <next/prev, station>> Dictionary<string, station> adj = new Dictionary<string, station>(); // <next = station, prev = station> adj.Add("next", next); // "next" = station next adj.Add("prev", prev); // "prev" = station prev adjacency_list.Add(line, adj); }
/// <summary> /// Perform a Breadth First Search on the graph, given a station to start at, and a destination. This function will always find a path /// (and currently prints it out to the console and returns true) if the graph is connected, however, the path is not (guaranteed to be) /// optimal. /// /// Because Breadth First Search is primarily a search algorithm, and not a path finding algorithm, some extra functionality has been added /// to the graph, namely the wrapping of GraphNode objects in PathNode objects, which contain a linked-list style reference from a node to /// it's previous node, to enable a backtrace once the destination is found. This backtrace returns the path taken to the node that is found /// and is the desired output of this function. The return value needs to adjusted a JSON object that contains this path. /// </summary> /// <param name="start">The station to start at.</param> /// <param name="end">The station to end at.</param> /// <returns>At this stage, true = found, false = not found (and generally means an error has occurred, probably in the creation /// of the graph structure, and probably with the format of the input data).</returns> public List<string> BFS(station start, station end) { // this dictionary contains PathNode pairs, a node and it's previous node, to determine the path // a PathNode contains a GraphNode and the name of the line that was used when passing the node. Dictionary<PathNode, PathNode> path = new Dictionary<PathNode, PathNode>(); // FIRST CHECK IF THE start NODE EXISTS GraphNode root = null; bool found = false; foreach (GraphNode n in graph) // first check if the station is in the graph { if (n.name == start.name) { root = n; // store this node as the root node to begin BFS with found = true; // the station does exist } } if (found == false) // the station does NOT exist, return return null; // END CHECK IF start NODE EXISTS // BFS PROPER Queue<PathNode> queue = new Queue<PathNode>(); // pathnode stores the line as well as the node List<string> visited = new List<string>(); // this list contains the name of ALL nodes that have been visited. PathNode root_pathnode = new PathNode(root.name, "", root); queue.Enqueue(root_pathnode); // enqueue the root node (starting point) visited.Add(root.name); // and mark it as visited (this list keeps track of visited nodes so they don't get visited again) path.Add(root_pathnode, null); // no line given to PathNode just yet while (queue.Count > 0) // while the queue is not empty, we still have nodes to check { PathNode check = queue.Dequeue(); // dequeue the next node if (check.node.name == end.name) // if this is the end node, we are done { //Console.WriteLine("FOUND IT!! Start {0} End {1}\n", start.name, end.name); // print a message PathNode curr = check, prev; // set curr to the node we found and init prev to null List<string> list_path = new List<string>(); // this list contains the path list_path.Add(curr.line + " - " + curr.name); // add the node we just found as the end of the path while (curr.node != root) // while we are not back at the first node { if (path.TryGetValue(curr, out prev) == true) // found a value matching the key { list_path.Add(curr.line + " - " + prev.name); // add the previous node to the path curr = prev; // set current node to previous node and repeat } else { Console.WriteLine("Couldn't find the prev pathnode, path broken."); // uh oh return null; // we should return if this happens, there's no way to show the path, it shouldn't happen though //break; // finished, we're doomed } } //print the path to console //Console.WriteLine(); list_path.Reverse(); // the nodes are back to front, reverse them foreach (string s in list_path) { Console.WriteLine("Path: {0}", s); // print each 'line - station' in the path } return list_path; } // This part is the main BFS loop, it just keeps going until we find the destination // FIND ALL NODES THAT THIS NODE CONNECTS TO AND ADD THEM TO THE QUEUE string[] lines = check.node.adjacency_list.Keys.ToArray<string>(); // get all the lines that this node is part of foreach (string line in lines) { Dictionary<string, station> adj = check.node.adjacency_list[line]; // grab the next/prev dict foreach (KeyValuePair<string, station> pair in adj) // for next, and prev { if (pair.Value != null) // either next or prev exists { foreach (GraphNode n in graph) // find the station in the graph (this sucks, I have to search the whole graph to find the node again) { if (n.name == pair.Value.name && visited.Contains(n.name) == false) // if the node name matches the next/prev name we are checking AND we haven't visited it before { PathNode to_queue = new PathNode(n.name, line, n); // create a new PathNode with the node name, line and a copy of the GraphNode queue.Enqueue(to_queue); // enqueue it visited.Add(n.name); // mark it as visited found = true; // flag the station does exist path.Add(to_queue, check); // add the node, and it's previous node to the path so we can retrace steps at the end } } if (found == false) // the station does NOT exist, return false (this is bad and shouldn't happen, means we have bad references) return null; } } } } return null; // not found, again, shouldn't happen if we are searching for a station that exists }
/// <summary> /// Create a new station object. /// </summary> /// <param name="id">Initial value of the id property.</param> /// <param name="line_id">Initial value of the line_id property.</param> /// <param name="name">Initial value of the name property.</param> public static station Createstation(global::System.Int32 id, global::System.Int32 line_id, global::System.String name) { station station = new station(); station.id = id; station.line_id = line_id; station.name = name; return station; }
public int InsertStation(int Id, Station Station) { station station = new station { line_id = Id, name = Station.Name }; _ctx.AddTostations(station); _ctx.SaveChanges(); return station.id; }
/// <summary> /// Deprecated Method for adding a new object to the stations EntitySet. Consider using the .Add method of the associated ObjectSet<T> property instead. /// </summary> public void AddTostations(station station) { base.AddObject("stations", station); }