/// <summary> /// Create a new sequential route from the parent and include the new vertex <paramref name="v"/>. /// </summary> /// <param name="parentObject"></param> /// <param name="parent">parent route</param> /// <param name="v">additional vertex</param> public SequentialRoute(ShortestPaths parentObject, IRoute parent, int v) { this.parentObject = parentObject; this.v = v; this.parent = parent; }
public EvenCycle(InitialCycles parent, ShortestPaths paths, int[] pathToP, int y, int[] pathToQ) : base(parent, paths, Join(pathToP, y, pathToQ)) { this.p = pathToP[pathToP.Length - 1]; this.q = pathToQ[pathToQ.Length - 1]; this.Y = y; }
public Cycle(InitialCycles parent, ShortestPaths paths, int[] path) { this.parent = parent; this.path = path; this.paths = paths; }
public OddCycle(InitialCycles parent, ShortestPaths paths, int[] pathToY, int[] pathToZ) : base(parent, paths, Join(pathToY, pathToZ)) { this.parent = parent; y = pathToY[pathToY.Length - 1]; z = pathToZ[pathToY.Length - 1]; }
/// <summary> /// Create a new all shortest paths utility for an <see cref="IAtomContainer"/>. /// </summary> /// <param name="container">the molecule of which to find the shortest paths</param> public AllPairsShortestPaths(IAtomContainer container) { // ToAdjList performs null check int[][] adjacent = GraphUtil.ToAdjList(container); int n = container.Atoms.Count; this.container = container; this.shortestPaths = new ShortestPaths[n]; // for each atom construct the ShortestPaths object for (int i = 0; i < n; i++) { shortestPaths[i] = new ShortestPaths(adjacent, container, i); } }
/// <summary> /// Try and find cycles through the triple formed from <paramref name="v"/> and any two /// of it's neighbours. /// </summary> /// <param name="v">a vertex in the graph</param> private void FindTriple(int v) { int[] ws = graph[v]; int deg = ws.Length; // disconnect 'v' from its neighbors 'ws' Disconnect(ws, v); // for every pair of neighbors (u,w) connected to v try and find the // shortest path that doesn't travel through 'v'. If a path can be found // this is the shortest cycle through the three vertices '-u-v-w-' // where u = ws[i] and w = ws[j] for (int i = 0; i < deg; i++) { ShortestPaths sp = new ShortestPaths(graph, null, ws[i]); for (int j = i + 1; j < deg; j++) { // ignore if there is an exciting cycle through the the triple if (canonical && Exists(ws[i], v, ws[j])) { continue; } // if there is a path between u and w, form a cycle by appending // v and storing in the basis if (sp.GetNPathsTo(ws[j]) > 0) { // canonic, use the a shortest path (dependant on vertex // order) - non-canonic, use all possible shortest paths int[][] paths = canonical ? new int[][] { sp.GetPathTo(ws[j]) } : sp.GetPathsTo(ws[j]); foreach (var path in paths) { basis.Add(new Path(Append(path, v))); } } } } Reconnect(ws, v); }
public void Main() { { #region IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); AllPairsShortestPaths apsp = new AllPairsShortestPaths(benzene); for (int i = 0; i < benzene.Atoms.Count; i++) { // only to half the comparisons, we can reverse the // path[] to get all j to i for (int j = i + 1; j < benzene.Atoms.Count; j++) { // reconstruct shortest path from i to j int[] path = apsp.From(i).GetPathTo(j); // reconstruct all shortest paths from i to j int[][] paths = apsp.From(i).GetPathsTo(j); // reconstruct the atoms in the path from i to j IAtom[] atoms = apsp.From(i).GetAtomsTo(j); // access the number of paths from i to j int nPaths = apsp.From(i).GetNPathsTo(j); // access the distance from i to j int distance = apsp.From(i).GetNPathsTo(j); } } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); #region From AllPairsShortestPaths apsp = new AllPairsShortestPaths(benzene); // access explicitly ShortestPaths sp = apsp.From(0); // or chain method calls int[] path = apsp.From(0).GetPathTo(5); #endregion } { IAtomContainer molecule = TestMoleculeFactory.MakeBenzene(); #region From_IAtom AllPairsShortestPaths apsp = new AllPairsShortestPaths(molecule); IAtom start = molecule.Atoms[0]; IAtom end = molecule.Atoms[1]; // access explicitly ShortestPaths sp = apsp.From(start); // or chain the method calls together // first path from start to end atom int[] path = apsp.From(start).GetPathTo(end); // first atom path from start to end atom IAtom[] atoms = apsp.From(start).GetAtomsTo(end); #endregion } }
void Main() { { #region IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; IAtom c4 = benzene.Atoms[3]; // shortest paths from C1 ShortestPaths sp = new ShortestPaths(benzene, c1); // number of paths from C1 to C4 int nPaths = sp.GetNPathsTo(c4); // distance between C1 to C4 int distance = sp.GetDistanceTo(c4); // reconstruct a path to the C4 - determined by storage order int[] path = sp.GetPathTo(c4); // reconstruct all paths int[][] paths = sp.GetPathsTo(c4); int[] org = paths[0]; // paths[0] == path int[] alt = paths[1]; #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetPathTo_int ShortestPaths sp = new ShortestPaths(benzene, c1); // reconstruct first path int[] path = sp.GetPathTo(5); // check there is only one path if (sp.GetNPathsTo(5) == 1) { path = sp.GetPathTo(5); // reconstruct the path } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetPathTo_IAtom ShortestPaths sp = new ShortestPaths(benzene, c1); IAtom end = benzene.Atoms[3]; // reconstruct first path int[] path = sp.GetPathTo(end); // check there is only one path if (sp.GetNPathsTo(end) == 1) { path = sp.GetPathTo(end); // reconstruct the path } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetPathsTo_int int threshold = 20; ShortestPaths sp = new ShortestPaths(benzene, c1); // reconstruct shortest paths int[][] paths = sp.GetPathsTo(5); // only reconstruct shortest paths below a threshold if (sp.GetNPathsTo(5) < threshold) { int[][] path = sp.GetPathsTo(5); // reconstruct shortest paths } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetPathsTo_IAtom int threshold = 20; ShortestPaths sp = new ShortestPaths(benzene, c1); IAtom end = benzene.Atoms[3]; // reconstruct all shortest paths int[][] paths = sp.GetPathsTo(end); // only reconstruct shortest paths below a threshold if (sp.GetNPathsTo(end) < threshold) { paths = sp.GetPathsTo(end); // reconstruct shortest paths } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetAtomsTo_int ShortestPaths sp = new ShortestPaths(benzene, c1); // reconstruct a shortest path IAtom[] path = sp.GetAtomsTo(5); // ensure single shortest path if (sp.GetNPathsTo(5) == 1) { path = sp.GetAtomsTo(5); // reconstruct shortest path } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetAtomsTo_IAtom ShortestPaths sp = new ShortestPaths(benzene, c1); IAtom end = benzene.Atoms[3]; // reconstruct a shortest path IAtom[] path = sp.GetAtomsTo(end); // ensure single shortest path if (sp.GetNPathsTo(end) == 1) { path = sp.GetAtomsTo(end); // reconstruct shortest path } #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetNPathsTo_int ShortestPaths sp = new ShortestPaths(benzene, c1); sp.GetNPathsTo(5); // number of paths sp.GetNPathsTo(-1); // returns 0 - there are no paths #endregion } { IAtomContainer benzene = TestMoleculeFactory.MakeBenzene(); IAtom c1 = benzene.Atoms[0]; #region GetNPathsTo_IAtom ShortestPaths sp = new ShortestPaths(benzene, c1); IAtom end = benzene.Atoms[3]; sp.GetNPathsTo(end); // number of paths sp.GetNPathsTo(null); // returns 0 - there are no paths sp.GetNPathsTo(new Atom("C")); // returns 0 - there are no paths #endregion } { #region GetDistanceTo_int_1 IAtomContainer container = TestMoleculeFactory.MakeBenzene(); IAtom c1 = container.Atoms[0]; ShortestPaths sp = new ShortestPaths(container, c1); // start = 0 int n = container.Atoms.Count; if (sp.GetDistanceTo(5) < n) { // these is a path from 0 to 5 } #endregion } { #region GetDistanceTo_int_2 IAtomContainer container = TestMoleculeFactory.MakeBenzene(); IAtom c1 = container.Atoms[0]; ShortestPaths sp = new ShortestPaths(container, c1); // start = 0 int[] path = sp.GetPathTo(5); int start = path[0]; int end = path[sp.GetDistanceTo(5)]; #endregion } { #region GetDistanceTo_IAtom_1 IAtomContainer container = TestMoleculeFactory.MakeBenzene(); IAtom c1 = container.Atoms[0]; ShortestPaths sp = new ShortestPaths(container, c1); // start atom IAtom end = container.Atoms[3]; int n = container.Atoms.Count; if (sp.GetDistanceTo(end) < n) { // these is a path from start to end } #endregion } { #region GetDistanceTo_IAtom_2 IAtomContainer container = TestMoleculeFactory.MakeBenzene(); IAtom c1 = container.Atoms[0]; ShortestPaths sp = new ShortestPaths(container, c1); // start atom IAtom end = container.Atoms[3]; IAtom[] atoms = sp.GetAtomsTo(end); Console.WriteLine(end == atoms[sp.GetDistanceTo(end)]); // true #endregion } }
/// <summary> /// Compute the initial cycles. The code corresponds to algorithm 1 from /// <token>cdk-cite-Vismara97</token>, where possible the variable names have been kept /// the same. /// </summary> private void Compute() { int n = graph.Length; // the set 'S' contains the pairs of vertices adjacent to 'y' int[] s = new int[n]; int sizeOfS; // order the vertices by degree int[] vertices = new int[n]; for (int v = 0; v < n; v++) { vertices[ordering[v]] = v; } // if the graph is known to be a biconnected component (prepossessing) // and there is at least one vertex with a degree > 2 we can skip all // vertices of degree 2. // // otherwise the smallest possible cycle is {0,1,2} (no parallel edges // or loops) we can therefore don't need to do the first two shortest // paths calculations int first = biconnected && nDeg2Vertices < n ? nDeg2Vertices : 2; for (int i = first; i < n; i++) { int r = vertices[i]; ShortestPaths pathsFromR = new ShortestPaths(graph, null, r, limit / 2, ordering); // we only check the vertices which belong to the set Vr. this // set is vertices reachable from 'r' by only travelling though // vertices smaller then r. In the ShortestPaths API this is // name 'IsPrecedingPathTo'. // // using Vr allows us to prune the number of vertices to check and // discover each cycle exactly once. This is possible as for each // simple cycle there is only one vertex with a maximum ordering. for (int j = 0; j < i; j++) { int y = vertices[j]; if (!pathsFromR.IsPrecedingPathTo(y)) { continue; } // start refilling set 's' by resetting it's size sizeOfS = 0; // z is adjacent to y and belong to Vr foreach (var z in graph[y]) { if (!pathsFromR.IsPrecedingPathTo(z)) { continue; } int distToZ = pathsFromR.GetDistanceTo(z); int distToY = pathsFromR.GetDistanceTo(y); // the distance of the path to z is one less then the // path to y. the vertices are adjacent, therefore z must // also belong to the shortest path from r to y. // // we queue up (in 's') all the vertices adjacent to y for // which this holds and then check these once we've processed // all adjacent vertices // // / ¯ ¯ z1 \ z1 and z2 are added to 's' and // r y - z3 checked later as p and q (see below) // \ _ _ z2 / // if (distToZ + 1 == distToY) { s[sizeOfS++] = z; } // if the distances are equal we could have an odd cycle // but we need to check the paths only intersect at 'r'. // // we check the intersect for cases like this, shortest // cycle here is {p .. y, z .. p} not {r .. y, z .. r} // // / ¯ ¯ y / ¯ ¯ \ / ¯ ¯ y // r - - - p | or r p | // \ _ _ z \ _ _ / \ _ _ z // // if it's the shortest cycle then the intersect is just {r} // // / ¯ ¯ y // r | // \ _ _ z // else if (distToZ == distToY && ordering[z] < ordering[y]) { int[] pathToY = pathsFromR.GetPathTo(y); int[] pathToZ = pathsFromR.GetPathTo(z); if (GetSingletonIntersect(pathToZ, pathToY)) { Cycle cycle = new Cycle.OddCycle(this, pathsFromR, pathToY, pathToZ); Add(cycle); } } } // check each pair vertices adjacent to 'y' for an // even cycle, as with the odd cycle we ensure the intersect // of the paths {r .. p} and {r .. q} is {r}. // // / ¯ ¯ p \ // r y // \ _ _ q / // for (int k = 0; k < sizeOfS; k++) { for (int l = k + 1; l < sizeOfS; l++) { int[] pathToP = pathsFromR.GetPathTo(s[k]); int[] pathToQ = pathsFromR.GetPathTo(s[l]); if (GetSingletonIntersect(pathToP, pathToQ)) { Cycle cycle = new Cycle.EvenCycle(this, pathsFromR, pathToP, y, pathToQ); Add(cycle); } } } } } }