Project 2 of CS1573 of Spring 2005
Last edited 2/14/05
The project is to implement an natural language understand (NLU)
front end to the theorem prover of project 1. You should
use a top-down parser and a definite clause grammar. In fact, you
should use the same theorem prover in two ways. With a bunch of
Horn clauses that represent NL knowledge, it serves as the top-down
parser. With a bunch of Horn clauses that represent blocks world
knowledge, it serves as a reasoner.
From the lecture of Feb 14 (S10.ppt), you'll
know that a basic approach is to represent a grammatical rule such as
S--> NP VP as the definite clause rule
Append(s1, s2, s3) & NP(s1, m1) & VP(s2, m2) & call(m3,
s.semantics(m1, m2)) >>S(s3, m3)
Where s1, s2 and s3 are logical variables that get bound to word
strings, and m1, m2 and m3 are logical variables that get bound to
quasi-logical forms.
A good data structure for representing a word string is
<word>*<word>*...*<word>*NIL, where * is the binary
arithmetic operator and the whole thing is an instance of an
Expr. Thus, the string "BlockA is large" would be
represented as BlockA*Is*Large*NIL. Because a word string is
represented as an Expr, we can use the Horn clauses themselves to
decompose them and merge them. For instance, you may use the Horn
clauses below to define the Append predicate:
Append(NIL, u, u).
Append(y,z,w) >> Append(x*y, z, x*w)
As mentioned in class, this code assumes that BlockA*Bites*NIL is
the same thing as BlockA*(Bites*NIL), and it is not the same thing as
(BlockA*Bites)*NIL. You should confirm that this is the case.
For a data structure that represents meaning, you are on your
own. There are some ideas in the lecture notes and in the
textbook. If you can figure out a way to use the Expr class,
great--that may keep your life simple. However, you will probably
need the full power of Python to compose to pieces of quasi-logical
form into a single larger piece, as done in the rule above. This
is why the rule includes call(m1, s.semantics(m1,m2)), which looks a
bit like a predicate, but when the theorem prover is given such a thing
as a goal to prove, it calls Python instead. Actaually, it first
applies the subsitution list to the second argument, creating something
like s.semantics(<quasi-logical form>, <quasi-logical
form>), then evaluates that. The result it returns is bound
the the variable in the second argument position.
The top level of your code should do the following steps:
- Input a word string
- Call KB.ask with Horn clause rules representing a definite clause
grammar and a lexicon. It should produce all possible interpretations
of the sentences, which means running the theorem prover again and
again in order to generate all successes. Each success should
result in a different list of substitutions. One of the
substitions will pair the logical variable for the meaning of the whole
sentence (e.g, m3) with a quasi-logical form.
- Convert the quasi-logical forms to logical forms. This
means extracting quantifier expressions from the positions as arguments
and putting them where they belong in a proper logical experssion.
- Call either KB.tell or KB.ask with the logical forms and the
blocks world KB. If you are answering a question, then use
KB.ask, and collect all possible answers.
- Gather up the answers, and decide how to respond. For
successful assertions (e.g., "BlockA is red") return "yes." For
yes-no questions (e.g., "Is there a large red block?"), return yes or
no. For Wh-questions, return a list of answers. For
instance, if the question is "Which blocks are red?" then it might says
"{BlockA, BlockB}".
Testing
The more English that your agent can handle, the better. Thus,
these section defines several levels. To get full marks, you must
accomplish all of them, but you should attempt them in the order shown.
Start by trying to get it to handle simple assertions and yes-no
questions, where all the NPs are proper nouns, and the VPs are either
"is <adjective>" or "<verb> <NP>." The test
sentences should include:
- BlockA is large
- Is BlockA large?
- BlockA supports BlockB.
- Does BlockA touch BlockB? (This assume the blocks world KB
has a rule that if x supports y then x touches y)
- Does BlockA dwarf BlockB? (this means "Is BlockA larger
than BlockB," but says it in a syntactically simple way.)
For the next level, assume that NPs can be <article><noun>
combinations, but still are not allowed to have adjectives or other
modifiers. This level includes sentences such as:
- BlockA is a pyramid.
- Is a pyramid red? (This results in proving the goal:
pyramid(x)&red(x).)
- Every pyamid is red. (This should results in asserting the
Horn clause "if x is a pyramid, then x is red")
- The pyramid is large. (This has the presupposition that
"The pyramid" is a unique object; You can ignore this presupposition
and treat the sentence the same way that you treat "Every pyramid is
red.")
The next level of competence includes Wh questions where the Wh phrase
appears as the subject of the sentence:
- Which blocks are large?
- What block is red? [Although this presupposes that there is
just one red block, you can ignore this presuppostion. Thus, this
questions is treated exactly the same way as "Which blocks are red?"]
This section of the assigment may be modified on the basis of Bryan's
experience in creating a solution for the project.
Grading
Submit via email to both the TA and the instructor the following:
- Your code, including
your version of the test sentences
- A trace (generated by
print statements in your code) of the code working through the test
suite.
- Instructions for how to
load, initialize and run your version of our test
suite. We may verify that the test suite works by running your
code.
- Design Discussion.
List the three hardest design problems
you encountered, and describe how you solved them.
Points for the assignment will be awarded based on
- How much of the test suite is handled correctly.
- The correctness of the code. Points off for bugs &
hacks.
- The clarity of the code; should be modular, have legible names,
good comments, good documentation, etc.
- The clarity and thoughtfulness of the Design Discussion.
- Your ability to answer questions about the code during the oral
exam.
Don't forget the ground rules on plagarism, which are repeated here:
You
should do your own programming for the programming projects.
Except as noted below, copying code written by others, including code
you've found on the web, is considered plagarism. Hiring others
to do your programming is considered plagarism. If I decide that
you have plagarized your programming assignment, I will give you a zero
on it. If you plagarize more than once, then I will consider
formal disciplinary action, including failure of the course. Exceptions: You definitely
should include code from the textbooks' Python code
repository. As you will see, many of the functions you will
want to use have been stubbed out--you will have to provide their
implementation, but key data structures have been defined for
you. If you wish, you may include code from the Python package index or the Vaults of Parnassus. As
of 1/3/04, there does not appear to be anything useful in either the
Python package index or the Vaults of Parnassus.
However, if you find something useful (modules are added daily), you
may use it if
- You clearly identify in your source code where the package came
from
- You are prepared to answer questions during the oral exam about
how it works
- You contact me as soon as you have found a package that you want
to use. Send me email with a URL for the package. If I
believe that it simplifies the project, then I'll send email to all the
students and may extend the project to make it sufficiently
challenging. If your project is submitted with a reference to
such a package and you did not contact me, then your score on the
project will be lowered.