Many Prolog systems have a freeze/2 predicate, a predicate
that should possibly have the name geler/2 since it was
even invented before Prolog-II.
Assume I have a condition on the same variable, but two
different goals, i.e.:
?- freeze(X, G1), freeze(X, G2), X=1.
What is the preferred wake-up strategy, is G1 first executed
or is G2 first executed? What if G1 and G2 do spawn new
freezes, which are also woken up:
G1 :- freeze(Y, G3), Y=1.
G2 :- freeze(Z, G4), Z=1.
Is G3 or G4 always executed in-between G1 and G2, or could it be
that G3 or G4 is executed after G1 and G2, or even any time later?
Bye
It depends a little bit how freeze/2 is implemented under the hood. The two main types of attribute variable interfaces that can come into play are type 1 and type 2 with respect to wake-up. Namely:
Type 1: Post-Unify
The wake-up would happen after X is instantiated and the current goal succeeded, before the next goal is called. With this type the frozen goal would see any instantiations but the execution is not immediate and not always.
Type 2: Pre-Unify
The wake-up would happen before X is instantiated during unification. A pre-unify doesn't make any sense for freeze/2, since then the frozen goal wouldn't see any instantiation.
In the above example the goal that succeeds is X=1, and the next goal is the pseudo goal of the end of the query. The woken-up goals, read off from the attribute value of the variable, are pushed on a list so that they are available for this next goal.
Lets see whether this list is a FIFO:
SWI-Prolog:
?- freeze(X, write('ha ')), freeze(X, write('tschi ')), X=1, nl.
ha tschi
X = 1.
?- freeze(X, write('ha ')), freeze(X, write('tschi ')), (X=1; X=2), nl.
ha tschi
X = 1 ;
ha tschi
X = 2.
Jekejeke Prolog with Minlog Extension:
?- use_module(library(term/suspend)).
% 5 consults and 0 unloads in 90 ms.
Yes
?- freeze(X, write('ha ')), freeze(X, write('tschi ')), X=1, nl.
ha tschi
X = 1
?- freeze(X, write('ha ')), freeze(X, write('tschi ')), (X=1; X=2), nl.
ha tschi
X = 1 ;
ha tschi
X = 2
So the list is a FIFO. So freezing and immediately waking up,
gives left to right execution in the above two Prolog systems. From this one can also deduce what would happen if the goals do further freezing and immediate wake up by themselves.
Related
I'm a very newbie to Prolog and I already need help. I looked up other similar questions but it didn't answer my question.
The problem is;
I have a list of mixed elements [Y, rat, gorilla, 30, mother(alex)]. I want to make a new list out of this with exclusively atoms.
So query should look like this.
?- atoms([Y, rat, gorilla, 30, mother(alex)], Result).
Result = [rat, gorilla].
I tried but I have no idea how to solve this. I think it should be recursive because it needs to check each item weather it's an atom or not.
atoms([], []).
atoms([H | T], Result) :-
atom(H),
append(H, [], Result).
What you want to do is called "filtering" and there is a ready-made "higher-level predicate" for this already. Why "higher level"? Because it doesn't deal in first-order "objects" only, but takes an executable goal that it calls.
Note that this is an eminently functional approach to programming and there is nothing wrong with that: fat chunks of a "logic program" are actually written in functional style. Here we go:
In SWI-Prolog, the predicate that filters is called include/3 or exclude/3.
% atoms/2 filters list Li into list Lo using the predicate atom/1
% This only works in direction Li-->Lo.
atoms(Li,Lo) :- include(atom,Li,Lo).
And a bit of unit test code:
:- begin_tests(filtering).
test("basic test", true(Result = [rat, gorilla])) :-
atoms([Y, rat, gorilla, 30, mother(alex)], Result).
:- end_tests(filtering).
And so:
?- run_tests.
% PL-Unit: filtering . done
% test passed
true.
It works.
Of course, you can always write your own atoms/2 using a recursive call (aka. using an inductive definition)
atoms_i([], []).
atoms_i([H|T], [H|Result]) :- % retain the H in the result list
atom(H), % the "guard" passes if H is atom
!, % then we commit to this branch
atoms_i(T, Result).
atoms_i([H|T], Result) :- % do not retain H in the result list
\+atom(H), % the "guard" passes if H is not atom
!, % then we commit to this branch
atoms_i(T, Result).
People will say that you can leave out the \+atom(H),! in the third clause for efficieny reasons. Although they are right, I find doing that extremely annoying as I prefer symmetry in the source code and cuts that can in principle be removed at a whim. Plus it's about time the compiler start doing some work to find that efficiency itself. It's 2020, not 1980.
Let's add a bit of unit test code:
:- begin_tests(filtering_i).
test("basic test", true(Result = [rat, gorilla])) :-
atoms_i([Y, rat, gorilla, 30, mother(alex)], Result).
:- end_tests(filtering_i).
And so:
?- run_tests.
% PL-Unit: filtering_i . done
% test passed
true.
Good.
I have a list of numbers in prolog. the numbers are already sorted.I want to check any of the numbers are not repeated and different between any two numbers is greater than one.How to check it. any idea. Thank you.
?- check([1,3,4]). %expectation
false.
?- check([2,5,7,10]). %expectation
true.
I assume list alreadeTry it...
check([_]).
check(L):-append([],[X1,X2|T],L),X1+1<X2,check([X2|T]).
Let me guess...
you are using SWI-Prolog, and
all numbers that your check/1 cares for are integers.
If so, read on!
Use clpfd!
:- use_module(library(clpfd)).
As you already might have guessed, there are a billions and billions of ways to implement the predicate check/1. In this answer we use a straight-forward, directly recursive approach:
check([]).
check([_]).
check([E0,E1|Es]) :-
E0+1 #< E1,
check([E1|Es]).
Sample queries:
?- check([1,3,4]).
false.
?- check([2,5,7,10]).
true ; % do not be bothered by the trailing `; false`
false. % `true ; false` is equivalent to `true`
Have you noticed the binary operator (#<)/2 in above definition of check/1?
It allows us to run general queries and get logically sound answers. Consider!
?- Xs = [1,A,B,C], check(Xs).
Xs = [1,A,B,C], A in 3..sup, A#=<B+ -2, B in 5..sup, B#=<C+ -2, C in 7..sup ;
false.
I want to create a predicate in Prolog which will check if a list A is a sublist of a list B. Moreover I do not want my program to consider an empty list as a subset of another one.
E.g. included_list([1,4],[1,2,3,4,5]).
true.
included_list([2,3],[1,2,3,4,5]).
true.
included_list([1,6],[1,2,3,4,5]).
false.
included_list([],[1,2,3,4,5]).
false.
and so on...
So, I have written the following code so far:
member(X,[X|Tail]).
member(X,[Head|Tail]):- member(X,Tail).
included_list([X],_).
included_list([Head|Tail],List):- member(Head,List), included_list(Tail,List).
But the above code seems to be wrong, because in one specific case it throws true, instead of throwing wrong. I wish I'd made it clear having presented the following screenshot:
As you might have noticed the fifth(5th) sentence gives true, instead of wrong. That is, when I write a sentence of the form:
included_list([x,y],[w,x,v,z]).
whereas only x is included in the second list(and not y) the program gives me true(and this is wrong).
In general, if the first argument of the first list is included in the second list then, no matter if the rest of the former are included in the latter, the program gives me true.
In any other case the program gives me the right result(true or false).
What do I do wrong?
I will be waiting for your answers!
Thank you in advance!
Your problem is the first clause of included_list/2. This:
included_list([X], _).
What does it mean? It means, "If the first argument is a list with one element, succeed, ignoring the second argument."
A short aside: if you would not ignore compiler warnings, you would have caught this mistake already. You should get a loud and clear "Singleton variable" warning, hinting that the code you have written does not do what you think it does.
What you actually mean is more along the lines of:
subset_list([X|Xs], Ys) :-
subset_list_1(Xs, X, Ys).
subset_list_1([], X, Ys) :-
member(X, Ys).
subset_list_1([X|Xs], X0, Ys) :-
member(X0, Ys),
subset_list_1(Xs, X, Ys).
But I don't know why you don't simply use the available subset/2, and simply add a requirement that the subset is not an empty list:
subset_list(Subset, List) :-
Subset = [_|_], % a list with at least one element
subset(Subset, List).
Despite what the documentation claims, the second argument to subset/2 does not have to be a true "set", but it does expect that both lists are ground (do not contain any free variables). You can see the source code here.
In this answer we let meta-predicate maplist/2 handle recursion and define:
all_included(Sub, Es) :-
same_length(Es, Xs),
Sub = [_|_], % minimum length: 1
append(_, Sub, Xs), % maximum length: as long as `Es`
maplist(list_member(Es), Sub).
Let's run the queries the OP gave!
First up, use-cases we expect to succeed:
?- member(Xs, [[1,4],[2,3],[2,3,5],[3,4]]), all_included(Xs, [1,2,3,4,5]).
Xs = [1,4]
; Xs = [2,3]
; Xs = [2,3,5]
; Xs = [3,4]
; false.
Next up, some use-cases we expect to fail:
?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.
?- all_included([3,5], [1,2,5]).
false.
How can I check if an element in the list is an empty list: [] ?
I've got the following:
display_degrees([A,B,C,D]):- write(B).
display_degrees([A,B,C,D]):- B==[], nl,write('has no degree'), nl, !.
When I enter in something like:
display_degrees([1,[],3,4]).
I just get: [] instead of 'has no degree'. Is my syntax wrong? Can I not add a clause to this predicate like this?
You're getting this behavior because proof search stops when a goal has succeeded. When you type
display_degrees([1,[],3,4]).
the first rule unifies, and it writes B. Since it was a success, it stops. You can ask Prolog to keep searching, and then it will find the second clause. In swipl, I get
?- [foo].
?- display_degrees([1,[],3,4]).
[]
true r % I type 'r' there
has no degree
true.
If you're just learning Prolog, I suggest you avoid the cut operator ! for some time. Also, doing IO is not the most intuitive thing. I would try some exercises with defining things like natural numbers and recursive functions. E.g., plus:
plus(z, X, X).
plus(s(X), Y, s(Z)) :- plus(X, Y, Z).
The problem with what you have is that the more general rule will fire first. You could switch the order:
display_degrees([A,[],C,D]) :- nl, write('has no degree'), nl, !.
display_degrees([A,B,C,D]) :- write(B).
I could just as well have written for the first predicate:
display_degrees([A,B,C,D]) :- B == [], nl, write('has no degree'), nl, !.
But the "shortcut" I show initially is more idiomatic for a Prolog predicate like this.
I kept the cut since you know you deterministically want one choice. The first rule will match if and only if the second list element is [].
| ?- display_degrees([1,[],3,4]).
has no degree
yes
| ?- display_degrees([1,2,3,4]).
2
yes
| ?-
By alignment I mean that the predicate takes in two lists, well three with the alignment list. And then check that every item in the alignment list is indeed an element in both the other lits. And there is a requirement about order, so that rules out just checking that every item in the alignment list is a member of both the other input lits. If I just check for member, a valid alignment would also be valid when reversed. Which of course is wrong.
Example:
?- mxAli([4,2,9,8],[1,9,5,2,3,8],A).
A=[2,8] or A=[9,8]
8,2 and 8,9 is not valid here.
At once when I think about how to actually check the order my head goes back too imperative language programming. Any input is much appreciated. But don't give the answer straight out, I want hints on what I should read about. (I need to say this, because I get so good help at this site that it's close too cheating if I don't point this out).
My idea is that I , or prolog, needs to continue its search after the index of it's current element. That would make the reverse alignment not valid?
Edit: It would have to continue the search, after the current element's index in both the lists. As in the example above, when it finds the 2, it starts the search for the next element at index 2 and at index 5. (First element being 1)
A naive way to check alignment would be to use append/3, i.e. something like:
append(_, [El | T1], L1),
append(_, [El | T2], L2),
...
where L1 and L2 are the given lists, and El is an element that they must share.
Later you can check if T1 and T2 align.
What follows is the complete solution:
align(L1, L2, [El | T]) :-
append(_, [El | T1], L1),
append(_, [El | T2], L2),
align(T1, T2, T).
align(_L1, _L2, []).
% Test, executed at consult time
:- align([4,2,9,8], [1,9,5,2,3,8], Alignment), writeln(Alignment), fail; true.
The test prints out:
[2, 8]
[2]
[9, 8]
[9]
[8]
[]
The key is not thinking algorithmically too much but going through cases where the predicate should be true.
Here I would consider the cases that the alignment list (3rd argument) is empty and that it is not empty. For the nonempty case describe what has to hold for the first element of the output list and use recursion for the rest of the list.