I have been trying to learn Prolog, and am totally stumped on what the predicate s() does.
I see it used often and there is so little resources on the internet about Prolog that I cannot find an answer.
Ex.
/* sum(Is,S) is true if S is the sum of the list of integers Is. */
sum([],0).
sum([0|Is],S):-sum(Is,S).
sum([s(I)|Is], s(Z) ):-sum([I|Is],Z).
s/1 does not do anything in itself, and it's not really a predicate. They are just terms, a representation of the successor of their argument. So, s(0) is used to represent the successor of 0 (i.e. 1), s(s(0)) is used to represent the successor of s(0) (i.e. 2), and so on and so forth. They are so widespread in Prolog because Prolog is quite fine a language to perform symbolic computation, whereas even simple arithmetic operations feel clunky, meaning that they are not seamlessly integrated with the programming paradigm.
s/1 stands for successor. It's used to represent numbers in a logically accessible ways.
It is Prolog-implementation specific. It refers to a successor-predicate, see this for some more info
Related
I am currently studying logic programming, and learn Prolog for that case.
We can have a Knowledge Base, which can lead us to some results, whereas Prolog will get in infinite loop, due to the way it expands the predicates.
Let assume we have the following logic program
p(X):- p(X).
p(X):- q(X).
q(X).
The query p(john) will get to an infinite loop because Prolog expands by default the first predicate that is unified. However, we can conclude that p(john) is true if we start expanding the second predicate.
So why doesn't Prolog expand all the matching predicates (implemented like threads/processes model with time slices), in order to conclude something if the KB can conclude something ?
In our case for example, two processes can be created, one expanded with p(X) and the other one with q(X). So when we later expand q(X), our program will conclude q(john).
Because Prolog's search algorithm for matching predicates is depth-first. So, in your example, once matching the first rule, it will match again the first rule, and will never explore the others.
This would not happen if the algorithm is breadth-first or iterative-deepening.
Usually is up to you to reorder the KB such that these situations never happen.
However, it is possible to encode breadth-first/iterative-deepening search in Prolog using a meta-interpreter that changes the search order. This is an extremely powerful technique that is not well known outside of the Prolog world. 'The Art of Prolog' describes this technique in detail.
You can find some examples of meta-interpreters here, here and here.
If I have a subset of logic programming which contains only one function symbol, am I able to do everything?
I think that I cannot but I am not sure at all.
A programming language can do anything user wants if it is a Turing-complete language. I was taught that this means it has to be able to execute if..then..else commands, recursion and that natural numbers should be defined.
Any help and opinions would be appreciated!
In classical predicate logic, there is a distinction between the formula level and the term level. Since an n-ary function can be represented as an (n+1)-ary predicate, restricting only the number of function symbols does not lessen the expressivity.
In prolog, there is no difference between the formula and the term level. You might pick an n-ary symbol p and try to encode turing machines or an equivalent notion(e.g. recursive functions) via nestings of p.
From my intution I would assume this is not possible: you can basically describe n-ary trees with variables as leaves, but then you can always unify these trees. This means that every rule head will match during recursive derivations and therefore you are unable to express any case distinction. Still, this is just an informal argument, not a proof.
P.S. you might also be interested in monadic logic, where only unary predicates are allowed. This fragment of first-order logic is decidable.
Because Prolog uses chronological backtracking(from the Prolog Wikipedia page) even after an answer is found(in this example where there can only be one solution), would this justify Prolog as using eager evaluation?
mother_child(trude, sally).
father_child(tom, sally).
father_child(tom, erica).
father_child(mike, tom).
sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).
parent_child(X, Y) :- father_child(X, Y).
parent_child(X, Y) :- mother_child(X, Y).
With the following output:
?- sibling(sally, erica).
true ;
false.
To summarize the discussion with #WillNess below, yes, Prolog is strict. However, Prolog's execution model and semantics are substantially different from the languages that are usually labelled strict or non-strict. For more about this, see below.
I'm not sure the question really applies to Prolog, because it doesn't really have the kind of implicit evaluation ordering that other languages have. Where this really comes into play in a language like Haskell, you might have an expression like:
f (g x) (h y)
In a strict language like ML, there is a defined evaluation order: g x will be evaluated, then h y, and f (g x) (h y) last. In a language like Haskell, g x and h y will only be evaluated as required ("non-strict" is more accurate than "lazy"). But in Prolog,
f(g(X), h(Y))
does not have the same meaning, because it isn't using a function notation. The query would be broken down into three parts, g(X, A), h(Y, B), and f(A,B,C), and those constituents can be placed in any order. The evaluation strategy is strict in the sense that what comes earlier in a sequence will be evaluated before what comes next, but it is non-strict in the sense that there is no requirement that variables be instantiated to ground terms before evaluation can proceed. Unification is perfectly content to complete without having given you values for every variable. I am bringing this up because you have to break down a complex, nested expression in another language into several expressions in Prolog.
Backtracking has nothing to do with it, as far as I can tell. I don't think backtracking to the nearest choice point and resuming from there precludes a non-strict evaluation method, it just happens that Prolog's is strict.
That Prolog pauses after giving each of the several correct answers to a problem has nothing to do with laziness; it is a part of its user interaction protocol. Each answer is calculated eagerly.
Sometimes there will be only one answer but Prolog doesn't know that in advance, so it waits for us to press ; to continue search, in hopes of finding another solution. Sometimes it is able to deduce it in advance and will just stop right away, but only sometimes.
update:
Prolog does no evaluation on its own. All terms are unevaluated, as if "quoted" in Lisp.
Prolog will unfold your predicate definitions as written and is perfectly happy to keep your data structures full of unevaluated uninstantiated holes, if so entailed by your predicate definitions.
Haskell does not need any values, a user does, when requesting an output.
Similarly, Prolog produces solutions one-by-one, as per the user requests.
Prolog can even be seen to be lazier than Haskell where all arithmetic is strict, i.e. immediate, whereas in Prolog you have to explicitly request the arithmetic evaluation, with is/2.
So perhaps the question is ill-posed. Prolog's operations model is just too different. There are no "results" nor "functions", for one; but viewed from another angle, everything is a result, and predicates are "multi"-functions.
As it stands, the question is not correct in what it states. Chronological backtracking does not mean that Prolog will necessarily backtrack "in an example where there can be only one solution".
Consider this:
foo(a, 1).
foo(b, 2).
foo(c, 3).
?- foo(b, X).
X = 2.
?- foo(X, 2).
X = b.
So this is an example that does have only one solution and Prolog recognizes that, and does not attempt to backtrack. There are cases in which you can implement a solution to a problem in a way that Prolog will not recognize that there is only one logical solution, but this is due to the implementation and is not inherent to Prolog's execution model.
You should read up on Prolog's execution model. From the Wikipedia article which you seem to cite, "Operationally, Prolog's execution strategy can be thought of as a generalization of function calls in other languages, one difference being that multiple clause heads can match a given call. In that case, [emphasis mine] the system creates a choice-point, unifies the goal with the clause head of the first alternative, and continues with the goals of that first alternative." Read Sterling and Shapiro's "The Art of Prolog" for a far more complete discussion of the subject.
from Wikipedia I got
In eager evaluation, an expression is evaluated as soon as it is bound to a variable.
Then I think there are 2 levels - at user level (our predicates) Prolog is not eager.
But it is at 'system' level, because variables are implemented as efficiently as possible.
Indeed, attributed variables are implemented to be lazy, and are rather 'orthogonal' to 'logic' Prolog variables.
I was wondering what sort of sentences can't you express in Prolog? I've been researching into logic programming in general and have learned that first-order logic is more expressive compared to definite clause logic (Horn clause) that Prolog is based on. It's a tough subject for me to get my head around.
So, for instance, can the following sentence be expressed:
For all cars, there does not exist at least 1 car without an engine
If so, are there any other sentences that CAN'T be expressed? If not, why?
You can express your sentence straightforward with Prolog using negation (\+).
E.g.:
car(bmw).
car(honda).
...
car(toyota).
engine(bmw, dohv).
engine(toyota, wenkel).
no_car_without_engine:-
\+(
car(Car),
\+(engine(Car, _))
).
Procedure no_car_without_engine/0 will succeed if every car has an engine, and fail otherwise.
The most problematic definitions in Prolog, are those which are left-recursive.
Definitions like
g(X) :- g(A), r(A,X).
are most likely to fail, due to Prolog's search algorithm, which is plain depth-first-search
and will run to infinity and beyond.
The general problem with Horn Clauses however is, that they're defined to have at most one positive element. That said, one can find a clause which is limited to those conditions,
for example:
A ∨ B
As a consequence, facts like ∀ X: cat(X) ∨ dog(X) can't be expressed directly.
There are ways to work around those and there are ways to allow such statements (see below).
Reading material:
These slides (p. 3) give an
example of which sentence you can't build using Prolog.
This work (p. 10) also explains Horn Clauses and their implications and introduces a method to allow 'invalid' Horn Clauses.
Prolog is a programming language, not a natural language interface.
The sentence you show is expressed in such a convoluted way that I had hard time attempting to understand it. Effectively, I must thanks gusbro that took the pain to express it in understandable way. But he entirely glossed over the knowledge representation problems that any programming language pose when applied to natural language, or even simply negation in first order logic. These problems are so urgent that the language selected is often perceived as 'unimportant'.
Relating to programming, Prolog lacks the ability to access in O(1) (constant time) any linear data structure (i.e. arrays). Then a QuickSort, for instance, that requires access to array elements in O(1), can't be implemented in efficient way.
But it's nevertheless a Turing complete language, for what is worth. Then there are no statements that can't be expressed in Prolog.
So you are looking for sentences that can't be expressed in clausal logic that can be expressed in first order logic.
Strictly speaking, there are many, simply because clausal logic is a restriction of FOL. So that's true by definition.
What you can do though is you can rewrite any set of FOL sentences into a logic program that is not equivalent but with good properties. So for example if you want to know if p is a consequence of your theory, you can use equivalently the transformed logic program.
A few notes on the other answers:
Negation in Prolog (\+) is negation as failure and not first order logic negation
Prolog is a programming language, as correctly pointed out, we should be talking about clausal logic instead.
Left recursion is not a problem. You can easily use a different selection rule, or some other inference mechanism.
I'm still very new to prolog, and am trying to wrap my head around why math constraints don't seem to work the same way logical ones do.
It seems like there's enough information to solve this:
f(A, B) :- A = (B xor 2).
But when I try f(C, 3), I get back C = 3 xor 2. which isn't very helpful. Even less useful is the fact that it simply can't find a solution if the inputs are reversed. Using is instead of = makes the example input return the correct answer, but the reverse refuses to even attempt anything.
From my earlier experimentation, it seems that I could write a function that did this logically using the binary without trouble, and it would in fact go both ways. What makes the math different?
For reference, my first attempt at solving my problem looks like this:
f(Input, Output) :-
A is Input xor (Input >> 11),
B is A xor ((A >> 7) /\ 2636928640),
C is B xor ((B << 15) /\ 4022730752),
Output is C xor (C >> 18).
This works fine going from input to output, but not the other way around. If I switch the is to =, it produces a long logical sequence with values substituted but can't find a numerical solution.
I'm using swi-prolog which has xor built in, but it could just as easily be defined. I was hoping to be able to use prolog to work this function in both directions, and really don't want to have to implement the logical behaviors by hand. Any suggestions about how I might reformulate the problem are welcome.
Pure Prolog is not supposed to handle math. The basic algorithm that drives Prolog - Unify and backtrack on failure - Doesn't mention arithmetic operators. Most Prolog implementations add arithmetics as an ugly hack into their bytecode.
The reason for this is that arithmetic functions do not act the same way as functors. They cannot be unified in the same way. Not every function is guaranteed to work for each combination of ground and unground arguments. For example, the algorithm for raising X to the power of Y is not symmetric to finding the Yth root of X. If all arithmetic functions were symmetric, encryption and cryptography wouldn't work!
That said, here are the missing facts about Prolog operators:
First, '=' is not "equals" in Prolog, but "unify". The goal X = Y op Z where op is an operator, unifies X with the functor 'op'(Y,Z). It has nothing to do with arithmetic equality or assignment.
Second, is, the ugly math hack, is not guaranteed to be reversible. The goal X is Expr, where Expr is an arithmetic expression, first evaluates the expression and then tries to assign it to X. It won't always work for each combination of numbers and variables - Check your Prolog library documentation.
To summarize:
Writing reversible mathematical functions requires the mathematical knowledge and algorithm to make the function reversible. Prolog won't do the magic for you in this case.
If you're looking for smart equation solving, you might want to check Prolog constraint-solving libraries for finite and contiguous domains. Not the same thing as reversible math, but somewhat smarter than Prolog's naive arithmetic operators.
If you want to compare the result of evaluating expression, you should use the operator (=:=)/2, or when checking for apartness the operator (=/=)/2.
The operator works also for bitwise operations, since bitwise operations work on integeres, and integers are numbers. The operator is part of the ISO core standard. For the following clause:
f(A, B) :- A =:= (B xor 2).
I get the following runs, in SWI-Prolog, Jekejeke Prolog etc..:
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.31)
Copyright (c) 1990-2016 University of Amsterdam, VU Amsterdam
?- f(100, 102).
true.
?- f(102, 100).
true.
?- f(100, 101).
false.
If you want a more declarative way of handling bits, you can use a SAT solver integrated into Prolog. A good SAT solver should also support limited or unlimited bit vectors, but I cant currenty tell whats available here and what the restrictions would be.
See for example this question here:
Prolog SAT Solver