コード例 #1
0
 /**
  * Converts multi-level ands and ors into single level ones.
  * @param root the expression to flatten
  * @return the flattened expression, which will always be root with
  *   potentially modified children.
  */
 internal static ExpressionTree flatten(ExpressionTree root)
 {
     if (root.getChildren() != null)
     {
         // iterate through the index, so that if we add more children,
         // they don't get re-visited
         for (int i = 0; i < root.getChildren().Count; ++i)
         {
             ExpressionTree child = flatten(root.getChildren()[i]);
             // do we need to flatten?
             if (child.getOperator() == root.getOperator() &&
                 child.getOperator() != ExpressionTree.Operator.NOT)
             {
                 bool first = true;
                 foreach (ExpressionTree grandkid in child.getChildren())
                 {
                     // for the first grandkid replace the original parent
                     if (first)
                     {
                         first = false;
                         root.getChildren()[i] = grandkid;
                     }
                     else
                     {
                         root.getChildren().Insert(++i, grandkid);
                     }
                 }
             }
             else
             {
                 root.getChildren()[i] = child;
             }
         }
         // if we have a singleton AND or OR, just return the child
         if ((root.getOperator() == ExpressionTree.Operator.OR ||
              root.getOperator() == ExpressionTree.Operator.AND) &&
             root.getChildren().Count == 1)
         {
             return(root.getChildren()[0]);
         }
     }
     return(root);
 }
コード例 #2
0
 /**
  * Convert an expression so that the top level operator is AND with OR
  * operators under it. This routine assumes that all of the NOT operators
  * have been pushed to the leaves via pushdDownNot.
  * @param root the expression
  * @return the normalized expression
  */
 internal static ExpressionTree convertToCNF(ExpressionTree root)
 {
     if (root.getChildren() != null)
     {
         // convert all of the children to CNF
         int size = root.getChildren().Count;
         for (int i = 0; i < size; ++i)
         {
             root.getChildren()[i] = convertToCNF(root.getChildren()[i]);
         }
         if (root.getOperator() == ExpressionTree.Operator.OR)
         {
             // a list of leaves that weren't under AND expressions
             List <ExpressionTree> nonAndList = new List <ExpressionTree>();
             // a list of AND expressions that we need to distribute
             List <ExpressionTree> andList = new List <ExpressionTree>();
             foreach (ExpressionTree child in root.getChildren())
             {
                 if (child.getOperator() == ExpressionTree.Operator.AND)
                 {
                     andList.Add(child);
                 }
                 else if (child.getOperator() == ExpressionTree.Operator.OR)
                 {
                     // pull apart the kids of the OR expression
                     foreach (ExpressionTree grandkid in child.getChildren())
                     {
                         nonAndList.Add(grandkid);
                     }
                 }
                 else
                 {
                     nonAndList.Add(child);
                 }
             }
             if (andList.Count != 0)
             {
                 if (checkCombinationsThreshold(andList))
                 {
                     root = new ExpressionTree(ExpressionTree.Operator.AND);
                     generateAllCombinations(root.getChildren(), andList, nonAndList);
                 }
                 else
                 {
                     root = new ExpressionTree(TruthValue.YES_NO_NULL);
                 }
             }
         }
     }
     return(root);
 }
コード例 #3
0
            /**
             * Push the negations all the way to just before the leaves. Also remove
             * double negatives.
             * @param root the expression to normalize
             * @return the normalized expression, which may share some or all of the
             * nodes of the original expression.
             */
            internal static ExpressionTree pushDownNot(ExpressionTree root)
            {
                if (root.getOperator() == ExpressionTree.Operator.NOT)
                {
                    ExpressionTree child = root.getChildren()[0];
                    switch (child.getOperator())
                    {
                    case ExpressionTree.Operator.NOT:
                        return(pushDownNot(child.getChildren()[0]));

                    case ExpressionTree.Operator.CONSTANT:
                        return(new ExpressionTree(child.getConstant().Value.not()));

                    case ExpressionTree.Operator.AND:
                        root = new ExpressionTree(ExpressionTree.Operator.OR);
                        foreach (ExpressionTree kid in child.getChildren())
                        {
                            root.getChildren().Add(pushDownNot(new
                                                               ExpressionTree(ExpressionTree.Operator.NOT, kid)));
                        }
                        break;

                    case ExpressionTree.Operator.OR:
                        root = new ExpressionTree(ExpressionTree.Operator.AND);
                        foreach (ExpressionTree kid in child.getChildren())
                        {
                            root.getChildren().Add(pushDownNot(new ExpressionTree
                                                                   (ExpressionTree.Operator.NOT, kid)));
                        }
                        break;

                    // for leaf, we don't do anything
                    default:
                        break;
                    }
                }
                else if (root.getChildren() != null)
                {
                    // iterate through children and push down not for each one
                    for (int i = 0; i < root.getChildren().Count; ++i)
                    {
                        root.getChildren()[i] = pushDownNot(root.getChildren()[i]);
                    }
                }
                return(root);
            }
