private ControlState Choose() { ControlState c = ControlState.Fail; Permuter p = btp.permuter; int count = xtoNodes.Count; do { for (int i = 0; i < count; i++) { c = ExtendForOnlyFunctionalEdges(xtoNodes.Choose(i), ytoNodes.Choose(p[i])); if (c == ControlState.Fail) break; } if (c == ControlState.Fail && p.Next()) { index = btp.index; indexDict = BacktrackPoint.getCopy(btp.indexDict); rangeDict = BacktrackPoint.getCopy(btp.rangeDict); } else break; } while (true); if (count > 1 && p.Next()) { btp.permuter = p; backtrackStack.Push(btp); } btp = null; return c; }
protected override Result <char, Match2> Parse(ArrayConsList <char> consList, int afterLastMatchIndex) { BacktrackPoint lastBacktrackPoint = null; StackFrame callStack = new GroupStackFrame(null, Pattern); var partialResult = new Result <char, int>(0, consList); while (callStack != null) { if (callStack is QuantifierStackFrame) { QuantifierStackFrame quantStackFrame = (QuantifierStackFrame)callStack; if (quantStackFrame.IsPositionChanged(partialResult.Tree)) { lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, quantStackFrame.SecondAlternative(partialResult.Tree), partialResult); callStack = quantStackFrame.FirstAlternative(partialResult.Tree); } else { callStack = quantStackFrame.Parent; } } else { BasePattern currentPattern = callStack.RemainingChildren.Head; if (currentPattern.MinCharLength > partialResult.Rest.Length) { partialResult = null; } else { callStack = ((GroupStackFrame)callStack).MoveToNextChild(); switch (currentPattern.Type) { case PatternType.Group: callStack = new GroupStackFrame(callStack, ((GroupPattern)currentPattern).Patterns); break; case PatternType.Quantifier: var quant = (QuantifierPattern)currentPattern; quant.AssertCanonicalForm(); if (quant.MinOccurrences == quant.MaxOccurrences) { callStack = new GroupStackFrame(callStack, new RepeaterConsList <BasePattern>(quant.ChildPattern, quant.MinOccurrences)); } else { callStack = new QuantifierStackFrame(callStack, quant); } break; case PatternType.Alternation: var alternatives = ((AlternationPattern)currentPattern).Alternatives; foreach (var alt in alternatives.Skip(1).Reverse()) { lastBacktrackPoint = new BacktrackPoint(lastBacktrackPoint, new GroupStackFrame(callStack, alt), partialResult); } callStack = new GroupStackFrame(callStack, alternatives.First()); break; case PatternType.Anchor: if (!doesAnchorMatch(((AnchorPattern)currentPattern).AnchorType, (ArrayConsList <char>)partialResult.Rest, afterLastMatchIndex)) { partialResult = null; } break; case PatternType.Char: partialResult = parseChar(partialResult, ((CharPattern)currentPattern).IsMatch); break; default: throw new ApplicationException( string.Format("BacktrackingMatcher: unrecognized pattern type ({0}).", currentPattern.GetType().Name)); } } if (partialResult == null) { if (lastBacktrackPoint != null) { callStack = lastBacktrackPoint.CallStack; partialResult = lastBacktrackPoint.PartialResult; lastBacktrackPoint = lastBacktrackPoint.Previous; } else { return(new Result <char, Match2>(Match2.Empty, consList)); } } } callStack = unwindEmptyFrames(callStack); } return(new Result <char, Match2>( new Match2(consList.ArrayIndex, partialResult.Tree, consList.AsEnumerable().Take(partialResult.Tree).AsString()), partialResult.Rest)); }
internal Map<Node, Node> ComputeIsomorphism() { // We start with a functional pass. ControlState c = ControlState.InitialFunctionalPass; while (true) { switch (c) { # region Find all reachable functional matches of current active nodes x and y. case ControlState.InitialFunctionalPass: c = ExtendForOnlyFunctionalEdges(x, y); break; # endregion #region Find all relational matches after one or more functional pass. case ControlState.RelationalPass: if (relationalPassIndex >= index) { if (relationalPassIndex == numberOfNodes) c = ControlState.Done; else c = ControlState.Fail; break; } x = bijection[relationalPassIndex, X]; y = bijection[relationalPassIndex, Y]; xData = g1.vertexRecords[x]; yData = g2.vertexRecords[y]; if (relationalEdgeEnumerator == default(IEnumerator<CompoundTerm>)) { relationalEdgeLabels = Set<CompoundTerm>.EmptySet; foreach (Pair<CompoundTerm, Set<Node>> pair in xData.unorderedOutgoingEdges) { relationalEdgeLabels = relationalEdgeLabels.Add(pair.First); } relationalEdgeEnumerator = relationalEdgeLabels.GetEnumerator(); } if (relationalEdgeEnumerator.MoveNext()) { xEdgeLabel = relationalEdgeEnumerator.Current; xtoNodes = xData.unorderedOutgoingEdges[xEdgeLabel]; if (yData.unorderedOutgoingEdges.ContainsKey(xEdgeLabel)) // Perhaps this check can be assumed true for all graphs? { ytoNodes = yData.unorderedOutgoingEdges[xEdgeLabel]; c = ControlState.NextRelationalEdge; } else c = ControlState.Fail; } else { relationalPassIndex++; relationalEdgeEnumerator = default(IEnumerator<CompoundTerm>); relationalEdgeLabels = default(Set<CompoundTerm>); if (relationalPassIndex == numberOfNodes) c = ControlState.Done; } break; // It is possible that we have multiple sets of relational edges from a node. The following is done for each set. case ControlState.NextRelationalEdge: // xEdgeLabel has been set // xtoNodes has been set; // ytoNodes has been set; Node x1, y1; // remove all nodes that have already been matched. for (int i = 0; i < xtoNodes.Count; i++) { x1 = xtoNodes.Choose(i); if (indexDict.ContainsKey(x1)) { y1 = bijection[indexDict[x1], Y]; if (ytoNodes.Contains(y1)) { xtoNodes = xtoNodes.Remove(x1); ytoNodes = ytoNodes.Remove(y1); } else { c = ControlState.Fail; goto EndOfNextRelationalEdge; } } } if (xtoNodes.Count == 0) { c = ControlState.RelationalPass; break; // out of the switch statement }// we do not need to check as all nodes contained in xtoNodes were already contained. //isoExt = ExtendIsomorphism4(backtrackBuckets, backtrackStack, isoExt, xtoNodes.Choose(), ytoNodes.Choose()); btp = new BacktrackPoint(indexDict, rangeDict, xEdgeLabel, index, relationalPassIndex, relationalEdgeLabels.Remove(xEdgeLabel), xtoNodes, ytoNodes); c = ControlState.Choose; //goto case ControlState.Choose; EndOfNextRelationalEdge: break; #endregion #region Choose one combination of matching relational edges case ControlState.Choose: if (btp == null) // check used to stop when backtracking. { c = ControlState.Fail; break; } c = Choose(); break; #endregion # region Process a backtrack request. case ControlState.Fail: if (backtrackStack.Count == 0) return null; else { // Reset environment to topmost backtrackpoint and continue // with the relevant Choose from where we left off last time. btp = backtrackStack.Pop(); // Restore program state from the BacktrackPoint. index = btp.index; relationalPassIndex = btp.relationalPassIndex; indexDict = BacktrackPoint.getCopy(btp.indexDict); xEdgeLabel = btp.outLabel; rangeDict = BacktrackPoint.getCopy(btp.rangeDict); x = bijection[relationalPassIndex, X]; y = bijection[relationalPassIndex, Y]; xData = g1.vertexRecords[x]; yData = g2.vertexRecords[y]; xtoNodes = btp.xtoNodes; ytoNodes = btp.ytoNodes; relationalEdgeLabels = btp.relationalEdgeLabels; relationalEdgeEnumerator = btp.relationalEdgeLabels.GetEnumerator(); c = ControlState.Choose; } break; # endregion case ControlState.Done: goto Success; default: break; } } #region Prepare result map and return. Success: Map<Node, Node> iso = Map<Node, Node>.EmptyMap; for (int i = 0; i < numberOfNodes; i++) { iso = iso.Add(bijection[i, X], bijection[i, Y]); } return iso; #endregion }