The means of combination used in the query language may at first seem identical to the operations and, or, and not of mathematical logic, and the application of query-language rules is in fact accomplished through a legitimate method of inference.[1] This identification of the query language with mathematical logic is not really valid, though, because the query language provides a control structure that interprets the logical statements procedurally. We can often take advantage of this control structure. For example, to find all of the supervisors of programmers we could formulate a query in either of two logically equivalent forms:
and(job($x, list("computer", "programmer")),
supervisor($x, $y))
and(supervisor($x, $y),
job($x, list("computer", "programmer")))
The aim of logic programming is to provide the programmer with
techniques for decomposing a computational problem into two separate
problems:
what
is to be computed, and how
this
should be computed. This is accomplished by selecting a subset of the
statements of mathematical logic that is powerful enough to be able to
describe anything one might want to compute, yet weak enough to have a
controllable procedural interpretation. The intention here is that,
on the one hand, a program specified in a logic programming language
should be an effective program that can be carried out by a computer.
Control (how
to compute) is effected by using the order of
evaluation of the language. We should be able to arrange the order of
clauses and the order of subgoals within each clause so that the
computation is done in an order deemed to be effective and efficient.
At the same time, we should be able to view the result of the
computation (what
to compute) as a simple consequence of the
laws of logic.
Our query language can be regarded as just such a procedurally
interpretable subset of mathematical logic. An assertion represents a
simple fact (an atomic proposition). A rule represents the
implication that the rule conclusion holds for those cases where the
rule body holds. A rule has a natural procedural interpretation: To
establish the conclusion of the rule, establish the body of the rule.
Rules, therefore, specify computations. However, because rules can
also be regarded as statements of mathematical logic, we can justify any
inference
accomplished by a logic program by asserting that
the same result could be obtained by working entirely within
mathematical logic.[2]
A consequence of the procedural interpretation of logic programs is that it is possible to construct hopelessly inefficient programs for solving certain problems. An extreme case of inefficiency occurs when the system falls into infinite loops in making deductions. As a simple example, suppose we are setting up a data base of famous marriages, including
assert(married("Minnie", "Mickey"))
married("Mickey", $who)
assert(rule(married($x, $y),
married($y, $x)))
married("Mickey", $who)Another quirk in the query system concerns not. Given the data base of section 4.4.1, consider the following two queries:
and(supervisor($x, $y),
not(job($x, list("computer", "programmer"))))
and(not(job($x, list("computer", "programmer"))),
supervisor($x, $y))The trouble is that our implementation of not really is meant to serve as a filter on values for the variables. If a not clause is processed with a frame in which some of the variables remain unbound (as does $x in the example above), the system will produce unexpected results. Similar problems occur with the use of javascript_predicate—the JavaScript predicate can't work if some of its variables are unbound. See exercise 4.74.
There is also a much more serious way in which the
not of the query language differs from the
not of mathematical logic. In logic, we
interpret the statement not $P$
to
mean that $P$ is not true. In the query system,
however, not $P$
means that
$P$ is not deducible from the knowledge in the
data base. For example, given the personnel data base of
section 4.4.1, the system would
happily deduce all sorts of not statements,
such as that Ben Bitdiddle is not a baseball fan, that it is not raining
outside, and that $2 + 2$
is not 4.[4] In other
words, the not of logic programming languages
reflects the so-called
closed world assumption that all relevant information has been
included in the data base.[5]
rule(outranked_by($staff_person, $boss),
or(supervisor($staff_person, $boss),
and(outranked_by($middle_manager, $boss),
supervisor($staff_person, $middle_manager))))
outanked_by(list("Bitdiddle", "Ben"), $who)wheel($who)
Query results:
wheel(list("Warbucks", "Oliver"))
wheel(list("Bitdiddle", "Ben"))
wheel(list("Warbucks", "Oliver"))
wheel(list("Warbucks", "Oliver"))
wheel(list("Warbucks", "Oliver"))
sum($amount,
and(job($x, list("computer", "programmer")),
salary($x, $amount)))Oh, no, my simple accumulation scheme won't work!What has Ben just realized? Outline a method he can use to salvage the situation.
greatto a grandson relationship. This should enable the system to deduce that Irad is the great-grandson of Adam, or that Jabal and Jubal are the great-great-great-great-great-grandsons of Adam.
related(list("great", "grandson"), "Adam", "Irad")
list(pair("great", $rel), $x, $y)inferenceaccomplished by a logic program, we assume that the computation terminates. Unfortunately, even this qualified statement is false for our implementation of the query language (and also false for programs in Prolog and most other current logic programming languages) because of our use of not and javascript_predicate. As we will describe below, the not implemented in the query language is not always consistent with the not of mathematical logic, and javascript_predicate introduces additional complications. We could implement a language consistent with mathematical logic by simply removing not and javascript_predicate from the language and agreeing to write programs using only simple queries, and, and or. However, this would greatly restrict the expressive power of the language. One of the major concerns of research in logic programming was to find ways to achieve more consistency with mathematical logic without unduly sacrificing expressive power.
To show $P(x)$ is true, show that $P(f(x))$ is true,for some suitably chosen function $f$.
Negation as Failureby Clark (1978).