Esempio n. 1
0
        /// <summary>
        /// Since this clause is full of disjunctions, might as well flatten them
        /// </summary>
        private void Flatten()
        {
            bool anyChanges = true;

            while (anyChanges)
            {
                anyChanges = false;
                BlockIterator.TerminableForEach(RootBlock, (currentBlock) =>
                {
                    if (currentBlock.ContentType == ContentType.Nested)
                    {
                        Block next = currentBlock.NextBlock,
                        current    = currentBlock.Isolate(true).GetContent() as Block;
                        anyChanges = true;

                        next.ExtendFront(current);
                        if (currentBlock.Equals(RootBlock))
                        {
                            RootBlock = current;
                        }

                        return(false);
                    }

                    return(true);
                });
            }
        }
Esempio n. 2
0
        public HornClauses(List <Block> clauses) : this()
        {
            foreach (var clause in clauses)
            {
                if (clause.NextBlock == clause && clause.PreviousBlock == clause)
                {
                    Facts.Add(clause.GetContent(true).ToString());
                    continue;
                }

                // safe against nested symbols inside clause or multiple clauses pointing at 1 symbol
                var symbol    = clause.PreviousBlock.GetContent(true).ToString();
                var unvisited = new List <Block> {
                    clause
                };
                if (!Implications.ContainsKey(symbol))
                {
                    Implications.Add(symbol, new List <List <string> >());
                }

                // if a horn clause is pointing at the same symbol as some other horn clauses,
                // add current clause's requirements to a new list instead of combining them together
                Implications[symbol].Add(new List <string>());

                // recursion using while loop, flatten down all nested symbols (if any)
                // as well as pushing clause's requirements for future reference
                while (unvisited.Count != 0)
                {
                    BlockIterator.TerminableForEach(unvisited[0], (block) =>
                    {
                        switch (block.ContentType)
                        {
                        case ContentType.Logic:
                            if ((block.GetContent() as PropositionalLogic).IsImplication)
                            {
                                return(false);
                            }
                            break;

                        case ContentType.Normal:
                            Implications[symbol].Last().Add(block.GetContent(true).ToString());
                            break;

                        case ContentType.Nested:
                            unvisited.Add(block.GetContent() as Block);
                            break;
                        }
                        return(true);
                    });

                    unvisited.RemoveAt(0);
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Remove any symbols inside clause, guarantee to also remove its trailing connective.
        /// <para>Eg: a||b||c into b||c if removing a or a||c if removing b</para>
        /// </summary>
        /// <param name="clauses"></param>
        /// <param name="symbol"></param>
        /// <returns></returns>
        private List <Block> RemoveSymbol(List <Block> clauses, Block symbol, bool newList = true)
        {
            // must specify a fresh copy on demand here because blocks are also objects
            // that have memory addresses
            var result = !newList ? clauses :
                         clauses.Select((b) => ClauseParser.Parse(b.ToString())).ToList();

            string rawSymbol = symbol.GetContent(true).ToString();

            for (int i = 0; i < result.Count; ++i)
            {
                var root = result[i];
                if (root == null)
                {
                    continue;
                }

                // remove either a symbol or the whole rootBlock
                BlockIterator.TerminableForEach(root, (currentBlock) =>
                {
                    if (currentBlock.GetContent(true).ToString() == rawSymbol)
                    {
                        // remove the whole clause if it contains the exact content of the symbol
                        // passed through in this method
                        // (true in a disjunctive clause means true as a whole)
                        if (currentBlock.IsNegated == symbol.IsNegated)
                        {
                            result.RemoveAt(i--);
                            return(false);
                        }

                        // remove only this symbol if it does not have the same negation
                        // because when this happens, the symbol within stored list turns out to be false
                        // which is removable in a sea of disjunctions
                        bool isEOL          = currentBlock.NextBlock == root;
                        var unaffectedBlock = isEOL ?
                                              currentBlock.PreviousBlock.PreviousBlock :
                                              currentBlock.NextBlock.NextBlock;

                        // block list contains only 1 block
                        if (unaffectedBlock == currentBlock)
                        {
                            currentBlock.Isolate(true);
                            result[i] = null;
                            return(false);
                        }

                        if (isEOL)
                        {
                            // a||b into b if remove a
                            unaffectedBlock.RemoveBack(true);
                            unaffectedBlock.RemoveBack(true);
                        }
                        else
                        {
                            // a||b||c into a||c if remove b
                            unaffectedBlock.RemoveFront(true);
                            unaffectedBlock.RemoveFront(true);
                        }

                        if (root == currentBlock)
                        {
                            result[i] = unaffectedBlock;
                            return(false);
                        }
                    }
                    return(true);
                });
            }

            return(result);
        }