/// <summary> /// Add a match to the isomorphism /// </summary> /// <remarks> /// This is only a proposed match. If it fails, the passed in BacktrackRecord /// will have all the actions taken as a consequence and they can be undone using /// that BacktrackRecord. /// </remarks> /// <param name="mtc">Proposed match</param> /// <param name="btr">BacktrackRecord to record actions into</param> /// <returns>True if match is locally consistent with a full isomorphism</returns> private bool FAddMatchToSolution(Match mtc, BacktrackRecord <TV, TE> btr) { var ivtx1 = mtc.Ivtx1; var ivtx2 = mtc.Ivtx2; // Record the match action in the backtrackRecord btr.SetMatch(mtc.Ivtx1, mtc.Ivtx2, this); // In and Out neighbors of the vertices in the match var lstIn1 = VfGraph1.InNeighbors(ivtx1); var lstIn2 = VfGraph2.InNeighbors(ivtx2); var lstOut1 = VfGraph1.OutNeighbors(ivtx1); var lstOut2 = VfGraph2.OutNeighbors(ivtx2); // Reclassify any neighbors of the added vertices that require it foreach (var ivtx in lstOut1) { if (((int)VfGraph1.GetGroup(ivtx) & (int)(Group.Disconnected | Group.ToMapping)) != 0) { btr.MoveToGroup(1, ivtx, Group.FromMapping, this); } } foreach (var ivtx in lstIn1) { if (((int)VfGraph1.GetGroup(ivtx) & (int)(Group.Disconnected | Group.FromMapping)) != 0) { btr.MoveToGroup(1, ivtx, Group.ToMapping, this); } } foreach (var ivtx in lstOut2) { if (((int)VfGraph2.GetGroup(ivtx) & (int)(Group.Disconnected | Group.ToMapping)) != 0) { btr.MoveToGroup(2, ivtx, Group.FromMapping, this); } } foreach (var ivtx in lstIn2) { if (((int)VfGraph2.GetGroup(ivtx) & (int)(Group.Disconnected | Group.FromMapping)) != 0) { btr.MoveToGroup(2, ivtx, Group.ToMapping, this); } } // If the total degrees into or out of the isomorphism don't match up properly (less for // subgraph isomorphism equal for exact isomorphism) then we can never match properly. if (!FnCompareDegrees(_outDegreeTotal1, _outDegreeTotal2) || !FnCompareDegrees(_inDegreeTotal1, _inDegreeTotal2)) { return(false); } // Also check the vertex counts which is a different check from the total degree above... return(FnCompareDegrees(lstOut1.Count, lstOut2.Count) && FnCompareDegrees(lstIn1.Count, lstIn2.Count)); }
/// <summary> /// Determine if a match is feasible or not /// </summary> /// <remarks> /// This is the heart of the VF isomorphism algorithm. /// </remarks> /// <param name="mtc">Match to check</param> /// <returns>True if feasible, False if not</returns> private bool FFeasible(Match mtc) { var ivtx1 = mtc.Ivtx1; var ivtx2 = mtc.Ivtx2; // Allow the user to override with a context check on the matching. if (_fContextCheck) { var icc1 = VfGraph1.GetAttr(ivtx1) as IContextCheck; var icc2 = VfGraph2.GetAttr(ivtx2) as IContextCheck; if (icc1 != null && icc2 != null) { if (!icc1.FCompatible(icc2)) { // User says they're not compatible regardless of the topology return(false); } } } var lstIn1 = VfGraph1.InNeighbors(ivtx1); var lstIn2 = VfGraph2.InNeighbors(ivtx2); var lstOut1 = VfGraph1.OutNeighbors(ivtx1); var lstOut2 = VfGraph2.OutNeighbors(ivtx2); // Vertex1's In Neighbors in mapping must map to Vertex2's In Neighbors... if (!FLocallyIsomorphic(lstIn1, lstIn2)) { return(false); } // Ditto the above for out neighbors... if (!FLocallyIsomorphic(lstOut1, lstOut2)) { return(false); } // Verify the in, out and new predicate from the paper. This amounts to // checking that the counts for the group classifications in the corresponding // lists below must match. if (!FInOutNew(lstOut1, lstIn1, lstOut2, lstIn2)) { return(false); } return(true); }