Checking all Members Of List - prolog

Let's say that I have the following list in my prolog:
L=[10,11,2,3,5]
Is there a way that we can check all the members of a list L to make sure that each member is less than 5?

We can make use of maplist/2 here. This is a predicate that:
maplist(:Goal, ?List)
True if Goal can successfully be applied on all elements of List. Arguments are reordered to gain performance as well as to make the predicate deterministic under normal circumstances.
So we can here check the elements with:
all_less_five(L) :-
maplist(>(5), L).
Here for every element x ∈ L, it will thus call >(5, x), or in inline form 5 > x. So if all these elements are less than five, the the all_less_five/1 predicate will succeed.
For example:
?- all_less_five([10,11,2,3,5]).
false.
?- all_less_five([2,3,5]).
false.
?- all_less_five([2,3]).
true.

Here goes another solution without using any built-in function:
all_less_five([]).
all_less_five([X|L]):-
X < 5,
all_less_five(L).
This solution uses the typical recursion over lists. The predicate stands true for the empty list, and then we only call the recursion over the tail if the head is less than five.
Here are some questions over the predicate:
?- all_less_five([10,11,2]).
false.
?- all_less_five([2,3,6,5]).
false.
?- all_less_five([1,2,3,4]).
true.
Now it should be easy to implement it to any given X. Try it!

Related

What does Prolog assert/1 do with the term it is passed?

