예제 #1
0
 public static void EnsureIsAnalyzed(LGSPGraph this_)
 {
     if (this_.statistics.vstructs == null || this_.changesCounterAtLastAnalyze != this_.ChangesCounter)
     {
         this_.AnalyzeGraph();
     }
 }
예제 #2
0
        // Version to be used by IsIsomorph(IDictionary<IGraph, SetValueType> graphsToCheckAgainst),
        // which is comparing a candidate against an entire set.
        // Not changing the metadata of this, matching each that inside this, not for normal use!
        private bool IsIsomorph(LGSPGraph this_, LGSPGraph that, bool includingAttributes, int threadId)
        {
            ++that.matchingState.numChecks;

            if (((LGSPGraph)that).matchingState == null)
            {
                ((LGSPGraph)that).matchingState = new GraphMatchingState((LGSPGraph)that);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Check " + this_.Name + " == " + that.Name + " on thread " + threadId);
            writer.Flush();
#endif

            // compare number of elements per type
            if (!AreNumberOfElementsEqual(this_, that))
            {
                return(false);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Undecided after type counts");
            writer.Flush();
#endif

            // ensure that is analyzed, for this it was ensured by our caller
            if (that.statistics.vstructs == null || that.changesCounterAtLastAnalyze != that.ChangesCounter)
            {
                lock (that)
                {
                    if (that.statistics.vstructs == null || that.changesCounterAtLastAnalyze != that.ChangesCounter)
                    {
                        that.AnalyzeGraph();
                    }
                }
            }

            // compare analyze statistics
            if (!AreVstructsEqual(this_, that))
            {
                return(false);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Undecided after vstructs comparison");
            writer.Flush();
#endif

            // invalidate outdated interpretation plans and compiled matchers of that
            // not needed for this cause we always use the matchers of that, matching inside this
            if (that.matchingState.interpretationPlan != null && that.matchingState.changesCounterAtInterpretationPlanBuilding != that.ChangesCounter)
            {
                lock (that)
                {
                    if (that.matchingState.interpretationPlan != null && that.matchingState.changesCounterAtInterpretationPlanBuilding != that.ChangesCounter)
                    {
                        that.matchingState.interpretationPlan = null;
                        that.matchingState.patternGraph       = null;
                        lock (GraphMatchingState.compilationLock)
                        {
                            GraphMatchingState.candidatesForCompilation.Remove(that);
                        }
                        that.matchingState.compiledMatcher = null;
                        that.matchingState.numMatchings    = 0;
                        that.matchingState.numChecks       = 0;
                    }
                }
            }

            // they were the same? then we must try to match that in this
            // if a compiled matcher is existing we use the compiled matcher
            // if an interpretation plan is existing we use the interpretation plan for matching
            // if none is existing, then we build an interpretation plan for that
            // and directly use it for matching thereafter
            // executing an interpretation plan or a compiled matcher is sufficient for isomorphy because
            // - element numbers are the same
            // - we match only exact types
            bool result;
            if (that.matchingState.compiledMatcher != null)
            {
                // lock(this_) was employed by our caller
                result = that.matchingState.compiledMatcher.IsIsomorph(that.matchingState.patternGraph, this_, includingAttributes, threadId);
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using compiled interpretation plan of that " + that.matchingState.compiledMatcher.Name);
#endif
            }
            else if (that.matchingState.interpretationPlan != null)
            {
                // lock(this_) was employed by our caller
                result = that.matchingState.interpretationPlan.Execute(this_, includingAttributes, null, threadId);
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using interpretation plan of that " + ((InterpretationPlanStart)that.matchingState.interpretationPlan).ComparisonMatcherName);
#endif
            }
            else
            {
                // we build the interpretation plan for that
                BuildInterpretationPlan(that);
                // lock(this_) was employed by our caller
                result = that.matchingState.interpretationPlan.Execute(this_, includingAttributes, null, threadId);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Result of matching: " + (result ? "Isomorph" : "Different"));
            writer.Flush();
#endif

            // update the statistics, and depending on the statistics we
            // - add candidats to the set of the matchers to be compiled
            // - it's on our caller to trigger a compiler run
            ++that.matchingState.numMatchings;
            if (that.matchingState.numMatchings == GraphMatchingState.MATCHES_NEEDED_TO_BECOME_A_CANDIDATE_FOR_COMPILATION)
            {
                lock (GraphMatchingState.compilationLock)
                {
                    GraphMatchingState.candidatesForCompilation.Add(that);
                }
            }

            return(result);
        }
예제 #3
0
        public bool IsIsomorph(LGSPGraph this_, LGSPGraph that, bool includingAttributes)
        {
            ++this_.matchingState.numChecks;
            ++that.matchingState.numChecks;

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Check " + this_.Name + " == " + that.Name);
            writer.Flush();
#endif

            if (this_ == that)
            {
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("this == that, identical graphs are isomorph");
                writer.Flush();
#endif
                return(true);
            }

            // compare number of elements per type
            if (!AreNumberOfElementsEqual(this_, that))
            {
                return(false);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Undecided after type counts");
            writer.Flush();
#endif

            // ensure graphs are analyzed
            if (this_.statistics.vstructs == null || this_.changesCounterAtLastAnalyze != this_.ChangesCounter)
            {
                lock (this_)
                {
                    if (this_.statistics.vstructs == null || this_.changesCounterAtLastAnalyze != this_.ChangesCounter)
                    {
                        this_.AnalyzeGraph();
                    }
                }
            }
            if (that.statistics.vstructs == null || that.changesCounterAtLastAnalyze != that.ChangesCounter)
            {
                lock (that)
                {
                    if (that.statistics.vstructs == null || that.changesCounterAtLastAnalyze != that.ChangesCounter)
                    {
                        that.AnalyzeGraph();
                    }
                }
            }

            // compare analyze statistics
            if (!AreVstructsEqual(this_, that))
            {
                return(false);
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Undecided after vstructs comparison");
            writer.Flush();
#endif

            // invalidate outdated interpretation plans and compiled matchers
            if (this_.matchingState.interpretationPlan != null && this_.matchingState.changesCounterAtInterpretationPlanBuilding != this_.ChangesCounter)
            {
                lock (this_)
                {
                    if (this_.matchingState.interpretationPlan != null && this_.matchingState.changesCounterAtInterpretationPlanBuilding != this_.ChangesCounter)
                    {
                        this_.matchingState.interpretationPlan = null;
                        this_.matchingState.patternGraph       = null;
                        lock (GraphMatchingState.compilationLock)
                        {
                            GraphMatchingState.candidatesForCompilation.Remove(this_);
                        }
                        this_.matchingState.compiledMatcher = null;
                        this_.matchingState.numMatchings    = 0;
                        this_.matchingState.numChecks       = 0;
                    }
                }
            }
            if (that.matchingState.interpretationPlan != null && that.matchingState.changesCounterAtInterpretationPlanBuilding != that.ChangesCounter)
            {
                lock (that)
                {
                    if (that.matchingState.interpretationPlan != null && that.matchingState.changesCounterAtInterpretationPlanBuilding != that.ChangesCounter)
                    {
                        that.matchingState.interpretationPlan = null;
                        that.matchingState.patternGraph       = null;
                        lock (GraphMatchingState.compilationLock)
                        {
                            GraphMatchingState.candidatesForCompilation.Remove(that);
                        }
                        that.matchingState.compiledMatcher = null;
                        that.matchingState.numMatchings    = 0;
                        that.matchingState.numChecks       = 0;
                    }
                }
            }

            // they were the same? then we must try to match this in that, or that in this
            // if a compiled matcher is existing we use the compiled matcher
            // if an interpretation plan is existing we use the interpretation plan for matching
            // if none is existing for neither of the graphs, then we build an interpretation plan
            // for the older graph and directly use it for matching thereafter
            // executing an interpretation plan or a compiled matcher is sufficient for isomorphy because
            // - element numbers are the same
            // - we match only exact types
            bool result;
            bool matchedWithThis;
            if (this_.matchingState.compiledMatcher != null)
            {
                lock (that)
                {
                    result = this_.matchingState.compiledMatcher.IsIsomorph(this_.matchingState.patternGraph, that, includingAttributes);
                }
                matchedWithThis = true;
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using compiled interpretation plan of this " + this_.matchingState.compiledMatcher.Name);
#endif
            }
            else if (that.matchingState.compiledMatcher != null)
            {
                lock (this_)
                {
                    result = that.matchingState.compiledMatcher.IsIsomorph(that.matchingState.patternGraph, this_, includingAttributes);
                }
                matchedWithThis = false;
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using compiled interpretation plan of that " + that.matchingState.compiledMatcher.Name);
#endif
            }
            else if (this_.matchingState.interpretationPlan != null)
            {
                lock (that)
                {
                    result = this_.matchingState.interpretationPlan.Execute(that, includingAttributes, null);
                }
                matchedWithThis = true;
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using interpretation plan of this " + ((InterpretationPlanStart)this_.matchingState.interpretationPlan).ComparisonMatcherName);
#endif
            }
            else if (that.matchingState.interpretationPlan != null)
            {
                lock (this_)
                {
                    result = that.matchingState.interpretationPlan.Execute(this_, includingAttributes, null);
                }
                matchedWithThis = false;
#if LOG_ISOMORPHY_CHECKING
                writer.WriteLine("Using interpretation plan of that " + ((InterpretationPlanStart)that.matchingState.interpretationPlan).ComparisonMatcherName);
#endif
            }
            else
            {
                // we build the interpretation plan for the older graph,
                // assuming it will survive while the younger one is the candidate for purging
                if (this_.GraphId < that.GraphId)
                {
                    BuildInterpretationPlan(this_);
                    lock (that)
                    {
                        result = this_.matchingState.interpretationPlan.Execute(that, includingAttributes, null);
                    }
                    matchedWithThis = true;
                }
                else
                {
                    BuildInterpretationPlan(that);
                    lock (this_)
                    {
                        result = that.matchingState.interpretationPlan.Execute(this_, includingAttributes, null);
                    }
                    matchedWithThis = false;
                }
            }

#if LOG_ISOMORPHY_CHECKING
            writer.WriteLine("Result of matching: " + (result ? "Isomorph" : "Different"));
            writer.Flush();
#endif

            // update the statistics, and depending on the statistics we
            // - add candidats to the set of the matchers to be compiled
            // - trigger a compiler run
            if (matchedWithThis)
            {
                ++this_.matchingState.numMatchings;
                if (this_.matchingState.numMatchings == GraphMatchingState.MATCHES_NEEDED_TO_BECOME_A_CANDIDATE_FOR_COMPILATION)
                {
                    lock (GraphMatchingState.compilationLock)
                    {
                        GraphMatchingState.candidatesForCompilation.Add(this_);
                    }
                }
            }
            else
            {
                ++that.matchingState.numMatchings;
                if (that.matchingState.numMatchings == GraphMatchingState.MATCHES_NEEDED_TO_BECOME_A_CANDIDATE_FOR_COMPILATION)
                {
                    lock (GraphMatchingState.compilationLock)
                    {
                        GraphMatchingState.candidatesForCompilation.Add(that);
                    }
                }
            }

            CompileComparisonMatchersAsNeeded();

            return(result);
        }