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 (xPartitions.Count > 0) goto case ControlState.NextPartition; if (relationalPassIndex >= index) { if (relationalPassIndex == numberOfNodes) c = ControlState.Done; else goto case ControlState.Fail; // 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]; xPartitions = GetPartitions(g1, x, xEdgeLabel); yPartitions = GetPartitions(g2, y, xEdgeLabel); //Console.WriteLine("Partitions: " + x + " has " + xPartitions.Count + "elements."); if (PartitionsAreConsistent(xPartitions,yPartitions)) goto case ControlState.NextPartition; else goto case ControlState.Fail; ////c = ControlState.NextRelationalEdge; //goto case ControlState.NextRelationalEdge; } else goto case ControlState.Fail; // c = ControlState.Fail; } else { relationalPassIndex++; relationalEdgeEnumerator = default(IEnumerator<CompoundTerm>); relationalEdgeLabels = default(Set<CompoundTerm>); if (relationalPassIndex == numberOfNodes) c = ControlState.Done; } break; case ControlState.NextPartition: if (xPartitions.Count > 0) // the other constraints have been implied by PartitionsAreConsistent { Pair<IComparable, bool> label = xPartitions.Keys.Choose(0); xtoNodes = xPartitions[label]; xPartitions = xPartitions.RemoveKey(label); ytoNodes = yPartitions[label]; yPartitions = yPartitions.RemoveKey(label); goto case ControlState.ProcessPartition; } else c = ControlState.RelationalPass; break; // It is possible that we have multiple sets of relational edges from a node. The following is done for each set. case ControlState.ProcessPartition: // xEdgeLabel has been set // xtoNodes has been set; // ytoNodes has been set; Node x1, y1; // remove all nodes that have already been matched. (previously implemented as PruneCandidates) Set<Node> xtoNodesTmp = xtoNodes; int count = xtoNodesTmp.Count; for (int i = 0; i < count; i++) { x1 = xtoNodesTmp.Choose(i); if (indexDict.ContainsKey(x1)) { y1 = bijection[indexDict[x1], Y]; if (ytoNodes.Contains(y1)) { xtoNodes = xtoNodes.Remove(x1); ytoNodes = ytoNodes.Remove(y1); } else { goto case ControlState.Fail;// c = ControlState.Fail; //goto EndOfNextRelationalEdge; //break; } } //else if (IsOrderIndependent(x1,g1)) //{ // xtoNodesOrderIndependent = xtoNodesOrderIndependent.Add(x1); // bucketOf[g1.LabelOf(x1)].g2Nodes // xtoNodes = xtoNodes.Remove(x1); // //ytoNodesOrderIndependent = ytoNodesOrderIndependent.Add(x1); //} } if (xtoNodes.Count == 0) { //c = ControlState.RelationalPass; c = ControlState.NextPartition; break; // out of the switch statement }// we do not need to check as all nodes contained in xtoNodes were already contained. //if (IsOrderIndependent(xtoNodes.Choose(0),g1)) //{ // goto case ControlState.ChooseOne; //} //else //{ btp = new BacktrackPointWithPartitions(indexDict, rangeDict, xEdgeLabel, index, relationalPassIndex, relationalEdgeLabels.Remove(xEdgeLabel), xtoNodes, ytoNodes, xPartitions, yPartitions); goto case ControlState.Choose; //} //break; #endregion #region Choose one combination of matching relational edges and add a backtrackpoint if necessary case ControlState.Choose: if (btp == null) // check used to stop when backtracking. { c = ControlState.Fail; break; } c = Choose(); break; #endregion #region Choose one combination of matching relational edges and do not add backtrackpoint case ControlState.ChooseOne: c = ChooseOne(); 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. btp = backtrackStack.Pop(); // Restore program state from the BacktrackPoint. index = btp.index; relationalPassIndex = btp.relationalPassIndex; indexDict = BacktrackPointWithPartitions.getCopy(btp.indexDict); xEdgeLabel = btp.outLabel; rangeDict = BacktrackPointWithPartitions.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(); xPartitions = btp.xPartitions; yPartitions = btp.yPartitions; 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 }
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 = BacktrackPointWithPartitions.getCopy(btp.indexDict); rangeDict = BacktrackPointWithPartitions.getCopy(btp.rangeDict); } else break; } while (true); if (count > 1 && p.Next()) { btp.permuter = p; backtrackStack.Push(btp); } btp = null; return c; }