private void ValidateRootIsDisjunction(LogicalTreeNode root)
 {
     if (root.Type != NodeType.Disjunction)
     {
         throw new ArgumentException("При применении трансформации удаления лишних скобок для дизъюнкции, корень должен быть дизъюнкцией", "root");
     }
 }
 private void ValidateRootIsConjunction(LogicalTreeNode root)
 {
     if (root.Type != NodeType.Conjunction)
     {
         throw new ArgumentException("При применении трансформации раскрытия дистрибутивности, корень должен быть конъюнкцией", "root");
     }
 }
示例#3
0
 private void UpdateHeightUsingChild(LogicalTreeNode node)
 {
     if (Height < node.Height + 1)
     {
         Height = node.Height + 1;
     }
 }
        public void Transform(LogicalTreeNode root)
        {
            ValidateRootIsConjunction(root);

            // Необходимо выполнить предварительную энумерацию (.ToArray()),
            // т.к. далее модифицируется коллекция, по которой происходит выборка
            var disjunctions = root.Children.Where(x => x.Type == NodeType.Disjunction).ToArray();
            var conjunctions = root.Children.Where(x => x.Type == NodeType.Conjunction).ToArray();
            var leafs        = root.Children.Where(x => x.Type == NodeType.Leaf).ToArray();

            var conjunctionsDescendants  = conjunctions.SelectMany(x => x.Children).ToArray();
            var disjunctionDescendants   = disjunctions.Select(x => x.Children).ToArray();
            var disjunctionsCombinations = SequencesCombinator <LogicalTreeNode> .Combinate(disjunctionDescendants);

            // Результат состоит из дизъюнкции элементарных конъюнкций
            // Каждая конъюнкция состоит из всех листовых переменных, непосредственных детей корня
            // Всех детей конъюнкций, где конъюнкция - непосредственный ребенок корня
            // Одного из вариантов комбинации детей дизъюнкций, где дизъюнкция - непосредственный ребенок корня
            root.Type = NodeType.Disjunction;
            root.ClearChildren();

            foreach (var disjunctionsCombination in disjunctionsCombinations)
            {
                // Сплащиваем конъюнкции, которые могли содержаться в комбинации детей дизъюнкций.
                var disjunctionLeafs = FlatInnerConjunctions(disjunctionsCombination);

                var conjunction = new LogicalTreeNode(NodeType.Conjunction);

                conjunction.AddNodes(disjunctionLeafs);
                conjunction.AddNodes(conjunctionsDescendants);
                conjunction.AddNodes(leafs);

                root.AddNode(conjunction);
            }
        }
示例#5
0
        public void RemoveNode(LogicalTreeNode node)
        {
            _children.Remove(node);
            node.Parent = null;

            UpdateHeight();
        }
示例#6
0
        public void AddNode(LogicalTreeNode node)
        {
            _children.Add(node);

            node.SetParent(this);

            UpdateHeightUsingChild(node);
        }
        public void Transform(LogicalTreeNode root)
        {
            // Вначале избавляемся от всех отрицаний в нелистьях
            // Потом редуцируем дерево по высоте к КНФ форме
            PullNegationsDown(root);

            ReductHeight(root);
        }
        /// <summary>
        /// Возвращает все вершины дерева, включая корень
        /// </summary>
        /// <param name="root">Корень дерева, для которого вычисляется список его вершин</param>
        /// <returns>Список вершин дерева</returns>
        private IEnumerable <LogicalTreeNode> GetNodes(LogicalTreeNode root)
        {
            var result = new List <LogicalTreeNode>();

            result.Add(root);

            foreach (var node in root.Children)
            {
                result.AddRange(GetNodes(node));
            }

            return(result);
        }
        private void ReductHeight(LogicalTreeNode root)
        {
            // Т.к. высота какого-либо элемента дерева не может увеличиться,
            // и высота вершины после редукции никогда не превышает 3 (высота КНФ)
            // то проходя от самого "низкого" элемента к самому "высокому",
            // гарантированно в конце получим правильный результат.
            var heightOrderedNodes = GetNodesOrderedByHeight(root).ToArray();

            foreach (var node in heightOrderedNodes)
            {
                _treeHeightReductionTransformation.Transform(node);
            }
        }
        public void Transform(LogicalTreeNode root)
        {
            ValidateRootIsConjunction(root);

            // Необходимо выполнить предварительную энумерацию (.ToArray()),
            // т.к. далее модифицируется коллекция, по которой происходит выборка
            var conjunctions = root.Children.Where(x => x.Type == NodeType.Conjunction).ToArray();
            var leafs        = root.Children.Where(x => x.Type == NodeType.Leaf).ToArray();

            root.ClearChildren();

            root.AddNodes(conjunctions.SelectMany(x => x.Children).ToList());
            root.AddNodes(leafs);
        }
示例#11
0
        private LogicalTreeNode Clone()
        {
            var clone = new LogicalTreeNode(Type);

            clone.Name    = Name;
            clone.Negated = Negated;

            foreach (var node in _children)
            {
                clone.AddNode(node.Clone());
            }

            return(clone);
        }
示例#12
0
        private void SetParent(LogicalTreeNode newParent)
        {
            DelinkFromParent();

            Parent = newParent;
        }
        /// <summary>
        /// Возвращает список вершин дерева, упорядоченные по высоте
        /// </summary>
        /// <param name="root">Корень дерева, для которого вычисляется упорядоченный список его вершин</param>
        /// <returns>Список вершин дерева, упорядоченные по высоте</returns>
        private IEnumerable <LogicalTreeNode> GetNodesOrderedByHeight(LogicalTreeNode root)
        {
            var nodes = GetNodes(root);

            return(nodes.OrderBy(x => x.Height));
        }
 private void PullNegationsDown(LogicalTreeNode root)
 {
     _deMorganNegationPuller.Transform(root);
 }