/// <summary>
        /// Split on a specific node. This gets a type and splits it into
        /// two subtypes.
        /// </summary>
        /// <param name="nodesInType"></param>
        /// <param name="typeParents"></param>
        /// <param name="node"></param>
        /// <returns></returns>
        public static SublatticeModification <T> SplitOn <T>(HashSet <LatticeNode <T> > nodesInType, HashSet <LatticeNode <T> > typeParents, LatticeNode <T> node)
        {
            //Debug.Assert(typeParents.Except(nodesInType).Count() == 0);

            HashSet <LatticeNode <T> > transitiveClosuresForNewType = AbstractColoredLattice <T> .GetTransitiveChildrenClosure(nodesInType, node);

            var modification = new SublatticeModification <T>()
            {
                Type   = ModificationType.Split,
                Data   = node,
                Before = new List <HashSet <LatticeNode <T> > >()
                {
                    nodesInType
                },
                BeforeParent = new List <HashSet <LatticeNode <T> > >()
                {
                    typeParents
                },
                After = new List <HashSet <LatticeNode <T> > >()
                {
                    new HashSet <LatticeNode <T> >(nodesInType.Except(transitiveClosuresForNewType)),
                    new HashSet <LatticeNode <T> >(transitiveClosuresForNewType)
                },
                AfterParents = new List <HashSet <LatticeNode <T> > >()
                {
                    new HashSet <LatticeNode <T> >(typeParents.Except(transitiveClosuresForNewType)),
                    new HashSet <LatticeNode <T> >(transitiveClosuresForNewType.Where(n => typeParents.Contains(n) || n.Parents.Any(p => !transitiveClosuresForNewType.Contains(p))).Concat(new List <LatticeNode <T> >()
                    {
                        node
                    }))
                }
            };

            // Does this split a cycle?
            var parentCluster   = modification.After[0];
            var childrenCluster = modification.After[1];

            Debug.Assert(parentCluster.Intersect(childrenCluster).Count() == 0);
            Debug.Assert(modification.AfterParents[0].Except(parentCluster).Count() == 0);
            Debug.Assert(modification.AfterParents[1].Except(childrenCluster).Count() == 0);

            var parClosure = AbstractColoredLattice <T> .GetTransitiveParentClosure(parentCluster);

            parClosure.IntersectWith(childrenCluster);
            if (parClosure.Count != 0)
            {
                return(null);                       // We are trying to split a circle
            }
            return(modification);
        }
Example #2
0
        protected static void ApplyModification(List <HashSet <LatticeNode <TData> > > currentColoring, List <HashSet <LatticeNode <TData> > > currentColoringParents, SublatticeModification <TData> modification)
        {
            for (int i = 0; i < modification.After.Count; i++)
            {
                Debug.Assert(modification.AfterParents[i].Except(modification.After[i]).Count() == 0);
            }
            var removed = true;

            foreach (var beforeType in modification.Before)
            {
                removed &= currentColoring.Remove(beforeType);
            }
            foreach (var beforeParents in modification.BeforeParent)
            {
                removed &= currentColoringParents.Remove(beforeParents);
            }
            Debug.Assert(removed);

            currentColoring.AddRange(modification.After);
            currentColoringParents.AddRange(modification.AfterParents);
        }