コード例 #4
0
 /**
  * Rewrite expression tree to update the leaves.
  * @param root the root of the tree to fix
  * @param leafReorder a map from old leaf ids to new leaf ids
  * @return the fixed root
  */
 static ExpressionTree rewriteLeaves(ExpressionTree root,
                                     int[] leafReorder)
 {
     if (root.getOperator() == ExpressionTree.Operator.LEAF)
     {
         return(new ExpressionTree(leafReorder[root.getLeaf()]));
     }
     else if (root.getChildren() != null)
     {
         List <ExpressionTree> children = root.getChildren();
         for (int i = 0; i < children.Count; ++i)
         {
             children[i] = rewriteLeaves(children[i], leafReorder);
         }
     }
     return(root);
 }
コード例 #5
0
            public SearchArgument.Builder end()
            {
                ExpressionTree current = currentTree.Pop();

                if (current.getChildren().Count == 0)
                {
                    throw new ArgumentException("Can't create expression " + root +
                                                " with no children.");
                }
                if (current.getOperator() == ExpressionTree.Operator.NOT &&
                    current.getChildren().Count != 1)
                {
                    throw new ArgumentException("Can't create not expression " +
                                                current + " with more than 1 child.");
                }
                return(this);
            }
コード例 #6
0
 /**
  * Recursively explore the tree to find the leaves that are still reachable
  * after optimizations.
  * @param tree the node to check next
  * @param next the next available leaf id
  * @param leafReorder
  * @return the next available leaf id
  */
 static int compactLeaves(ExpressionTree tree, int next, int[] leafReorder)
 {
     if (tree.getOperator() == ExpressionTree.Operator.LEAF)
     {
         int oldLeaf = tree.getLeaf();
         if (leafReorder[oldLeaf] == -1)
         {
             leafReorder[oldLeaf] = next++;
         }
     }
     else if (tree.getChildren() != null)
     {
         foreach (ExpressionTree child in tree.getChildren())
         {
             next = compactLeaves(child, next, leafReorder);
         }
     }
     return(next);
 }
コード例 #7
0
            /**
             * Remove MAYBE values from the expression. If they are in an AND operator,
             * they are dropped. If they are in an OR operator, they kill their parent.
             * This assumes that pushDownNot has already been called.
             * @param expr The expression to clean up
             * @return The cleaned up expression
             */
            internal static ExpressionTree foldMaybe(ExpressionTree expr)
            {
                if (expr.getChildren() != null)
                {
                    for (int i = 0; i < expr.getChildren().Count; ++i)
                    {
                        ExpressionTree child = foldMaybe(expr.getChildren()[i]);
                        if (child.getConstant() == TruthValue.YES_NO_NULL)
                        {
                            switch (expr.getOperator())
                            {
                            case ExpressionTree.Operator.AND:
                                expr.getChildren().RemoveAt(i);
                                i -= 1;
                                break;

                            case ExpressionTree.Operator.OR:
                                // a maybe will kill the or condition
                                return(child);

                            default:
                                throw new InvalidOperationException("Got a maybe as child of " +
                                                                    expr);
                            }
                        }
                        else
                        {
                            expr.getChildren()[i] = child;
                        }
                    }
                    if (expr.getChildren().Count == 0)
                    {
                        return(new ExpressionTree(TruthValue.YES_NO_NULL));
                    }
                }
                return(expr);
            }
