/// <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);
        }
        /// <summary>
        /// Ensure that degrees of vertices are compatible
        /// </summary>
        /// <returns>True if compatible, False if not</returns>
        private bool FCompatibleDegrees()
        {
            if (!FnCompareDegrees(VfGraph1.VertexCount, VfGraph2.VertexCount))
            {
                return(false);
            }

            // Since we've sorted the vertices by degree, we can do a quick compare on the degree sequence
            // on a vertex by vertex basis...
            for (var iVertex = 0; iVertex < VfGraph2.VertexCount; iVertex++)
            {
                if (!FnCompareDegrees(VfGraph1.TotalDegree(iVertex), VfGraph2.TotalDegree(iVertex)))
                {
                    return(false);
                }
            }
            return(true);
        }