I am developing a predicate in Prolog and it is possible for it to terminate before the end of it.
For that reason I was looking for a command similar to return; (C++). I used a cut ! but I'm doubtful as to what it literally stands for and if it does exactly what return; does. Ex:
pred(X) :-
X = 1 -> do this, !; else do that,
write('x =/= 1').
void pred(int X) {
if (X = 1) {do this; return;} else do that;
cout << "x =/= 1";
}
Are the functions above exactly the same?
There is no direct correspondence of Prolog's execution mechanism and those of traditional imperative languages. So any analogy rather leads you on a dead path.
In your example, the cut has no effect whatsoever: The (->)/2 alone will already exclude the Else branch. In a sense it does a "tiny" cut on If and the alternative. Would there be another clause to pred/1, your cut would exclude that branch too.
Prolog's execution mechanism is much more complex. If you insist on an analogy in imperative languages, think of iterators. The cut causes all iterators in scope of the cut to produce a done on the next next. So it is a bit like a break. Somewhat. But only in a language that supports iterators in the first place.
If you want to learn Prolog, don't try to develop your notions out of these (half) broken analogies.
Better start by imagining what relations a Prolog predicate describes and approximate from that the meaning of a predicate. Procedural notions will fit in, one by one.
So you have some procedural code like this:
def foo():
if cond1:
handle_cond1()
return
if cond2:
handle_cond2()
return
do_other_stuff()
You can transform this in the procedural domain to have no explicit returns, first doing this:
def foo():
if cond1:
handle_cond1()
return
if cond2:
handle_cond2()
else:
do_other_stuff()
And then doing this:
def foo():
if cond1:
handle_cond1()
else:
if cond2:
handle_cond2()
else:
do_other_stuff()
Once you have eliminated the return statements you can transform this into Prolog:
foo :-
cond1 ->
handle_cond1
; (cond2 ->
handle_cond2
; do_other_stuff
).
There is no way to immediately succeed in Prolog. (You can immediately fail with fail). You will have to perform a transformation like this to achieve a similar flow. Best of all would be to follow #false's advice and learn Prolog on its own terms.
As was pointed out, Prolog doesn't map well to procedural thought.
I find the best way to think of a Prolog program and its "database" as a tree (forest?). The analogy is a bit rough since the graph contains cycles (recursion).
When you ask the prolog engine to determine the truth or falseness of a particular assertion (predicate), it commences to do a depth-first, left-to-right traversal of the tree using unification (pattern matching) to guide the traversal. When the traversal reaches a leaf node, the predicate is true. On backtracking, it... backtracks and continues the tree walk. When there are no more reachable leaf nodes, the predicate fails.
Prolog is a descriptive language: you describe the conditions for success in terms of predicate calculus. Then you simply let Prolog's inference engine find the applicable solutions. If you try to shoehorn procedural, imperative thought into the model, in addition to making things more difficult than they should otherwise be, in my experience, you're pretty much guaranteeing poor performance.
I found Leon Sterling and Eliot Shapiro's textbook, The Art of Prolog, to be invaluable and far more instructive and enlightening than Clocksin & Mellish's Programming in Prolog.
Edited to note: Your sample predicate
pred(X) :-
X = 1 -> do this , ! ; else do that ,
write('x =/= 1')
.
has some problems.
First, just like C or C# or other procedural languages where the and and or operators have different precedences so an expression like if ( a && b || c && d ) ... probably doesn't bind the way you think it does, due to operator precedence, your example predicate is probably not doing what you think it's doing: as written, it binds as
pred(X) :-
X=1 ->
( do_this , ! )
;
( do_that , write( 'x =/= 1' ) )
.
When what you probably wanted was
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that ,
) ,
write( 'x =/= 1' )
.
You need to use parentheses to omake your intended binding explicit:
pred(X) :-
( X=1 ->
( do_this , ! )
;
do_that
),
write('x =/= 1')
.
Further, the cut (!) in your example is unnecessary, since the implication operator -> acts as if there were a cut involved. This:
foo(X) :-
truthy(X) ->
writeln('truthy!')
;
writeln('falsy')
.
is pretty much exactly the same thing as
foo(X) :- truthy(X) , ! ,
writeln( 'truthy' ) .
foo(_) :- writeln( 'falsy' ) .
Third, you should make use of unification and pattern matching in the head. Ignoring the write/1, your example might make better sense as
pred(1) :- do_this , ! .
pred(X) :- do_that .
And in general, if you're learning prolog, I would say avoid the implication operator (and alternation (logical OR, ';'/2) in general. Prefer explicit predicates with multiple clauses to express choice. Instead of something like
foo(X) :- ( try_this(X) ; try_that(X) ; finally(X) ) .
prefer
foo(X) :- try_this(X) .
foo(X) :- try_that(X) .
foo(X) :- finally(X) .
And instead of implication:
foo(X) :- X=1 -> try_this(X) ; try_that(X) .
prefer something like this:
foo(1) :- ! , try_this(X) .
foo(X) :- try_that(X) .
I think it makes it easier to grok what's going on since it makes the choice points (and their elimination) explicit.
I would like to add that having solid coding guidelines can also help quite a bit to increase code readability and to avoid code brittleness.
Starting with #DanielLyons' code:
foo :-
cond1 ->
handle_cond1
; (cond2 ->
handle_cond2
; do_other_stuff
).
In practice, cascades of multiple nested if-then-else constructs occur: "if-then-elseif-then-elseif-then-elseif-then-...-else".
To increase readability, the code layout can be brushed up and the level of indentation adjusted:
foo :-
( cond1 -> handle_cond1
; cond2 -> handle_cond2
; do_other_stuff
).
Whenever code lines get too wide, a slightly less wide and more tall style may be preferable:
foo :-
( cond1
-> handle_cond1
; cond2
-> handle_cond2
; do_other_stuff
).
Related
I am trying to write a crossword solver I have got this code but I can't Understand some parts of it:
size(5).
black(1,3).
black(2,3).
black(3,2).
black(4,3).
black(5,1).
black(5,5).
words([do,ore,ma,lis,ur,as,po, so,pirus, oker,al,adam, ik]) .
:- use_module(library(lists),[nth1/3, select/3]).
crossword(Puzzle) :-
words(WordList),
word2chars(WordList,CharsList),
make_empty_words(EmptyWords) ,
fill_in(CharsList,EmptyWords),
word2chars(Puzzle,EmptyWords).
word2chars([],[]).
word2chars([Word|RestWords] ,[Chars|RestChars] ) :-
atom_chars(Word,Chars),
word2chars(RestWords,RestChars).
fill_in([],[]).
fill_in([Word|RestWords],Puzzle) :-
select(Word,Puzzle,RestPuzzle),
fill_in(RestWords,RestPuzzle).
make_empty_words(EmptyWords) :-
size(Size),
make_puzzle(Size,Puzzle),
findall(black(I,J),black(I,J),Blacks) ,
fillblacks(Blacks,Puzzle),
empty_words(Puzzle,EmptyWords).
make_puzzle(Size,Puzzle) :-
length(Puzzle,Size),
make_lines(Puzzle,Size).
make_lines([],_).
make_lines([L|Ls],Size) :-
length(L,Size),
make_lines(Ls,Size).
fillblacks([],_).
fillblacks([black(I,J)|Blacks],Puzzle) :-
nth1(I,Puzzle,LineI),
nth1(J,LineI,black),
fillblacks(Blacks,Puzzle).
empty_words(Puzzle,EmptyWords) :-
empty_words(Puzzle,EmptyWords,TailEmptyWords),
size(Size),
transpose(Size,Puzzle,[],TransposedPuzzle),
empty_words(TransposedPuzzle,TailEmptyWords,[] ).
empty_words([],Es,Es).
empty_words([L|Ls],Es,EsTail) :-
empty_words_on_one_line(L,Es,Es1) ,
empty_words(Ls,Es1,EsTail).
empty_words_on_one_line([], Tail, Tail).
empty_words_on_one_line([V1,V2|L],[[V1,V2|Vars]|R],Tail) :-
var(V1), var(V2), !,
more_empty(L,RestL,Vars),
empty_words_on_one_line(RestL,R,Tail) .
empty_words_on_one_line([_| RestL],R, Tail) :-
empty_words_on_one_line(RestL,R,Tail) .
more_empty([],[],[]).
more_empty([V|R],RestL,Vars) :-
( var(V) ->
Vars = [V|RestVars],
more_empty(R,RestL,RestVars)
;
RestL = R,
Vars = []
).
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0 ->
TransposedPuzzle = Acc
;
nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
nth_elements(_,[],[]).
nth_elements(N,[X|R],[NthX| S]) :-
nth1(N,X,NthX),
nth_elements(N,R,S).
This code is used for solving crosswords like this:
What are symbols ; -> used for?
My main problem is understanding the rules , transpose and more_empty.
Any explanation to help me understand the code would be appreciated.
-> and ; are Prolog's control flow, like the if-then-else satement in other languages. So:
transpose(N,Puzzle,Acc,TransposedPuzzle) :-
( N == 0 ->
TransposedPuzzle = Acc
;
nth_elements(N,Puzzle,OneVert),
M is N - 1,
transpose(M,Puzzle,[OneVert|Acc], TransposedPuzzle)
).
translates to psuedocode:
def transpose(N, Puzzle, Acc)
if N == 0
return Acc
else
OneVert = nth_elements(N, Puzzle)
transpose(N-1, Puzzle, [OneVert, Acc])
or:
def transpose(N, Puzzle, Acc)
while N > 0
OneVert = nth_elements(N, Puzzle)
Acc = [OneVert, Acc]
N = N - 1
return Acc
That should give you some idea what it does. I suggest you translate the more_empty function into psuedocode yourself (or just step through it in your head), and try to work it out from there.
In addition to the correct answers of Josh and Avi Tshuva stating that a -> b ; c is like "if a then b else c", I would like to explain that -> and ; are individual operators which can be used separately.
; is logical disjunction, ie. logical "or". So x; y means "x or y". This makes the conditional statement a bit confusing because a -> b ; c reads like "a implies b or c" which is obviously not what it means! Even if you parenthesize it like "(a implies b) or c" you get a different meaning from the conditional statement because in this incorrect interpretation, c will always be tried, even if (a implies b) succeeds.
The difference is because -> has some "non-logical" semantics. From SWI-Prolog docs:
:Condition -> :Action If-then and If-Then-Else. The ->/2 construct commits to the choices made at its left-hand side, destroying choice points created inside the clause (by ;/2), or by goals called by this clause. Unlike !/0, the choice point of the predicate as a whole (due to multiple clauses) is not destroyed. The combination ;/2 and ->/2 acts as if defined as:
If -> Then; _Else :- If, !, Then.
If -> _Then; Else :- !, Else.
If -> Then :- If, !, Then.
Please note that (If -> Then) acts as (If -> Then ; fail), making the construct fail if the condition fails. This unusual semantics is part of the ISO and all de-facto Prolog standards.
(note that in the above quote, If, Then etc. are variables!)
So beware of anything with an implicit cut!
These are Prolog's if-then-else control structure.
The syntax is as follows:
condition -> then statements/decelerations ; else
statements/declerations
I am trying to make a game similar to minesweeper and i need to check the neighbours of a square in the map but i get a syntax error at my for loop, I am using SWI-Prolog
checkneighbours(X,Y) :-
retractall(vecini(_)),
assert(vecini(0)),
foreach(I in X-1..X+1,
(foreach J in Y-1..Y+1,
(map(I,J,Z),
( Z=:= "X"
-> vecini(V),
V1 is V+1,
assert(vecini(V1))
)
)
)
).
didn't I declare the loops right? or how can I loop between X-1 and X+1?
There are no real loops like that in Prolog. I am also not sure if it is wise to use assert to dynamically change the fact database (it is usually better to represent your data in a structure). But if you really insist to use a "loop" for its side effects, you should be using forall:
?- forall( between(-1,1,X), format('~d~n', [X]) ).
-1
0
1
true.
I need some help here with Prolog.
So I have this function between that evaluates if an element is between other two.
What I need now is a function that evaluates if a member is not between other two, even if it is the same as one of them.
I tried it :
notBetween(X,Y,Z,List):-right(X,Y,List),right(Z,Y,List). // right means Z is right to Y and left the same for the left
notBetween(X,Y,Z,List):-left(X,Y,List),left(Z,Y,List).
notBetween(X,Y,Z,List):-Y is Z;Y is X.
I am starting with Prolog so maybe it is not even close to work, so I would appreciate some help!
When it come to negation, Prolog behaviour must be handled more carefully, because negation is 'embedded' in the proof engine (see SLD resolution to know a little more about abstract Prolog). In your case, you are listing 3 alternatives, then if one will not be true, Prolog will try the next. It's the opposite of what you need.
There is an operator (\+)/2, read not. The name has been chosen 'on purpose' different than not, to remember us that it's a bit different from the not we use so easily during speaking.
But in this case it will do the trick:
notBeetwen(X,Y,Z,List) :- \+ between(X,Y,Z,List).
Of course, to a Prolog programmer, will be clearer the direct use of \+, instead of a predicate that 'hides' it - and requires inspection.
A possibile definition of between/4 with basic lists builtins
between(X,Y,Z,List) :- append(_, [X,Y,Z|_], List) ; append(_, [Z,Y,X|_], List).
EDIT: a simpler, constructive definition (minimal?) could be:
notBetween(X,Y,Z, List) :-
nth1(A, List, X),
nth1(B, List, Y),
nth1(C, List, Z),
( B < A, B < C ; B > A, B > C ), !.
EDIT: (==)/2 works with lists, without side effects (it doesn't instance variables). Example
1 ?- [1,2,3] == [1,2,3].
true.
2 ?- [1,2,X] == [1,2,X].
true.
3 ?- [1,2,Y] == [1,2,X].
false.
I have the code
newplan(State, [c(StateList)], [], State):- satisfied( State, StateList).
and I don't know what c() predicate does. I tried to search internet for answers but I couldn't find. Please help me.
In this code c/1 is just a structure. Prolog is a little different from most languages, in that a structure and a predicate (what might be thought of as a function call in another language) share syntax. So here c/1 doesn't do anything, it's just a marker that (presumably) is granted meaning through something else in the code which you haven't shared with us.
Let me give you a concrete example.
eval(c(X), X2) :- X2 is (X*2) + 3.
eval(q(X), X2) :- X2 is X / 3.
something_to_do(c(14)).
something_to_do(q(21)).
In this code, c/1 and q/1 do not do anything. If you query something_to_do/1 you'll get structures back:
?- something_to_do(X).
X = c(14) ;
X = q(21) ;
false.
But if you then pass that structure to eval/2 it does something depending on which structure it gets. So you could say eval/2 imbues the structure q/1 and c/1 with meaning (though "imbuing meaning" is not in any sense official Prolog nomenclature).
?- something_to_do(X), eval(X, Y).
X = c(14), Y = 31 ;
X = q(21), Y = 7 ;
false.
It's the same story here. You're going to have to search your codebase and find out what c/1 means in it, because it is not a built-in predicate.
Note: it's possible to have structures and predicates with the same name in the same codebase at the same time. For instance, I could add a predicate like
q(foo).
q(bar).
q(X) :- even(X).
and this predicate does not in any sense overlap with the q/1 structure above. This is just one of those fun confusing things about Prolog (later on it turns out to be powerful and grand). There is an acute difference between creating structures and attempting to unify goals.
I starting to study for my upcoming exam and I'm stuck on a trivial prolog practice question which is not a good sign lol.
It should be really easy, but for some reason I cant figure it out right now.
The task is to simply count the number of odd numbers in a list of Int in prolog.
I did it easily in haskell, but my prolog is terrible. Could someone show me an easy way to do this, and briefly explain what you did?
So far I have:
odd(X):- 1 is X mod 2.
countOdds([],0).
countOdds(X|Xs],Y):-
?????
Your definition of odd/1 is fine.
The fact for the empty list is also fine.
IN the recursive clause you need to distinguish between odd numbers and even numbers. If the number is odd, the counter should be increased:
countOdds([X|Xs],Y1) :- odd(X), countOdds(Xs,Y), Y1 is Y+1.
If the number is not odd (=even) the counter should not be increased.
countOdds([X|Xs],Y) :- \+ odd(X), countOdds(Xs,Y).
where \+ denotes negation as failure.
Alternatively, you can use ! in the first recursive clause and drop the condition in the second one:
countOdds([X|Xs],Y1) :- odd(X), !, countOdds(Xs,Y), Y1 is Y+1.
countOdds([X|Xs],Y) :- countOdds(Xs,Y).
In Prolog you use recursion to inspect elements of recursive data structs, as lists are.
Pattern matching allows selecting the right rule to apply.
The trivial way to do your task:
You have a list = [X|Xs], for each each element X, if is odd(X) return countOdds(Xs)+1 else return countOdds(Xs).
countOdds([], 0).
countOdds([X|Xs], C) :-
odd(X),
!, % this cut is required, as rightly evidenced by Alexander Serebrenik
countOdds(Xs, Cs),
C is Cs + 1.
countOdds([_|Xs], Cs) :-
countOdds(Xs, Cs).
Note the if, is handled with a different rule with same pattern: when Prolog find a non odd element, it backtracks to the last rule.
ISO Prolog has syntax sugar for If Then Else, with that you can write
countOdds([], 0).
countOdds([X|Xs], C) :-
countOdds(Xs, Cs),
( odd(X)
-> C is Cs + 1
; C is Cs
).
In the first version, the recursive call follows the test odd(X), to avoid an useless visit of list'tail that should be repeated on backtracking.
edit Without the cut, we get multiple execution path, and so possibly incorrect results under 'all solution' predicates (findall, setof, etc...)
This last version put in evidence that the procedure isn't tail recursive. To get a tail recursive procedure add an accumulator:
countOdds(L, C) :- countOdds(L, 0, C).
countOdds([], A, A).
countOdds([X|Xs], A, Cs) :-
( odd(X)
-> A1 is A + 1
; A1 is A
),
countOdds(Xs, A1, Cs).