public class CNFConverter
extends Object
This class handles the conversion from a normal com.javaoffers.thrid.sqlparse.expression tree into
the CNF form.
Here is the definition of CNF form:
https://en.wikipedia.org/wiki/Conjunctive_normal_form
Basically it will follow these steps:
To help understanding, I will generate an example:
Here is the original tree:
OR
/ \
OR NOT
/ \ |
NOT H AND
| / \
NOT G OR
| / \
F H NOT
|
OR
/ \
AND L
/ \
( ) ( )
| |
J K
1. rebuild the tree by replacing the "and" and "or" operators
(which are binary) into their counterparts node that could hold
multiple elements. Also, leave out the parenthesis node between the
conditional operators to make the tree uniform.
After the transform, the result should be like this:
OR(M)
/ \
OR(M) NOT
/ \ |
NOT H AND(M)
| / \
NOT G OR(M)
| / \
F H NOT
|
OR(M)
/ \
AND(M) L
/ \
J K
2. push the not operators into the bottom of the com.javaoffers.thrid.sqlparse.expression. That
means the not operator will be the root of the com.javaoffers.thrid.sqlparse.expression tree
where no "and" or "or" exists. Be sure use the De Morgan's law
and double not law.
How to use De Morgan law:
For example, here is the original com.javaoffers.thrid.sqlparse.expression tree:
NOT
|
AND(M)
/ \
G H
After we use the De Morgan law, the result should be like this:
OR(M)
/ \
NOT NOT
| |
G H
After the transform, the result should be like this:
OR(M)
/ \
OR(M) OR(M)
/ \ / \
F H NOT AND(M)
| / \
G NOT OR(M)
| / \
H AND(M) L
/ \
J K
3. gather all the adjacent "and" or "or" operator together.
After doing that, the com.javaoffers.thrid.sqlparse.expression tree will be presented as:
all the and com.javaoffers.thrid.sqlparse.expression will be in either odd or even levels,
this will be the same for the or operator.
After the transform, the com.javaoffers.thrid.sqlparse.expression tree should be like this:
OR(M)
/ / \ \
F H NOT AND(M)
| / \
G NOT OR(M)
| / \
H AND(M) L
/ \
J K
4. push the and operator upwards until the root is an and
operator and all the children are or operators with multiple
components. At this time we get the result: an com.javaoffers.thrid.sqlparse.expression in CNF form.
How do we push and up? Use distribution law!
For example, here is the way to push the and up and merge them.
OR
/ \
AND L
/ \
J K
In the normal form, it could be: (J AND K) OR L.
If we apply the distribution law, we will get the result like this:
(J OR L) AND (K OR L), the tree form of this should be like:
AND
/ \
OR OR
/ \ / \
J L K L
So after we push the AND at the deepest level up and merge it with the
existing add, we get this result.
OR(M)
/ / \ \
F H NOT AND(M)
| / | \
G NOT OR(M) OR(M)
| / \ / \
H J L K L
Now let us push the and up and we will get the result like this:
AND(M)
/ | \
OR(M) OR(M) OR(M)
/ / \ \ / / | \ \ / / | \ \
F H NOT NOT F H NOT J L F H NOT K L
| | | |
G H G G
5. The last step, convert the Multiple Expression back to the binary
form. Note the final tree shall be left-inclined.
The final com.javaoffers.thrid.sqlparse.expression tree shall be like this:
AND
/ \
AND ( )
/ \ |
( ) ( ) part1
| |
OR part2
/ \
OR NOT
/ \ |
OR NOT H
/ \ |
F H G
part1: OR
/ \
OR L
/ \
OR K
/ \
OR NOT
/ \ |
F H G
part2: OR
/ \
OR L
/ \
OR J
/ \
OR NOT
/ \ |
F H G
- 作者:
- messfish