Algorithm to Calculate Density of Boolean Function

爱⌒轻易说出口 提交于 2020-01-06 19:09:08

问题


I'm trying to write a program that requires the calculation of a specific value dealing with Boolean functions. Given a single-output Boolean function f, given by a cover F, let's say I define the density of the function as the fraction of all input vectors where the function has the value 1.

For example, suppose I pass in the given function f(a, b, c) which is defined by cover F = ab'+c'. The function has 5 ON-set minterms, and 8 total minterms, hence its density is d(f) = 5/8 = 0.625. It should be noted that cube ab’ covers 2 minterms and cube c’ covers 4 minterms, but one of those minterms is covered by both cubes.

Can anyone think of a good algorithm to handle this? I have a strong suspicion that it will be best expressed recursively, but I'm having trouble pinning down something efficient.


回答1:


The bad news: there's no hope for an algorithm that is always fast.

Namely, this problem:

Given a boolean formula in a conjunctive normal form (product of sums), decide if there is an assignment of the free variables such that the formula yields true

is NP-complete. This means that if you find a polynomial-time algorithm that solves it, you can solve some of the world's hardest problems (knapsack, travelling salesman problem, hamiltonian cycle problem just to name a few) in polynomial time as well. No-one really expects that to be possible.

This problem is, in fact, equivalent to this problem:

Given a boolean formula in a disjunctive normal form (sum of products), decide if its density is 100%


The good news:

The input size is likely to be very small. At three variables, you don't really care for speed. At thirty input variables, you still are more likely to run out of memory (using some algorithms) than to run unbearably long.

Algorithm #1: O(2^v*i) time, few lines of code, v= number of variables; i=length of the input.

  • if any clause is inconsistent (A & !A), drop it.
  • sort the clauses by size, largest (fewest variables) first.
  • for every minterm in the universal set
    • for every clause in the input
      • for every literal in the term
        • if the minterm is not covered by the literal, continue to the next clause
      • The minterm is covered by the clause:
      • Count the minterm as covered, and continue to the next minterm.
    • The minterm is not covered by any literal; continue to the next minterm.
  • let density = [#covered terms]/[#terms]

If you want to run faster, you will need to hope for a good input. You can try to use binary decision diagrams (BDDs) to encode the current set of encoded minterms, and try to update the binary decision diagram as you add clauses from the input.

A binary decision diagram is a rooted directed acyclic graph such that every node is either a decision node (test a single variable, then take either the false branch or the true branch) or a leaf node (either true or false). For example, XOR can be expressed with this binary decision diagram:

     |
     A
    / \
   /   \
  B     B
 / \   / \
0   1 1   0

Algorithm #2 (Lazy-expanding BDD, more complicated but potentially faster for large amount of variables):

  • if any clause is inconsistent (A & !A), drop it.
  • sort the clauses by size, largest (fewest variables) first.
  • start with an empty BDD (root = false)
  • for every clause
    • update the BDD: start on the root.
    • for every variable:
      • if the clause has no more literals, replace the current node with true (only at the edge along which you came)
        • if the immediate sibling is also true, replace the common parent with true, and repeat this test for the new node.
      • if the current node is true
        • continue to the next clause or recursion branch, or join the sibling thread.
      • if the variable is in the clause and in the current BDD node,
        • descend to the child that intersects the clause.
      • if the variable is in the clause but not in the current BDD node.
        • create a new BDD node
        • set both children to the current node
        • replace the current node with the new node (only at the edge along which you came)
        • descend to the child that intersects the clause.
      • if the variable is in the BDD but not in the clause
        • descend to both children in turn recursively. Alternatively, descend to both children in parallel in separate threads.
      • if the variable is neither in the BDD nor in the clause
        • do nothing.
  • let density = 0/(2^variables) (the denominator signifies the suggested scale for integer computation)
  • every leaf node is either true or false. For every path in the BDD
    • if the leaf node is true
      • let length be the number of non-leaf nodes encountered along the path.
      • add 1/(2^length) to density.


来源:https://stackoverflow.com/questions/15100676/algorithm-to-calculate-density-of-boolean-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!