Prolog loops and conditional statements? - prolog

Is there anything in Prolog that works like a for loop and if then condition?

if/then/else can be obtained with (->)/2 and (;)/2:
( If ->
Then
; Else
)
Sometimes this is useful. In general though (when the condition contains variables), it will make your programs unsound and incomplete. Whenever it is possible to describe the conditions with pattern matching, you should use pattern matching instead. You can then not only check but also generate solutions.

If you are looking for such kinds of statements then you are not thinking in Prolog :)
Just kidding, by the way there aren't plain translation or for and if/else, but you can think about how they should be in prolog:
an if/else statement can be obtained by just having two rules that match over different conditions
a for loop can be done with two recursive rules, one is the base case and it doesn't depends upon itself to keepon while the other does what you intend to do inside the loop and follows itself..

Related

Prolog: Looping through elements of list A and comparing to members of list B

I'm trying to write Prolog logic for the first time, but I'm having trouble. I am to write logic that takes two lists and checks for like elements between the two. For example, consider the predicate similarity/2 :
?- similarity([2,4,5,6,8], [1,3,5,6,9]).
true.
?- similarity([1,2,3], [5,6,8]).
false.
The first query will return true as those two lists have 5 and 6 in common. The second returns false as there are no common elements between the two lists in that query.
I CANNOT use built in logic, such as member, disjoint, intersection, etc. I am thinking of iterating through the first list provided, and checking to see if it matches each element in the second list. Is this an efficient approach to this problem? I will appreciate any advice and help. Thank you so much.
Writing Prolog for the first time can be really daunting, since it is unlike many traditional programming languages that you will most likely encounter; however it is a very rewarding experience once you've got a grasp on this new style of programming! Since you mention that you are writing Prolog for the first time I'll give some general tips and tricks about writing Prolog, and then move onto some hints to your problem, and then provide what I believe to be a solution.
Think Recursively
You can think of every Prolog program that you write to be intrinsically recursive in nature. i.e. you can provide it with a series of "base-cases" which take the following form:
human(John). or wildling(Ygritte) In my opinion, these rules should always be the first ones that you write. Try to break down the problem into its simplest case and then work from there.
On the other hand, you can also provide it with more complex rules which will look something like this: contains(X, [H|T]):- contains(X, T) The key bit is that writing a rule like this is very much equivalent to writing a recursive function in say, Python. This rule does a lot of the heavy lifting in looking to see whether a value is contained in a list, but it isn't complete without a "base-case". A complete contains rule would actually be two rules put together: contains(X, [X|_]).
contains(X, [H|T]):-contains(X, T).
The big takeaway from this is to try and identify the simple cases of your problem, which can act like base cases in a recursive function, and then try to identify how you want to "recurse" and actually do work on the problem at hand.
Pattern Matching
Part of the great thing about Prolog is the pattern matching system that it has in place. You should 100% use this to your advantage whenever you can -- it is especially helpful when trying to do anything with lists. For example:
head(X, [X|T]).
Will evaluate to true when called thusly: head(1, [1, 2, 3]) because intrinsic in the rule is the matching of X. This sort of pattern matching on the first element of a list is incredibly important and really the key way that you will do any work on lists in Prolog. In my experience, pattern matching on the head of a list will often be one of the "base-cases" that I mentioned beforehand.
Understand The Flow of the Program
Another key component of how Prolog works is that it takes a "top-down" approach to reading code. What I mean by that is that every time a rule is called (except for definitions of the form king(James).), Prolog starts at line 1 and continues until it reaches a rule that is true or the end of the file. Therefore, the ordering of your rules is incredibly important. I'm assuming that you know that you can combine rules together via a comma to indicate logical AND, but what is maybe more subtle is that if you order one rule above another, it can act as a logical OR, simply because it will be evaluated before another rule, and can potentially cause the program to recurse.
Specific Example
Now that I've gotten all of my general advice out of the way, I'll actually reference the given problem. First, I'd write my "base-case". What would happen if you are given two lists whose first elements are the same? If the first element in each list is not the same, then they have to be different. So, you have to look through the second list to see if this element is contained anywhere in the rest of the list. What kind of rule would this produce? OR it could be the case that the first element of the first list is not contained within the second at all, in which case you have to advance once in the first list, and start again with the second list. What kind of rule would this produce?
In the end, I would say that your approach is the correct one to take, and I have provided my own solution below:
similarity([H|_], [H|_]).
similarity(H1|T1], [_|T2]):- similarity([H1|T1], T2).
similarity([_|T1], [H2|T2]):- similarity(T1, [H2|T2]).
Hope all of this helps in some way!

Prolog: How to tell if a predicate is deterministic or not

