I. Top-down ground proof query procedure Today we talked about the details of the proof procedure that allows CILOG to turn our queries into yes or no answers. The procedure is called the top-down ground proof query procedure. There's a corresponding bottom-up procedure that you should read about in your textbook; we won't talk about it here. The top-down ground proof query procedure begins with a generalization of modus ponens, the basic rule of inference: if "h <- b1 ^ b2 ^ ... ^ bm" is a clause in the knowledge base, and each bi has been derived, then h can be derived Or in other words, if you know that each bi is true, then "and"ing them all together is true, so you can infer that h is true. (The word "derived" means it can be computed from the knowledge base. If g can be derived from KB, we can denote this with KB |- g.) Now when we say something like this to CILOG: "ask a1 & a2 & ... & am." we're really saying "prove this theorem: a1 & a2 & ... & am." In Datalog, the almost-CILOG language used in your text, you'd see "^" instead of "&", but otherwise it's the same thing. Either way, the theorem gets converted to an answer clause that looks like this: yes <- a1 ^ a2 ^ ... ^ am. Given an answer clause, the proof procedure begins the real work. First, the proof procedure selects on atom or conjunct from the right hand side of the answer clause. Let's say the selected atom is ai. Next the proof procedure chooses a clause from the knowledge base whose head matches ai. The chosen clause might be ai <- b1 ^ ... ^ bx. The proof procedure then resolves the answer clause with the clause chosen from the knowledge base by replacing the ai in the answer clause with the body of the chosen clause from the knowledge base: yes <- a1 ^ a2 ^ ... ^ b1 ^ ... ^ bx ^ ... ^am. The proof procedure repeats this process until all of the atoms in the body of the answer clause have resolved to True: yes <- a1 ^ a2 ^ a3 ^ ... ^ am. yes <- a1 ^ true ^ a3 ^ ... ^ am. yes <- a1 ^ a3 ^ ... ^ am. yes <- a1 ^ true ^ ... ^ am. yes <- a1 ^ ... ^ am. : : yes <- . A sequence of answer clauses that ends with "yes <- ." is called a derivation, and the process is called definite clause resolution. Here's a brief algorithmic description of a top-down definite clause interpreter: solve or prove: ?a1 ^ ... ^ ak. AC := yes <- a1 ^ ... ^ ak. repeat select a conjunct ai from the body of AC choose a clause C from KB with ai as its head replace ai in the body of AC with the body of C until AC is an answer (that is, until AC is yes <- .) There are a couple of things to note here. First, this description ignores what is to be done with variables. We'll deal with this next time. The other thing to note is that this description is nondeterministic -- there are points in the algorithm where decisions are to be made, but how the decisions should be made isn't specified. It just says "select" a conjunct or "choose" a clause, but it never says which one. Of course, you've learned in previous CS classes that it's possible to simulate nondeterminism, or in this case to find all derivations, by systematically considering all possibilities, right? II. "select" vs. "choose" While we're on the topic of nondeterminism, it's worthwhile to mention that there are actually two kinds of nondeterminism involved here. The first kind of nondeterminism is called "don't-care" nondeterminism, and it's indicated in the algorithm above by the word "select". In the case of our top-down interpreter, the interpreter selects any atom or conjunct from the body of the answer clause and attempts to derive that atom from the knowledge base, thus showing the atom to be true. If the interpreter can't find a derivation for that atom, it doesn't care about looking at other atoms in the answer clause. If the selected atom isn't true, then the conjunction of the selected atom and all the other atoms in the answer clause can never be true, so there's no sense in trying another atom from the answer clause. The second kind of nondeterminism is called "don't-know" nondeterminism, and it's indicated by the use of the word "choose". When an atom from the answer clause has been selected, the interpreter must then choose a clause from the knowledge base to resolve with the selected atom in an attempt to derive the atom from the knowledge base. If that resolution ultimately leads to a solution, then all is well. If not, however, the nondeterministic question to be answered is "will choosing a different clause from the knowledge base make a difference?" In this case, the answer is that the interpreter doesn't know. It is possible, however, that choosing a different clause from the KB could yield a different result, so the interpreter backtracks to the decision point, chooses a different clause, and tries again to find a derivation. So in this case, the interpreter does care about choosing another clause, it just doesn't know if a different choice will yield a different result, thus it tries another choice of clause.
Last revised: October 3, 2004