예제 #1
0
        bool FMatchRecursive()
        {
            Match           mchCur;
            CandidateFinder cf;

            if (FCompleteMatch())
            {
                return(true);
            }

            cf = new CandidateFinder(this);
            while ((mchCur = cf.NextCandidateMatch()) != null)
            {
                if (FFeasible(mchCur))
                {
                    BacktrackRecord btr = new BacktrackRecord();
                    AddMatchToSolution(mchCur, btr);
                    if (FMatchRecursive())
                    {
                        _fSuccessfulMatch = true;
                        return(true);
                    }
                    btr.Backtrack(this);
                }
            }
            return(false);
        }
예제 #2
0
 public void TestConstructor()
 {
     var vfs = VfsTest();
     var cf = new CandidateFinder(vfs);
     var mch = cf.NextCandidateMatch();
     Assert.AreEqual(0, mch.Ivtx1);
     Assert.AreEqual(0, mch.Ivtx2);
     mch = cf.NextCandidateMatch();
     Assert.AreEqual(1, mch.Ivtx1);
     Assert.AreEqual(0, mch.Ivtx2);
 }
예제 #3
0
            public void TestConstructor()
            {
                VfState         vfs = VfsTest();
                CandidateFinder cf  = new CandidateFinder(vfs);
                Match           mch = cf.NextCandidateMatch();

                Assert.AreEqual(0, mch.Inod1);
                Assert.AreEqual(0, mch.Inod2);
                mch = cf.NextCandidateMatch();
                Assert.AreEqual(1, mch.Inod1);
                Assert.AreEqual(0, mch.Inod2);
            }
예제 #4
0
        // Find an isomorphism between a subgraph of _vfgr1 and the entirity of _vfgr2...
        public bool FMatch()
        {
            if (!FCompatibleDegrees())
            {
                return(false);
            }

            Stack <CandidateFinder> stkcf = new Stack <CandidateFinder>();
            Stack <BacktrackRecord> stkbr = new Stack <BacktrackRecord>();

            Match           mchCur;
            CandidateFinder cf;
            BacktrackRecord btr;
            bool            fPopOut = false;

#if GATHERSTATS
            int cSearchGuesses = 0;
            int cBackTracks    = 0;
            int cInfeasible    = 0;
#endif

            if (_fMatched)
            {
                return(false);
            }
            _fMatched = true;

            // Since the subgraph of subgraph isomorphism is in _vfgr1, it must have at
            // least as many nodes as _vfgr2...
            if (!fnCmp(_vfgr1.NodeCount, _vfgr2.NodeCount))
            {
                return(false);
            }

            if (FCompleteMatch())
            {
                _fSuccessfulMatch = true;
                return(true);
            }

            // Non-recursive implementation of a formerly recursive function
            while (true)
            {
                if (fPopOut)
                {
                    if (stkcf.Count <= 0)
                    {
                        break;                                                          // Out of the top level while loop and return false
                    }
                    cf  = stkcf.Pop();
                    btr = stkbr.Pop();
#if GATHERSTATS
                    cBackTracks++;
#endif
                    btr.Backtrack(this);
                }
                else
                {
                    cf  = new CandidateFinder(this);
                    btr = new BacktrackRecord();
                }
                fPopOut = true;
                while ((mchCur = cf.NextCandidateMatch()) != null)
                {
                    if (FFeasible(mchCur))
                    {
                        if (FAddMatchToSolution(mchCur, btr) && FCompleteMatch())
                        {
                            _fSuccessfulMatch = true;
#if GATHERSTATS
                            Console.WriteLine("cBackTracks = {0}", cBackTracks);
                            Console.WriteLine("cSearchGuesses = {0}", cSearchGuesses);
                            Console.WriteLine("cInfeasible = {0}", cInfeasible);
#endif
                            if (_fFindAll)
                            {
                                // Record this match and simulate a failure...
                                RecordCurrentMatch();
                                stkcf.Push(cf);
                                stkbr.Push(btr);
                                break;
                            }
                            else
                            {
                                return(true);
                            }
                        }
#if GATHERSTATS
                        // Made a bad guess, count it up...
                        cSearchGuesses++;
#endif
                        stkcf.Push(cf);
                        stkbr.Push(btr);
                        fPopOut = false;
                        break;                                                          // Out of the inner level while loop to "call" into the outer loop
                    }
#if GATHERSTATS
                    else
                    {
                        cInfeasible++;
                    }
#endif
                }
            }
#if GATHERSTATS
            Console.WriteLine("cBackTracks = {0}", cBackTracks);
            Console.WriteLine("cSearchGuesses = {0}", cSearchGuesses);
            Console.WriteLine("cInfeasible = {0}", cInfeasible);
#endif
            return(_fSuccessfulMatch);
        }