I'm trying to understand what assert and retract do with the term they are passed. If I run the following:
?- assertz(item(first)).
true.
?- assertz(item(second)).
true.
?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.
?- retract(item(X)).
X = first ;
X = second ;
false.
retract/1 removes all of the items but my writeln/1 is never called, so it appears retract is not actually resolving the term it is passed. It looks like it is doing some special operation where it:
Unifies the term with only facts (i.e. rules with no tail) in the database
Retracts each one after applying the substitution from unification
Is this right? Or is something else happening here?
Said another way: If I write my own single argument rule, Prolog does not automatically unify item(X) with the database and iterate through all facts that are item/1. It just gives me item(X). How is retract doing its magic?
?- assertz((myRule(X) :- writeln(X))).
true.
? myRule(item(X)).
item(_2556)
true.
Answer with further clarification:
Based on the answer by User9213, it appears that the answer is "retract (but not assert!) has a funny behavior where it does a simple unification of its term before it does something to the database". I'm left wondering why other built-in functions that I've seen (like atom/1 and writeln/1) don't appear to do this. Maybe it is more common than I've experienced?
For consistency, it seems like retract should have required ground terms and if the user wanted to do something like my above example, they could have done this:
?- (item(X), retract(item(X))).
It all makes me think I'm missing something or maybe these built in functions were just inconsistently designed? Any clarification that would explain that would be great.
To add my voice to the chorus, yes, all these predicates (assert*, retract*) manipulate the Prolog database of facts and rules; they do not evaluate their arguments as if they were facts or rules. Yes, they just do "syntactic" unification between their argument and the facts and rules in the database.
Prolog is a homoiconic language. The program can be manipulated as if it was data; the data structures can be interpreted as if they were the program. Most importantly: whether a certain structure is data or program depends only on the context.
You seem to understand this, but for the next poor soul that stumbles across your question and this answer, here is a toy example to demonstrate.
There is a built-in predicate atom/1 that succeeds if its argument is, well, an atom:
?- atom(foo).
true.
?- atom(Bar). % Bar is a free variable, which is not an atom
false.
?- atom(atom(bar)). % atom(bar) is a compound term, which is not an atom
false.
But atom(bar) is just a compound term in the last query. It is a compound term with a functor atom/1. Its only argument is an atom. So if you now queried it:
?- atom(bar).
true.
There is also this really nice predicate called call. It makes it even easier to blur the lines between program and data. The following three queries are identical in meaning:
?- atom(bar).
true.
?- call(atom, bar).
true.
?- call(atom(bar)).
true.
In addition, you can dynamically (at run-time) create a data structure and evaluate it as program. Here is a naive implementation of call/2 that can evaluate predicates, provided a predicate name and a list of arguments. It constructs the compound term using "univ" and evaluates it by just placing it in a slot where a subgoal is supposed to be. I'll call it my_call/2 and I will add it to the database using assertz:
?- assertz((my_call(Name, Args) :- Goal =.. [Name|Args], Goal)).
true.
?- my_call(between, [1, 3, X]).
X = 1 ;
X = 2 ;
X = 3.
Do you see what is going on? (Note: it seems that call is a relatively new addition to Prolog. Before call was widely available, you had to do this trick if you wanted to meta-call predicates. I don't know this from experience, just educated guessing based on things I've read or heard and can't be bothered to cite right now.)
So, let's try that again. In reality things are more complicated, but very simplified:
A Prolog program is a set of predicates. Not ordered!
Each predicate is a list of clauses. It is a list because a predicate may have 0 or more clauses, and they have order.
A clause can be a fact or a rule.
A rule is a compound term with functor :-/2. Yes, this is right. To see what I mean:
?- assertz(:-(foo(X), between(1, 3, X))).
true.
?- listing(foo/1).
:- dynamic foo/1.
foo(A) :-
between(1, 3, A).
true.
This is just another way to write it. It is more conventional.
So indeed, these two are very different:
foo(X). % a fact
foo(X) :- between(1, 3, X). % a rule
You cannot unify the one with the other. This is why, if you want to retract foo(X) :- between(1, 3, X), you cannot just pass foo(X) as the argument to retract. Or, to complete your example:
?- assertz(item(first)).
true.
?- assertz(item(second)).
true.
?- assertz((item(Y) :- =(Y, third), writeln(Y))).
true.
?- retract(item(X)).
X = first ;
X = second ;
false.
?- retract((item(X) :- X = Y, writeln(X))).
Y = third.
Do you see it now?
I had a vague memory of there being a retractall/1 that lives alongside retract/1 and it turns out the reason for it is situations like this. retract/1 accepts a Prolog term, as the documentation states:
retract(+Term)
When Term is an atom or a term it is unified with the first unifying fact or clause in the database. The fact or clause is removed from the database.
Emphasis added by me.
This is illustrated by the following:
?- asserta(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
X = 2 ;
X = 4.
?- retract(foo(X)).
false.
?- foo(X).
X = 2 ;
X = 4.
?- retract(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
false.
Note that if you furnish the complete clause you gave to asserta/1, it will be retracted. As #CapelliC points out below, you can also furnish a clause with a variable as a parameter to retract things with bodies:
retract(foo(X) :- Y).
However, if you do want to retract things that match a pattern, you can use retractall/1, which the documentation states:
retractall(+Head)
All facts or clauses in the database for which the head unifies with Head are removed.
This is illustrated by the following:
?- asserta(foo(X) :- X = 2 ; X = 4).
true.
?- foo(X).
X = 2 ;
X = 4.
?- retractall(foo(X)).
true.
?- foo(X).
false.
Another important difference between these two is that retract/1 will remove one thing at a time, and it will unify those things:
?- asserta(foo(X) :- X = 2).
true.
?- asserta(foo(X) :- X = 4).
true.
?- retract(foo(X) :- Y).
Y = (X=4) ;
Y = (X=2) .
This is in contrast to retractall/1 which will remove everything that matches the pattern, without unifying anything:
?- asserta(foo(X) :- X=2).
true.
?- asserta(foo(X) :- X=4).
true.
?- foo(X).
X = 4 ;
X = 2.
?- retractall(foo(X)).
true.
?- foo(X).
false.
So, retract/1 is really for doing one-at-a-time retractions but expects something shaped like the term you asserted, whereas retractall/1 only wants a head, treats it as a pattern, and will remove as many things as match the pattern.
This certainly helped me improve my understanding of Prolog, so I hope it helps you as well!
The definition of assert in swi-prolog is:
Assert a clause (fact or rule) into the database. The predicate asserta/1 asserts the clause as first clause of the predicate while assertz/1 assert the clause as last clause. The deprecated assert/1 is equivalent to assertz/1. If the program space for the target module is limited (see set_module/1), asserta/1 can raise a resource_error(program_space) exception. The example below adds two facts and a rule. Note the double parentheses around the rule.
Hence, it does not call or infer anything! It's just an assertion for the fact and the rule into the active memory.

Prolog and List Unification

I'm trying to further my understanding of Prolog, and how it handles unification. In this case, how it handles unification with lists.
This is my knowledgebase;
member(X, [X|_]).
member(X, [_|T]):- member(X, T).
If I'm understanding the process correctly. If member(X, [X|_]) is not true, then it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
So what happens to the anonymous variable in my recursive predicate? Does it get discarded? I'm having difficulty understanding the exact unification process with lists, as [_|T] is two variables, rather than one. I'm just trying to figure out how the unification process works precisely with lists.
Assume that _ is Y
member(X, [Y|T]):- member(X, T).
Then this is True regardless Y. Now you are "returning" member(X, T). In other words, you are discarding Y and "returning" member(X, T).
_ means, whatever it is, ignore that variable.
The _ is just like any other variable, except that each one you see is
treated as a different variable and Prolog won't show you what it
unifies with. There's no special behavior there; if it confuses you
about the behavior, just invent a completely new variable and put it
in there to see what it does.
In your case, your function check if a given element exists on a list, so, you take first element of the list, check if is equal, if not, you discard that element and moves on.
I think your primary question of how lists are represented as variables has been adequately answered, but I sense there are some other aspects to Prolog that need clarification.
To understand Prolog predicates and clauses, it's a good idea not to think of them as "functions" that "return" things, even metaphorically. It can lead you down the dark path of imperative thinking in Prolog. :)
In considering the predicate:
(1) member(X, [X|_]).
(2) member(X, [_|T]) :- member(X, T).
Think of member/2 as a relation which describes when element X is a member of the list L, and the clauses are the rules for determining when it is true.
I'll assume that you already know about how lists are represented in Prolog based upon other answers (e.g., Will Ness' detailed answer).
The first clause says:
(1) X is a member of [X|_] regardless of what the tail of the list [X|_] is
In that notation, the variable _ represents the tail of list [X|_] and X represents the first element of that list. It's trivially true that X is a member of this list, so member(X, [X|_]). is a fact. It's true regardless of what the tail of the list is, so we just use _ (an anonymous variable) since this rule doesn't need the information. Prolog doesn't technically "throw the value away" but the programmer throws it away because the programmer isn't using it. If we had, instead, said, member(X, [X|T]). that would work fine, but we're not using T. Prolog might instantiate it, but it wouldn't be used. It's like assigning x = 3 in C but not using it's value. In this case, Prolog will indicate a warning about a "singleton" variable. Watch for those, because it often means you misspelled something or forgot something. :)
The next rule is recursive. It says:
(2) X is a member of list [_|T] if X is a member of the tail (T) of that list, regardless of what the first element of the list is
Here we're considering the less trivial case where the first element in the list may not be a match to X, so the truth value of member(X, L) depends, in this rule, upon the truth value of member(X, T) where T is the tail (everything but the first element) of L. The rule does not unify member(X, [_|T]) with member(X, T), so it does not unify T with [_|T] as you might suppose. The :- operator defines a rule or implication (note the if in the rule description). [N.B., If you were to unify these terms, it would be done with with the unification operator, =/2: member(X, [_|T]) = member(X, T)].
On the recursive query member(X, T), Prolog goes back to the top, the first rule, and attempts to unify the first argument X with the head of the second argument (which is the original list minus its first element, or head) and, if it doesn't match, goes to rule #2 again, continually checking the tail as well, until it can unify. If it gets to the point where the tail is empty ([]) and hasn't been able to unify X with any elements, the predicate fails because there are no facts or rules that match member(X, []). However, if it does unify X with an element, it succeeds (it does not "return a value* in the sense that a function would in other languages) and reveals the values of any variables it instantiated in the arguments in the process, or simply will succeed if all the arguments passed are already instantiated. If there are more rules to check after succeeding (there was what's called a choice point), it will (if you tell it to) go back and check for more solutions and, if it finds them, display them as well. Or display no or false if there are no more.
Looking at an example query, is b a member of [a,b,c]?
member(b, [a,b,c]).
Prolog will first try to unify the query with a fact or the head of a predicate. The first one it finds is:
member(X, [X|_]).
In attempting to unify, X = b, but [a,b,c] (or, [a|[b,c]] in the head-tail notation) doesn't unify with [b|_](note the head elementsaandb` mismatch). Prolog then moves on to the next clause:
member(X, [_|T]) :- member(X, T).
In unifying member(b, [a,b,c]) with the head, it comes up with:
member(b, [_|[b,c]]) :- member(b, [b,c]).
It now has the recursive query to chase down: member(b, [b,c]). Since it's a new query, it starts at the top again and attempts to unify this with member(X, [X|_]). Now, it's successful, because member(b, [b,c]) (or, member(b, [b|[c]])) matches this pattern: member(b, [b|_]).
Therefore, the member(b, [a,b,c]). succeeds and Prolog will return "true". However, it's not done yet because it left what's called a choice point. Even though it matched member(b, [b,c]) with the first clause, it will still want to go back and find more cases that make it succeed, and there's still another clause to pursue. So, Prolog will go back and try member(b, [b,c]) against the second clause, matching member(b, [b|[c]]) to member(b, [_|[c]]) and doing another recursive query, member(b, [c]) and so on until it ultimately fails to find another solution. This is why the query looks something like this:
| ?- member(b, [a,b,c]).
true ? ;
no
| ?-
It first succeeds, but then we ask for more (with ;) and it then fails (no). This confuses some Prolog beginners, but it's because we've asked Prolog to get another solution, and it said there are none.
Because Prolog continues to try to find solutions (upon request), you can also use a variable in the query:
member(E, [a,b,c]).
This query runs the same way as the prior example, but now I have a variable as the first argument. Prolog will successfully match this to the first clause: member(E, [a,b,c]) unifies with member(X, [X|_]) via E = a. So you'll see something like:
| ?- member(E, [a,b,c]).
E = a ?
If we now ask for more solutions with ;, Prolog goes back and attempts the second clause, unifying member(E, [a|[b,c]]) with member(X, [_|T]) yielding _ = a (which is ignored in the predicate) and T = [b,c]. It then recursively queries, member(E, [b,c]) and, since it's a new query, goes back to the top and matches member(X, [X|_]) again, this time with E = b. So we see:
| ?- member(E, [a,b,c]).
E = a ? ;
E = b ?
And so on. member(E, [a,b,c]) will find all the values of E which make member(E, [a,b,c]) true and then finally fail after exhausting all the elements of [a,b,c]).
[A|B] represents a list where A is the Head element and B is the whole rest list.
So to explain you the algorithm shortly:
Clause: If X is the first element of the list the predicate succeeds.
Clause: If that's not the case, we try to find X in the tail of the list. Therefore, we call member recursively but instead of passing the whole list we now pass the list EXCEPT the head element. In other words, we walk through the list step by step always looking at the head element first. If that is not our element, we dig further.
Think of the anonymous variable _ just as a variable you do not need later. The algorithm would also work, if you replaced _ by a capital letter, however it would give you a warning that you named a variable that you never use.
A list is just a compound term with the '.' functor:
1 ?- [_|T] = .(_,T).
true.
2 ?- [_|T] =.. X.
X = ['.', _G2393, T].
The usual process of structural unification of compound terms apply:
3 ?- [A|T] = .(B,R).
A = B,
T = R.
[A|T] is really .(A,T) so the functors (.) and the arities (both terms are binary, of arity 2) match, so the respective constituents are matched as well.
Yes, the anonymous variable _ is ignored for the purposes of reporting the unification results. Otherwise it is just a fresh uniquely named variable.
it moves into the recursive rule, and if X is in list T, then [_|T] is unified with T.
Not quite. The unification happens before the "moving on", as part of the clause selection. To unify a list L with [_|T] is to select its "tail" and have T referring to it. E.g.
4 ?- L = [1,2,3], L = [_|T].
L = [1, 2, 3],
T = [2, 3].
(_ is 1 but is not reported).

What exactly is member(b,X)?

Today I came across this query:
?- member(b,X).
The program was:
member(X,[X|_]).
member(X,[_|T]) :-
member(X,T),
!.
When I ran the query, I got these answers:
?- member(b,X).
X = [b|_G1560] ;
X = [_G1559, b|_G1563].
What exactly is that? What does this query do?
The query member(b,X) generates lists containing b. As the second argument is not instantiated, you have a (theoretically) infinite number of solutions. The first solution will have b in the first position, the second solution will have b in the second position and so on. Moreover, if you look closely to any of the solutions, you see that it represents any list with a b on that position. For example, the first solution is [b| _]. As the list tail is not instantiated (see the member/2 predicate base case), this solution unifies with any list with b in the head position.
If you want to make the member/2 deterministic, i.e. if you want to use the predicate only to check if a term is a member of a list, you will need to add a cut in the base clause, not in the recursive clause as #false noted:
member(Head, [Head| _]) :-
!.
member(Head, [_| Tail]) :-
member(Head, Tail).
The resulting predicate is usually named memberchk/2 and available as such as a library predicate.

Check If Everything In Head Is Less Than Tail

Given a list containing sublists [[1].[2],[3]] how would I check to see if HEAD of the first sublist in the list is less than the rest of the HEADS of the other sublists?
Comparison of Standard Order of Terms in ISO-Prolog can be applied - recursively - to arbitrary complex structures.
Then your problem could be solved with something like
first_head_is_less([H|R]) :- maplist(#<(H), R).
test:
?- first_head_is_less([[1],[2],[3]]).
true.
?- first_head_is_less([[10],[2],[3]]).
false.
edit the code above must be refined, because it fail (for instance) on this:
?- first_head_is_less([[1,2],[1,3],[3]]).
true.
which is incorrect. Here a stricter test:
first_head_is_less([H|R]) :-
maplist(head_is_less(H), R).
head_is_less([F|_], [E|_]) :- F #< E.

Predicate that succeeds if two or more results are returned

How to implement rule1 that succeeds iff rule2 returns two or more results?
rule1(X) :-
rule2(X, _).
How can I count the results, and then set a minimum for when to succeed?
How can I count the results, and then set a minimum for when it's true?
It is not clear what you mean by results. So I will make some guesses. A result might be:
A solution. For example, the goal member(X,[1,2,1]) has two solutions. Not three. In this case consider using either setof/3 or a similar predicate. In any case, you should first understand setof/3 before addressing the problem you have.
An answer. The goal member(X,[1,2,1]) has three answers. The goal member(X,[Y,Z]) has two answers, but infinitely many solutions.
So if you want to ensure that there are at least a certain number of answers, define:
at_least(Goal, N) :-
\+ \+ call_nth(Goal, N).
with call_nth/2 defined in another SO-answer.
Note that the other SO-answers are not correct: They either do not terminate or produce unexpected instantiations.
you can use library(aggregate) to count solutions
:- use_module(library(aggregate)).
% it's useful to declare this for modularization
:- meta_predicate at_least(0, +).
at_least(Predicate, Minimum) :-
aggregate_all(count, Predicate, N),
N >= Minimum.
example:
?- at_least(member(_,[1,2,3]),3).
true.
?- at_least(member(_,[1,2,3]),4).
false.
edit here is a more efficient way, using SWI-Prolog facilities for global variables
at_least(P, N) :-
nb_setval(at_least, 0),
P,
nb_getval(at_least, C),
S is C + 1,
( S >= N, ! ; nb_setval(at_least, S), fail ).
with this definition, P is called just N times. (I introduce a service predicate m/2 that displays what it returns)
m(X, L) :- member(X, L), writeln(x:X).
?- at_least(m(X,[1,2,3]),2).
x:1
x:2
X = 2.
edit accounting for #false comment, I tried
?- call_nth(m(X,[1,2,3]),2).
x:1
x:2
X = 2 ;
x:3
false.
with call_nth from here.
From the practical point of view, I think nb_setval (vs nb_setarg) suffers the usual tradeoffs between global and local variables. I.e. for some task could be handly to know what's the limit hit to accept the condition. If this is not required, nb_setarg it's more clean.
Bottom line: the better way to do would clearly be using call_nth, with the 'trick' of double negation solving the undue variable instantiation.

Resources