internal static MetroEdge CreateFromTwoEdges(int v, MetroEdge e1, MetroEdge e2) { int s = e1.Source() == v?e1.Target() : e1.Source(); int t = e2.Source() == v?e2.Target() : e2.Source(); if (s < t) { return(CreateFromTwoEdges(v, e1.nodes, e2.nodes)); } else { return(CreateFromTwoEdges(v, e2.nodes, e1.nodes)); } }
internal static MetroEdge CreateFromTwoEdges(int v, List <int> e1, List <int> e2) { List <int> nodes = new List <int>(e1.Count + e2.Count - 1); if (e1[0] != v) { for (int i = 0; i < e1.Count; i++) { nodes.Add(e1[i]); } } else { for (int i = e1.Count - 1; i >= 0; i--) { nodes.Add(e1[i]); } } if (e2[0] == v) { for (int i = 1; i < e2.Count; i++) { nodes.Add(e2[i]); } } else { for (int i = e2.Count - 2; i >= 0; i--) { nodes.Add(e2[i]); } } MetroEdge res = new MetroEdge(); res.nodes = nodes; #if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=289 res.UpdateHashKey(); #endif return(res); }
/// <summary> /// Get the ordering of lines on station u with respect to the edge (u->v) /// </summary> IEnumerable <Metroline> IMetroMapOrderingAlgorithm.GetOrder(Station u, Station v) { MetroEdge me = MetroEdge.CreateFromTwoNodes(u.SerialNumber, v.SerialNumber); List <int> orderedMetrolineListForUv = order[me]; if (u.SerialNumber < v.SerialNumber) { foreach (int MetrolineIndex in orderedMetrolineListForUv) { yield return(MetrolinesGlobal[MetrolineIndex]); } } else { for (int i = orderedMetrolineListForUv.Count - 1; i >= 0; i--) { yield return(MetrolinesGlobal[orderedMetrolineListForUv[i]]); } } }
/// <summary> /// Remove vertex v from the graph. Update graph and paths correspondingly /// </summary> void ProcessNonTerminal(int v) { //oldEdge => sorted PathLists Dictionary <MetroEdge, List <PathList> > newSubLists = RadixSort(v); //update current data foreach (MetroEdge oldEdge in orderedAdjacent[v]) { Debug.Assert(e2p.ContainsKey(oldEdge)); List <PathList> newSubList = newSubLists[oldEdge]; //update e2p[oldEdge] e2p[oldEdge].paths = null; e2p[oldEdge].subLists = newSubList; //update ordered adjacency data UpdateAdjacencyData(OppositeNode(oldEdge, v), oldEdge, newSubList); //update paths and add new edges foreach (PathList pl in newSubList) { MetroEdge newEdge = pl.edge; //we could check the reverse edge before if (e2p.ContainsKey(newEdge)) { continue; } //add e2p for new edge e2p.Add(newEdge, pl); //update paths foreach (PathOnEdge path in pl.paths) { UpdatePath(path, v, newEdge); } } } }
void Initialize() { //non terminals and adjacent nonTerminals = new HashSet <int>(); initialEdges = new HashSet <MetroEdge>(); //non-sorted adjacent edges. will be sorted later Dictionary <int, HashSet <MetroEdge> > adjacent = new Dictionary <int, HashSet <MetroEdge> >(); for (int mi = 0; mi < Metrolines.Count; mi++) { int[] Metroline = Metrolines[mi]; for (int i = 0; i + 1 < Metroline.Length; i++) { MetroEdge me = MetroEdge.CreateFromTwoNodes(Metroline[i], Metroline[i + 1]); if (!initialEdges.Contains(me)) { initialEdges.Add(me); } if (i + 2 < Metroline.Length) { nonTerminals.Add(Metroline[i + 1]); } CollectionUtilities.AddToMap(adjacent, Metroline[i], me); CollectionUtilities.AddToMap(adjacent, Metroline[i + 1], me); } } //order neighbors around each vertex InitAdjacencyData(adjacent); //create e2p and paths... InitPathData(); }
/// <summary> /// Linear sorting of paths passing through vertex v /// </summary> Dictionary <MetroEdge, List <PathList> > RadixSort(int v) { //build a map [old_edge => list_of_paths_on_it]; the relative order of paths is important Dictionary <MetroEdge, List <PathOnEdge> > r = new Dictionary <MetroEdge, List <PathOnEdge> >(); //first index in circular order Dictionary <MetroEdge, int> firstIndex = new Dictionary <MetroEdge, int>(); foreach (MetroEdge oldEdge in orderedAdjacent[v]) { PathList pathList = e2p[oldEdge]; foreach (PathOnEdge path in pathList.paths) { MetroEdge ej = FindNextEdgeOnPath(v, path); CollectionUtilities.AddToMap(r, ej, path); } firstIndex.Add(oldEdge, (r.ContainsKey(oldEdge) ? r[oldEdge].Count : 0)); } //oldEdge => SortedPathLists Dictionary <MetroEdge, List <PathList> > res = new Dictionary <MetroEdge, List <PathList> >(); //build the desired order for each edge foreach (MetroEdge oldEdge in orderedAdjacent[v]) { //r[oldEdge] is the right order! (up to the circleness) List <PathOnEdge> paths = r[oldEdge]; Debug.Assert(paths.Count > 0); List <PathList> subLists = new List <PathList>(); HashSet <PathOnEdge> curPathSet = new HashSet <PathOnEdge>(); for (int j = 0; j < paths.Count; j++) { int i = (j + firstIndex[oldEdge]) % paths.Count; MetroEdge nowEdge = paths[i].node.Value; MetroEdge nextEdge = paths[(i + 1) % paths.Count].node.Value; curPathSet.Add(paths[i]); if (j == paths.Count - 1 || nowEdge != nextEdge) { //process MetroEdge newEdge = MetroEdge.CreateFromTwoEdges(v, oldEdge, nowEdge); PathList pl = new PathList(); pl.edge = newEdge; pl.paths = curPathSet; subLists.Add(pl); //clear curPathSet = new HashSet <PathOnEdge>(); } } if (oldEdge.Source() == v) { subLists.Reverse(); } res.Add(oldEdge, subLists); } return(res); }
/// <summary> /// replace edges (av) and (vb) with edge (ab) on a given path /// </summary> void UpdatePath(PathOnEdge pathOnEdge, int v, MetroEdge newEdge) { LinkedListNode<MetroEdge> f = pathOnEdge.node; Debug.Assert(f.Value.Source() == v || f.Value.Target() == v); int a, b; a = OppositeNode(f.Value, v); if (f.Next != null && (b = OppositeNode(f.Next.Value, v)) != -1) { Debug.Assert((a == newEdge.Source() || a == newEdge.Target())); Debug.Assert((b == newEdge.Source() || b == newEdge.Target())); f.Value = newEdge; f.List.Remove(f.Next); } else if (f.Previous != null && (b = OppositeNode(f.Previous.Value, v)) != -1) { Debug.Assert((a == newEdge.Source() || a == newEdge.Target())); Debug.Assert((b == newEdge.Source() || b == newEdge.Target())); f.Value = newEdge; f.List.Remove(f.Previous); } else throw new NotSupportedException(); }
internal static MetroEdge CreateFromTwoNodes(int u, int v) { MetroEdge res = new MetroEdge(); res.nodes = new List<int>(); res.nodes.Add(Math.Min(u, v)); res.nodes.Add(Math.Max(u, v)); #if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=289 res.UpdateHashKey(); #endif return res; }
/// <summary> /// return an opposite vertex of a given edge /// </summary> int OppositeNode(MetroEdge edge, int v) { if (edge.Source() == v) return edge.Target(); if (edge.Target() == v) return edge.Source(); return -1; }
/// <summary> /// recursively build an order on the edge /// </summary> List<int> RestoreResult(MetroEdge edge) { List<int> res = new List<int>(); PathList pl = e2p[edge]; if (pl.subLists == null) { foreach (PathOnEdge path in pl.paths) res.Add(path.index); } else { foreach (PathList subList in pl.subLists) { List<int> subResult = RestoreResult(subList.edge); if (!(edge.Source() == subList.edge.Source() || edge.Target() == subList.edge.Target())) subResult.Reverse(); res.AddRange(subResult); } } return res; }
/// <summary> /// update adjacencies of node 'a': put new edges instead of oldEdge /// </summary> void UpdateAdjacencyData(int a, MetroEdge oldEdge, List<PathList> newSubList) { //find a (cached) position of oldEdge in order LinkedListNode<MetroEdge> node = adjacencyIndex[new Tuple<int, MetroEdge>(a, oldEdge)]; Debug.Assert(node.Value == oldEdge); LinkedListNode<MetroEdge> inode = node; foreach (PathList pl in newSubList) { MetroEdge newEdge = pl.edge; if (oldEdge.Source() == a) node = node.List.AddAfter(node, newEdge); else node = node.List.AddBefore(node, newEdge); adjacencyIndex.Add(new Tuple<int, MetroEdge>(a, newEdge), node); } adjacencyIndex.Remove(new Tuple<int, MetroEdge>(a, oldEdge)); inode.List.Remove(inode); }
internal static MetroEdge CreateFromTwoEdges(int v, List<int> e1, List<int> e2) { List<int> nodes = new List<int>(e1.Count + e2.Count - 1); if (e1[0] != v) { for (int i = 0; i < e1.Count; i++) nodes.Add(e1[i]); } else { for (int i = e1.Count - 1; i >= 0; i--) nodes.Add(e1[i]); } if (e2[0] == v) { for (int i = 1; i < e2.Count; i++) nodes.Add(e2[i]); } else { for (int i = e2.Count - 2; i >= 0; i--) nodes.Add(e2[i]); } MetroEdge res = new MetroEdge(); res.nodes = nodes; #if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=289 res.UpdateHashKey(); #endif return res; }
internal static MetroEdge CreateFromTwoEdges(int v, MetroEdge e1, MetroEdge e2) { int s = e1.Source() == v ? e1.Target() : e1.Source(); int t = e2.Source() == v ? e2.Target() : e2.Source(); if (s < t) return CreateFromTwoEdges(v, e1.nodes, e2.nodes); else return CreateFromTwoEdges(v, e2.nodes, e1.nodes); }