예제 #5
0
        public IEnumerable <FullMapping> Matches()
        {
            // Check for an empty second graph
            if (_ldr2.VertexCount == 0)
            {
                // If the second is empty, check for a successful "match"
                if (FnCompareDegrees(_ldr1.VertexCount, 0))
                {
                    // Return empty mapping - successful, but nothing to map to
                    yield return(new FullMapping(new Dictionary <int, int>(), new Dictionary <int, int>()));
                }
                yield break;
            }

            // Quick easy check to make the degrees compatible.
            if (!FCompatibleDegrees())
            {
                yield break;
            }

            var stkcf = new Stack <CandidateFinder <TV, TE> >();
            var stkbr = new Stack <BacktrackRecord <TV, TE> >();

            var fBacktrack = false;

#if GATHERSTATS
            int cSearchGuesses = 0;
            int cBackTracks    = 0;
            int cInfeasible    = 0;
#endif

            // The general structure here is:
            // While (true)
            //		if (backtracking)
            //			if there are no graph2 vertices to backtrack to, we can't find any other isomorphisms so return
            //			pop off the previous graph2 vertex to continue it's match
            //			perform backtrack actions
            //		else
            //			pick a new graph2 vertex to try to match
            //		while (there are still potential graph1 vertices to match our current graph2 vertex)
            //			if (the selected graph1 vertex is a feasible match to our current graph2 vertex)
            //				Add the match (and record it if we later need to backtrack)
            //				if (we've got a complete isomorphism)
            //					yield the isomorphism
            //					Push our current graph2 vertex so it will be popped off during backtracking
            //					break the inner loop to trigger artificial backtrack
            //				push the current graph2 vertex search and continue in outer loop with no backtracking
            //
            while (true)
            {
                CandidateFinder <TV, TE> cf;
                BacktrackRecord <TV, TE> btr;

                // If it's time to backtrack...
                if (fBacktrack)
                {
                    // If there are no more candidates left, we've failed to find an isomorphism
                    if (stkcf.Count <= 0)
                    {
                        break;                         // Out of the top level while loop and end enumeration
                    }

                    // Pop off the previous candidate finder so we can continue in our list
                    cf = stkcf.Pop();

#if GATHERSTATS
                    cBackTracks++;
#endif
                    // Get the backtrack record...
                    btr = stkbr.Pop();

                    // ...and undo any actions that need to be backtracked
                    btr.Backtrack(this);
                }
                else
                {
                    // Moving forward - new candidate finder

                    // Each new candidate finder we produce here picks a vertex in graph2 and works
                    // at matching it to a vertex in graph1 until there are no possibile graph1 vertices left.
                    // at that point we know that the current isomorphism is impossible since no
                    // graph1 vertex can be matched to the selected graph2 vertex.  At that point we
                    // will pop the candidate finder, backtrack any changes we've made and move to
                    // the next graph1 candidate in the previous candidate finder on the stack.
                    cf = new CandidateFinder <TV, TE>(this);

                    // Start a new backtracking record in case we fail to find a match for our
                    // selected graph2 vertex.
                    btr = new BacktrackRecord <TV, TE>();
                }

                // Assume failure
                fBacktrack = true;
                Match mchCur;

                // For all the graph1 vertices that could potentially match up with the current
                // candidateFinder's graph2 vertex...
                while ((mchCur = cf.NextCandidateMatch()) != null)
                {
                    // If the candidate match is feasible
                    if (FFeasible(mchCur))
                    {
                        // Add it to the isomorphism so far and see if we've completed the isomorphism
                        if (FAddMatchToSolution(mchCur, btr) && FCompleteMatch())
                        {
                            // Yay!  Isomorphism found!
#if GATHERSTATS
                            Console.WriteLine("cBackTracks = {0}", cBackTracks);
                            Console.WriteLine("cSearchGuesses = {0}", cSearchGuesses);
                            Console.WriteLine("cInfeasible = {0}", cInfeasible);
#endif
                            // Record this match
                            Dictionary <int, int> vidToVid1;
                            Dictionary <int, int> vidToVid2;

                            // Change the ivertex to ivertex VfGraph mapping in _vfGraphIvtx1To2Isomorphism
                            // to an vid to vid mapping in the original graph...
                            VfGraphVfGraphIvtxToGraphGraphVid(
                                _vfGraphIvtx1To2Isomorphism,
                                _degreeSortedToOriginal1,
                                _degreeSortedToOriginal2,
                                out vidToVid1,
                                out vidToVid2);
                            yield return(new FullMapping(vidToVid1, vidToVid2));

                            // This will cause a backtrack where this candidateFinder
                            // will be popped off the stack and we'll continue
                            // with this graph2 vertex looking for the next solution.
                            stkcf.Push(cf);
                            stkbr.Push(btr);
                            break;
                        }
#if GATHERSTATS
                        // Made a bad guess, count it up...
                        cSearchGuesses++;
#endif
                        // Dang!  No full isomorphism yet but our choices so far aren't infeasible.
                        // Push candidate finder/backtrack record and break out of the inner loop which will
                        // cause us to pick another candidate finder/graph2 vertex to be mapped.
                        stkcf.Push(cf);
                        stkbr.Push(btr);
                        fBacktrack = false;
                        break;                         // Out of the inner level while loop to "call" into the outer loop
                    }
#if GATHERSTATS
                    else
                    {
                        cInfeasible++;
                    }
#endif
                }
            }
#if GATHERSTATS
            Console.WriteLine("cBackTracks = {0}", cBackTracks);
            Console.WriteLine("cSearchGuesses = {0}", cSearchGuesses);
            Console.WriteLine("cInfeasible = {0}", cInfeasible);
#endif
        }