Distributing AND over OR in a binary tree (Conjunctive Normal Form)

后端 未结 2 1229
忘了有多久
忘了有多久 2021-01-14 01:08

I\'m trying to convert a binary tree e.g.

OR (Implementation of Operator - a specialisation of TreeNode... see below)
|-A (Implementation of TreeNode... see          


        
2条回答
  •  暗喜
    暗喜 (楼主)
    2021-01-14 01:52

    If AND and OR are the only operators you are using, it shouldn't be hard to tranform your tree to CNF. All you have to do is find structures in the form OR(AND(X,Y), Z) or OR(Z, AND(X,Y)) and use the distribution law.

    private static TreeNode distribute(TreeNode n, TreeNode left, TreeNode right) {
      if (n instanceof Or) {
        if (left instanceof And) {
          // distribute right over left AND
          return new And(new Or(left.getLeft(), right), 
                         new Or(left.getRight(), right));
        } else if (right instanceof And) {
          // distribute left over right AND
          return new And(new Or(right.getLeft(), left), 
                         new Or(right.getRight(), left));
        }
      }
    
      // no change
      return treeNode;
    }
    

    This algorithm must be applied to all nodes of your tree until the tree isn't changed anymore. The order in which you apply the algorithm to the nodes doesn't matter. Intuitively, repetitive application of the algorithm will pull up all AND nodes over OR nodes until the tree is in CNF.

    TreeNode root = ....;
    while (true) {
      TreeNode transformedRoot = reconstruct(root);
      if (root.equals(transformedRoot)) {
        break;
      }
      root = transformedRoot;
    }
    // root is now in CNF
    

    Note: Be aware that the CNF transformation may blow up your tree exponential in size. The shown implementation is quite primitive and doesn't use any enhancements to reduce computation time.

提交回复
热议问题