Comp 212 Programming Assignment #1
Boolean Simplifier
Due 99.October.28 at 11:59 PM (Thursday night)
The purpose of this assignment is to build a system of cooperating objects to simplify boolean expressions. Such a program has application in digital logic. The process of simplifying a boolean expression consists of the following steps.
In this assignment, you are to write appropriate classes to carry out steps 1, 2, 3, and 4. As a starting point, you must use the class design provided in the solution to questions 2 and 3 of homework 3. Unless instructed otherwise, you are free to extend and modify this design as long as you do not change the names and the semantics of the given classes and their public methods. At a later time, we will provide you with one or more classes that we will use to test your program. These classes are capable of reading files containing an arbitrary number of boolean expressions and create appropriate boolean expressions objects specified in the aforementioned class design. This is why you must not change the names and public methods of the classes that are given to you, unless instructed otherwise. You will pay a 20% grade penalty if you do not follow this particular constraint.
Here is a sample input file.
(> z (| y z))
(> (| (! a) b) (> a b))
(& (| x y)(& (| x (! y))(& (| (! x) y)(| (! x) (! y)))))
Your program will be graded using a much larger and more demanding data file.
A Semi-Normal Form is defined recursively as follows.
Variable and Constant objects are said to be atomic.
Examples.
Define an interface called ISNForm, to represent objects in semi-normal form and an interface called ISNFVisitor, to represent visitors to ISNForm. Modify Variable and Constant to implement ISNForm. Variable and Constant are thus simultaneously a ABooleanExp and a ISNForm. This is an example of multiple inheritance. Review chapter 4 of JPL for more details on multiple inheritance. Define class SNIf to implement ISNForm as specified in the UML diagram below. The method SNIf.equals (Object obj) is used to compare a SNIf with other objects for equality. Checking for equality is needed in performs reduction and deconversion. Since it makes sense to only compare objects of the same type, you may use instanceof to do type checking in this method.

Define a class called SNFConverter as an IBEVisitor to convert a ABooleanExp to an ISNForm.
A Normal Form is defined recursively as follows.
Examples.
Before we describe the normalization algorithm, we first describe a "helper" algorithm called "head normalization". Head normalization is a ISNFVisitor whose host is either atomic (i.e. a Variable or a Constant), or a SNIf(test, conseq, alt)where all three components test, conseq, alt are in normal form. Head normalization takes such a host and transforms it into an equivalent normalized ISNForm. The algorithm for head normalization is based on the logical formula: (? (?tt tc ta) c a ) == (? tt (? tc c a) (? ta c a))(can you see why?), and can be carried out recursively as follows.
Normalization is a ISNFVisitor which makes use of the head normalization process. We are now ready to describe the normalization algorithm.
Define an ISNFVisitor called Normalizer that takes a ISNForm host and transforms it into an equivalent ISNForm in normal form. Define a ISNFVisitor called HeadNormalizer as an inner class of Normalizer to implement head normalization. Make HeadNormalizer an inner class of Normalizer to ensure that head normalization is invoked with the appropriate input type.
The process of "reducing" and "deconverting" ISNForm objects involves comparing them for equality. The specified method SNIf.equals (Object obj) is used for such a purpose. The way Constant is designed, the built-in operator == will correctly compute equality for Constant objects, and as a result, the inherited equals method also computes correctly. In order to compare Variable objects for equality using the built-in operator == (and consequently the inherited equals method), we need a unique Variable object for each distinct variable name. For example, there should be only one instance of a Variable object corresponding to the variable name "xyz". This can be achieved by applying the "flyweight" pattern to the manufacturing of Variable objects. In this pattern, Variable objects are said to be flyweights. Modify the class Variable as shown in the following diagram. The flyweight pattern will be covered in the lab.

In the above diagram,
Reduction is the process of performing "symbolic evaluation" to transform SNForm objects to "simplest" form . Reduction is a ISNFVisitor which performs symbolic evaluation on its host by applying the following translation rules until no further reduction is possible:
(1) (? T x y) -> x (2) (? F x y) -> y (3) (? V y y) -> y (4) (? V T F) -> V (5) (? V y z) -> (? V y[V=T] z[V=F])
The uppercase placeholder V stands for any Variable (as
opposed to any constant or formula). The notation y[X=T] means y
with all occurrences of the variable X replaced by the expression T.
If more than one rule matches the expression being evaluated, apply the rule that is nearest to the top of the list.
The symbolic evaluation process reduces every expression to "simplest" form,
which is T for tautologies and F for contradictions. In
principle, it can be accomplished by repeatedly applying the reduction rules shown above
until no further change is possible. But there are much more efficient ways to
accomplish the same process.
A simple but very effective algorithm is the following.
You can implement NFEnvironment by composing it with a QFList. This is an example of the "adapter pattern".

Constant obviously reduces to itself. Variable reduces to its binding in the environment or to itself if it is
unbound. Variable, you must look it up in the
environment to see if it reduces to a Constant. Constant, either
rule (1) or (2) applies. If it is a Variable, rule (3) or (4) may apply. If
rule 4 applies, no further simplification is possible. If rule 3 applies, the consequent
subformula x must be reduced. x and y and then perform
a final check to see if rules (3) and (4) can be used to perform one last simplification
step. Design an ISNFVisitor called Reducer that takes a ISNForm host and transforms it into an equivalent ISNForm in simplest form using the above algorithm.
Design an ISNFVisitor called DeConverter
that translates ISNForm objects back to conventional
boolean expression form (no if-then-else constructions are allowed) using the following
rules:
(? a T F) --> a (? a F T) --> (! a) (? a b F) --> (& a b) (? a F b) --> (& (! a) b) (? a T b) --> (| a b) (? a b T) --> (> a b)
where rules earlier in the list takes precedence over rules later in the list. Note
that the rules must be applied recursively to translate the component expressions a
and b.
When tackling a challenging programming problem, it is a good idea to solve a
simplified version of the problem first. In this case, you might try writing a Reducer
visitor class that implements all of the reduction rules except (5). You can later add the
processing required to support rule (5) by passing a NFEnvironment as the input to each Reducer
visitor.
Procedure for electronic submission will be announced later. Stay tuned!