So from what I understand about deterministic predicates:
Deterministic predicate = 1 solution
Non-deterministic predicate = multiple solutions
Are there any type of rules as to how you can detect if the predicate is one or the other? Like looking at the search tree, etc.
There is no clear, generally accepted consensus about these notions. However, they are usually based rather on the observed answers and not based on the number of solutions. In certain contexts the notions are very implementation related. Non-determinate may mean: leaves a choice point open. And sometimes determinate means: never even creates a choice point.
Answers vs. solutions
To see the difference, consider the goal length(L, 1). How many solutions does it have? L = [a] is one, L = [23] another... but all of these solutions are compactly represented with a single answer substitution: L = [_] which thus contains infinitely many solutions.
In any case, in all implementations I know of, length(L, 1) is a determinate goal.
Now consider the goal repeat which has exactly one solution, but infinitely many answers. This goal is considered non-determinate.
In case you are interested in constraints, things become even more evolved. In library(clpfd), the goal X #> Y, Y #> X has no solution, but still one answer. Combine this with repeat: infinitely many answers and no solution.
Further, the goal append(Xs, Ys, []) has exactly one solution and also exactly one answer, nevertheless it is considered non-determinate in many implementations, since in those implementations it leaves a choice point open.
In an ideal implementation, there would be no answers without solutions (except false), and there would be non-determinism only when there is more than one answer. But then, all of this is mostly undecidable in the general case.
So, whenever you are using these notions make sure on what level things are meant. Rather explicitly say: multiple answers, multiple solutions, leaves no (unnecessary) choice point open.
You need understand the difference between det, semidet and undet, it is more than just number of solutions.
Because there is no loop control operator in Prolog, looping (not recursion) is constructed as a 'sequence generating' predicate (undet) followed by the loop body. Also you can store solutions with some of findall-group predicates as a list and loop later with the member/2 predicate.
So, any piece of your program is either part of loop construction or part of usual flow. So, there is a difference in designing det and undet predicates almost in the intended usage. If you can work with a sequence you always do undet and comment it as so. There is a nice unit-test extension in swi-prolog which can check wheter your predicate always the same in mean of det/semidet/undet (semidet is for usage the same way as undet but as a head of 'if' construction).
So, the difference is pre-design, and this question should not be arised with already existing predicates. It is a good practice always comment the intended usage in a comment like.
% member(?El, ?List) is undet.
Deterministic: Always succeeds with a single answer that is always the same for the same input. Think a of a static list of three items, and you tell your function to return value one. You will get the same answer every time. Additionally, arithmetic functions. 1 + 1 = 2. X + Y = Z.
Semi-deterministic: Succeeds with a single answer that is always the same for the same input, but it can fail. Think of a function that takes a list of numbers, and you ask your function if some number exists in the list. It either does, or it doesn't, based on the contents of the list given and the number asked.
Non-deterministic: Succeeds with a single answer, but can exhibit different behaviors on different runs, even for the same input. Think any kind of math.random(min,max) function like random/3
In essence, this is entirely separate from the concept of choice points, as choice points are a function of Prolog. Where I think the Prolog confusion of these terms comes from is that Prolog can find a single answer, then go back and try for another solution, and you have to use the cut operator ! to tell it that you want to discard your choice points explicitly.
This is very useful to know when working with Prolog Unit Testing

In PROLOG, How can I use assert recursively without getting 'true' result?

I'm planning to make new facts based on existing facts, by using assert.
However, the number of facts to be made will be more than 500, so that typing semicolon to go further steps become pretty tedious work.
thus I want to ignore or pass the 'true'(in the SWI PROLOG)
Are there any ways to deal with this?(ex. automatically pass all the 'true's...)
here's a part of my code
%initialize
initialize :-
discipline(X,Y),
assert(result(X,0)).
I have too many Xs in discipline(X,Y)..
maybe
?- forall(a_fact(F), your_fact_processing(F)).
In this specific case forall is actually preferred, but in general, in Prolog you have to rely on the language's mechanism for this kind of iteration. Here's an example for your case:
initialize:-
discipline(X,Y),
assert(result(X,0)),
fail.
initialize.
In this bit of code above, you are telling the interpreter that initialize should perform all the 'asserts' given possible disciplines through the backtracking mechanism. Unless you become really familiar with this, Prolog will never "click" for you.
Note that in this example initialize will never fail, even if there are no disciplines (and therefore no results) to assert. You'll need some extra work to detect edge-cases like that - which is why forall is actually preferred for this specific task of assertin many facts.
Also note that if it's good practice to not have singleton variables declared, you can use the notation where variables that you won't use start with the '_' (underscore) character.

Change comparator in prolog rbtree

I am using the swi-prolog rb_trees. The standard implementation uses "==" to compare values, I need to use "=#=", is there some way to do it?
If it is not possible I guess I would need to find some other representation for the clauses I store in the tree. The clauses have this format for example:
cl(daughter(X,Y), [female(X), parent(Y,X)])
I need the above clause to be equal to for example this clause:
cl(daughter(A,B), [female(A), parent(B,A)])
One function that gives the same output only for =#= clauses is portray_clause i guess. However it doesn't have an output argument, so I am not able to store the output of portray_clause into rb_tree.
Maybe you can use numbervars/3 on the clauses for storing them in the red-black tree and varnumbers/3 to get the original clause back? The predicate numbervars/3 will ground the clauses and maybe that will make the use of (==)/2 work for your case?
I don't think there's a way to change the predicate used for comparisons.
The best solution is probably to use ground terms as keys, since then the difference between == and =#= disappears. (In fact, using ground terms is a good idea anyway, since you don't want a variable binding that occurs in between tree operations to invalidate the tree's order property.)

What's the difference between Prolog rules and queries?

I'm new to logical programming and find it difficult to understand the difference between rules and queries, I feel they are basically the same. Any help to clarify this would be greatly appreciated.
Syntactically, they are largely the same; "p(1)." could be either a rule or a query, depending on where you put it.
Semantically, they are not. "p(1)." as a rule tells Prolog "p(1) is true". "p(1)." as a query asks Prolog "is p(1) true?".
A rule is a definition such as
foo(X) :- bar(X), baz(X).
as it appears in a Prolog program.
A query is either the right hand side of a definition like the above, i.e. (bar(X), baz(X)) or what you type at the Prolog interpreter prompt to get the program running.
A query is a statement you are asking to have proven (which in the process of doing so may instantiate variables, which can server as your "output"); rules make up the "program" used to develop that proof.
Your intuition is correct: they're both variations on a Horn clause. The basic structure of a Horn clause is:
head(...) :- body.
If you have a head without a body, you have a fact. If you have both, you have a predicate. If you have just a body, then you have a query.

Resources