コード例 #8
0
 /**
  * Rewrite expression tree to update the leaves.
  * @param root the root of the tree to fix
  * @param leafReorder a map from old leaf ids to new leaf ids
  * @return the fixed root
  */
 static ExpressionTree rewriteLeaves(ExpressionTree root,
                                     int[] leafReorder)
 {
     if (root.getOperator() == ExpressionTree.Operator.LEAF)
     {
         return new ExpressionTree(leafReorder[root.getLeaf()]);
     }
     else if (root.getChildren() != null)
     {
         List<ExpressionTree> children = root.getChildren();
         for (int i = 0; i < children.Count; ++i)
         {
             children[i] = rewriteLeaves(children[i], leafReorder);
         }
     }
     return root;
 }
コード例 #9
0
 /**
  * Recursively explore the tree to find the leaves that are still reachable
  * after optimizations.
  * @param tree the node to check next
  * @param next the next available leaf id
  * @param leafReorder
  * @return the next available leaf id
  */
 static int compactLeaves(ExpressionTree tree, int next, int[] leafReorder)
 {
     if (tree.getOperator() == ExpressionTree.Operator.LEAF)
     {
         int oldLeaf = tree.getLeaf();
         if (leafReorder[oldLeaf] == -1)
         {
             leafReorder[oldLeaf] = next++;
         }
     }
     else if (tree.getChildren() != null)
     {
         foreach (ExpressionTree child in tree.getChildren())
         {
             next = compactLeaves(child, next, leafReorder);
         }
     }
     return next;
 }
コード例 #10
0
 /**
  * Push the negations all the way to just before the leaves. Also remove
  * double negatives.
  * @param root the expression to normalize
  * @return the normalized expression, which may share some or all of the
  * nodes of the original expression.
  */
 internal static ExpressionTree pushDownNot(ExpressionTree root)
 {
     if (root.getOperator() == ExpressionTree.Operator.NOT)
     {
         ExpressionTree child = root.getChildren()[0];
         switch (child.getOperator())
         {
             case ExpressionTree.Operator.NOT:
                 return pushDownNot(child.getChildren()[0]);
             case ExpressionTree.Operator.CONSTANT:
                 return new ExpressionTree(child.getConstant().Value.not());
             case ExpressionTree.Operator.AND:
                 root = new ExpressionTree(ExpressionTree.Operator.OR);
                 foreach (ExpressionTree kid in child.getChildren())
                 {
                     root.getChildren().Add(pushDownNot(new
                         ExpressionTree(ExpressionTree.Operator.NOT, kid)));
                 }
                 break;
             case ExpressionTree.Operator.OR:
                 root = new ExpressionTree(ExpressionTree.Operator.AND);
                 foreach (ExpressionTree kid in child.getChildren())
                 {
                     root.getChildren().Add(pushDownNot(new ExpressionTree
                         (ExpressionTree.Operator.NOT, kid)));
                 }
                 break;
             // for leaf, we don't do anything
             default:
                 break;
         }
     }
     else if (root.getChildren() != null)
     {
         // iterate through children and push down not for each one
         for (int i = 0; i < root.getChildren().Count; ++i)
         {
             root.getChildren()[i] = pushDownNot(root.getChildren()[i]);
         }
     }
     return root;
 }
コード例 #11
0
 /**
  * Remove MAYBE values from the expression. If they are in an AND operator,
  * they are dropped. If they are in an OR operator, they kill their parent.
  * This assumes that pushDownNot has already been called.
  * @param expr The expression to clean up
  * @return The cleaned up expression
  */
 internal static ExpressionTree foldMaybe(ExpressionTree expr)
 {
     if (expr.getChildren() != null)
     {
         for (int i = 0; i < expr.getChildren().Count; ++i)
         {
             ExpressionTree child = foldMaybe(expr.getChildren()[i]);
             if (child.getConstant() == TruthValue.YES_NO_NULL)
             {
                 switch (expr.getOperator())
                 {
                     case ExpressionTree.Operator.AND:
                         expr.getChildren().RemoveAt(i);
                         i -= 1;
                         break;
                     case ExpressionTree.Operator.OR:
                         // a maybe will kill the or condition
                         return child;
                     default:
                         throw new InvalidOperationException("Got a maybe as child of " +
                             expr);
                 }
             }
             else
             {
                 expr.getChildren()[i] = child;
             }
         }
         if (expr.getChildren().Count == 0)
         {
             return new ExpressionTree(TruthValue.YES_NO_NULL);
         }
     }
     return expr;
 }
