CS 1571: Homework 3 (programming)

FOL Inference: Forward Chaining (100 pts)

Assigned: October 25, 2017

Due: November 13, 2017

I. Implement basic (not necessarily efficient) FOL Forward-Chaining in Python, Java, or C#.

For this homework project, we will use the term rule to refer to an implication which has a left-hand side (LHS - a conjunction of non-negated atoms) and a right-hand side (RHS - one non-negated atom). Also, we will use fact to refer to a single atom. We will say applying or firing a rule to refer to a legal application of Generalized Modus Ponens to that rule, thus deriving a new fact.

For the purposes of this assignment, there are several simplifying assumptions to make your job easier:

In general, there is a set of rules, and a separate set of facts. Each time a new fact comes in, the Forward-Chain algorithm is invoked to set off all possible rule firing, like the "domino effect", adding new facts to the knowledge base. In addition to implementing Forward-Chain, you must write code to invoke it for each new incoming fact.

Unification algorithm. Due to the above simplifying assumptions, the unification algorithm can be simpler than that given in the text. Here is the unification algorithm you should implement:

Unify(f1, f2) takes two atoms as input, the second of which has no variables (a fact). If they can be matched, it returns a list of variable bindings. Otherwise, it returns "fail".

  1. Initialize substitutions (a local variable) to the empty list.
  2. If f1 and f2 have different predicate names or different numbers of arguments, Then return "fail".
  3. For each argument, a1, in f1, with corresponding argument a2 in f2:
      If a1 is a variable
      Then If a1 is bound to something other than a2 in substitutions
       Then return "fail"
        Else add the binding a1/a2 to substitutions
      Else If (constant) a1 doesn't equal (constant) a2
       Then return "fail"
  4. return substitutions
Make sure that when you invoke Unify you give the two arguments in the correct order (as shown above, the second argument must have no variables).

Text-based I/O. Your system should be able to handle (piped as standard input) input such as that shown below in Part II. As in the text, variables are lower-case, and constants are capitalized. You need not check for errors in the input -- you can assume the input is syntactically correct. You may expect the input to first list all the rules, and then all the facts. You can assume no spaces within each predicate-argument structure, but spaces everywhere else.

II. Test Your System.

Example 1: You must show your system working on the following example similar to the book, typed here for your convenience so you can cut-and-paste:

American(x)  ^  Weapon(y)  ^  Nation(z)  ^  Hostile(z)  ^  Sells(x,z,y)  ->  Criminal(x)
Owns(Nono,x)  ^  Missile(x)  ->  Sells(West,Nono,x)
Missile(x)  ->  Weapon(x)
Enemy(x,America)  ->  Hostile(x)
American(West)
Nation(Nono)
Enemy(Nono,America)
Owns(Nono,M1)
Missile(M1)
Nation(America)
PROVE   Criminal(West)

From this, it should derive that West is a criminal.

Note that test cases will include a final line at the end stating the required thing to PROVE.

Example 2: You must also show your system working on the following example:

Instrument(y)  ^  Musician(x)  ->  Plays(x,y)
Instrument(y)  ^  Plays(x,y)  ->  NotToneDeaf(x)
Musician(Grace)
Instrument(I1)
PROVE   NotToneDeaf(Grace)

From this, it should derive that Grace is not tonedeaf.

Other Examples: We will also test your system on new examples which will be announced on November 7. Note that some examples may involve cases where the proof fails. You should modify Example 1 or 2 to make sure you can handle this case.

III. Incremental Forward Chaining

Modify your code to do incremental forward chaining and retest your system. Your trace should give enough detail for you to include a writeup explaining how it shows that incremental forward-chaining is more efficient.

IV. What to Submit and Grading Guidelines

See Ahmed's Instructions.