A B1, B2, ... , Bn.
where A and B1 through Bn are predicates. A is called the head of the rule and the expression to the right of the '''' is called the body.
part_cost1(X, Y) <- part_cost(top_tube, X, Y, Z).
run_for_your_life <- physician(`Dr. Frankenstein`).
distance(City, City, 0).
distance(`Austin`, `Waco`, 110).Facts are normally stored in the database (but facts occasionally occur in the program.)
A <- B. A <- C.
are logically equivalent to
(B A) & (C A)
which is
(B C) A.
We will refer to a predicate such as A, which is the result of the union
of two (or more) rules, as a union predicate.
Rules: Interpretation
A rule,
A B1, B2, ... , Bn.
is logically equivalent to: the conjunction of B1, B2, ... , Bn implies A.
When the truth value of each predicate in the body is TRUE, the head predicate is also TRUE.
b(1,2).
b(2,4).
Equality Predicate
|
sums(X) <- t(X,Y,Z), X = Y + Z.
returns all a,b,c such that the tuple t(a,b,c) appears in t
and a = b + c. The equality serves as a test.
t(3,2,1).
t(5,2,3).
t(8,4,3).
t(7,4,3).
t(7,3,4).
export sums(X); query sums(X) returns {sums(3), sums(5), sums(7)}
export sums($X); query sums(5) returns TRUE, query sums(8) returns FALSE.
Equation Solving
t1(X, Z) is a base predicate; X, Z are integers.
sums1(Y) <- t1(X, Z), X = Y*Y + Z.
Fails at compile time! Although X, Z are known, the system cannot solve the equation for Y.
(The current
will however
solve simple linear equations.)
Equality Predicate Operating as single Assignment
t1(X, Z) is a base predicate, X, Z are integers.
sums2(Y) <- t1(X, Z), Y = X + Z.
export sums2(X)
compiles correctly! In this form the equality is used as a single assignment.
t1(1,2).
t1(3,5).
query sums2(X) returns {sums2(3), sums2(8)}.
export sums2($X); query sums2(3) returns TRUE, query sums2(4) returns FALSE.
Safety thus depend on the exectution used (e.g., bottom-up, top-down, or a combination of the two).
Safety: Example
good_salary(X) <- X > 80000.
export good_salary(X) does not compile!
export good_salary($X) is safe.
In the bound values in the exports are always propagated down to the defining predicates---if these are not recursive. For recursive predicates the situation is more complex and will be discussed later.
Safety: Modified Example
well_paid_employee(Name,Salary) <- employee(Name,Salary), Salary > 80000.Now
export well_paid_employee(Name,Salary)
Arithmetic
|
Y + Z
X * ( Y / Z)
Arithmetic: Precedence
Example: The term A / B * C + D will be evaluated in the following order:
Arithmetic: Result Types
Example:
result(X) <- b(A, B), X = A / B.b(1, 2).
query result(X) returns result(0) when A,B are declared as integers in the schema, it returns result(0.500) when A,B are declared real numbers.
Arithmetic: Example
|
Two equivalent formulations:
distance_feet1(X, Z, W) <- distance(X, Z, Y), W = 5280 * Y.
or,
distance_feet(X, Z, 5280 * Y) <- distance(X, Z, Y). export distance_feet($X, $Z, Y).When the user types:
query distance_feet('Austin', 'Bastrop', Z)the system returns:
distance_feet( 'Austin', 'Bastrop', 158400 ). -- 1 solution
``List all cities which are within 100 miles of Austin''.
close(X, Y, Z) <- distance(X, Y, W), W < Z. export close($X, Y, $Z). query close( 'Austin', City, 100) close( 'Austin', 'San_antonio', 100 ). close( 'Austin', 'Bastrop', 100 ). -- 2 solutions
The query form: export close($X, Y, Z) will not compile. Why?
Arithmetic: Safety
Also, the program
close1(X, Y, Z) <- W < Z, distance(X, Y, W). export close1($X, Y, $Z)will not compile, since W is unbound when used in the comparison. Predicates must be permuted in the body to render it safe.