コード例 #12
0
 /**
  * Converts multi-level ands and ors into single level ones.
  * @param root the expression to flatten
  * @return the flattened expression, which will always be root with
  *   potentially modified children.
  */
 internal static ExpressionTree flatten(ExpressionTree root)
 {
     if (root.getChildren() != null)
     {
         // iterate through the index, so that if we add more children,
         // they don't get re-visited
         for (int i = 0; i < root.getChildren().Count; ++i)
         {
             ExpressionTree child = flatten(root.getChildren()[i]);
             // do we need to flatten?
             if (child.getOperator() == root.getOperator() &&
                 child.getOperator() != ExpressionTree.Operator.NOT)
             {
                 bool first = true;
                 foreach (ExpressionTree grandkid in child.getChildren())
                 {
                     // for the first grandkid replace the original parent
                     if (first)
                     {
                         first = false;
                         root.getChildren()[i] = grandkid;
                     }
                     else
                     {
                         root.getChildren().Insert(++i, grandkid);
                     }
                 }
             }
             else
             {
                 root.getChildren()[i] = child;
             }
         }
         // if we have a singleton AND or OR, just return the child
         if ((root.getOperator() == ExpressionTree.Operator.OR ||
             root.getOperator() == ExpressionTree.Operator.AND) &&
             root.getChildren().Count == 1)
         {
             return root.getChildren()[0];
         }
     }
     return root;
 }
コード例 #13
0
 /**
  * Convert an expression so that the top level operator is AND with OR
  * operators under it. This routine assumes that all of the NOT operators
  * have been pushed to the leaves via pushdDownNot.
  * @param root the expression
  * @return the normalized expression
  */
 internal static ExpressionTree convertToCNF(ExpressionTree root)
 {
     if (root.getChildren() != null)
     {
         // convert all of the children to CNF
         int size = root.getChildren().Count;
         for (int i = 0; i < size; ++i)
         {
             root.getChildren()[i] = convertToCNF(root.getChildren()[i]);
         }
         if (root.getOperator() == ExpressionTree.Operator.OR)
         {
             // a list of leaves that weren't under AND expressions
             List<ExpressionTree> nonAndList = new List<ExpressionTree>();
             // a list of AND expressions that we need to distribute
             List<ExpressionTree> andList = new List<ExpressionTree>();
             foreach (ExpressionTree child in root.getChildren())
             {
                 if (child.getOperator() == ExpressionTree.Operator.AND)
                 {
                     andList.Add(child);
                 }
                 else if (child.getOperator() == ExpressionTree.Operator.OR)
                 {
                     // pull apart the kids of the OR expression
                     foreach (ExpressionTree grandkid in child.getChildren())
                     {
                         nonAndList.Add(grandkid);
                     }
                 }
                 else
                 {
                     nonAndList.Add(child);
                 }
             }
             if (andList.Count != 0)
             {
                 if (checkCombinationsThreshold(andList))
                 {
                     root = new ExpressionTree(ExpressionTree.Operator.AND);
                     generateAllCombinations(root.getChildren(), andList, nonAndList);
                 }
                 else
                 {
                     root = new ExpressionTree(TruthValue.YES_NO_NULL);
                 }
             }
         }
     }
     return root;
 }
コード例 #14
0
 private static void assertNoSharedNodes(ExpressionTree tree, HashSet<ExpressionTree> seen)
 {
     if (seen.Contains(tree) &&
         tree.getOperator() != ExpressionTree.Operator.LEAF)
     {
         Assert.True(false, "repeated node in expression " + tree);
     }
     seen.Add(tree);
     if (tree.getChildren() != null)
     {
         foreach (ExpressionTree child in tree.getChildren())
         {
             assertNoSharedNodes(child, seen);
         }
     }
 }