Example #1
0
            /// <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;
            }
Example #2
0
 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;
 }
Example #3
0
            public Cycle(InitialCycles parent, ShortestPaths paths, int[] path)
            {
                this.parent = parent;

                this.path  = path;
                this.paths = paths;
            }
Example #4
0
                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];
                }
Example #5
0
        /// <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);
            }
        }
Example #6
0
        /// <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
            }
        }
Example #9
0
        /// <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);
                            }
                        }
                    }
                }
            }
        }