Do you really need to convert Truths to values in Prolog? - prolog

I wrote a bubble sort in Prolog (code below). It works but it smells. I'm quite new to prolog. Here's the problematic part:
% Problem: convert the true value to something
% I can actually use.
sorted_value(X,X) :- sorted(X).
sorted_value(X,[]) :- not(sorted(X)).
It's weird I need to use this function to convert a True value to something (in this case, []) and False to another thing in order to use them. Isn't there a cleaner way?
% Bubble Sort a list.
% is the list sorted?
sorted([]).
sorted([Head|[]]).
sorted([First|[Second|Rest]]) :-
min(First,Second,First),
sorted([Second|Rest]).
% swap all pairs in the list that
% needs to be swapped
bubble_sort_list([], []).
bubble_sort_list([Head|[]],[Head]).
bubble_sort_list([First|[Second|Rest]], [One|Solution]) :-
min(First,Second, One),
max(First,Second,Two),
bubble_sort_list([Two|Rest],Solution).
% Problem: convert the true value to something
% I can actually use.
sorted_value(X,X) :- sorted(X).
sorted_value(X,[]) :- not(sorted(X)).
% Repeatedly call bubble_sort until
% the list is sorted
bubble_sort_helper([],List, Solution) :-
bubble_sort_list(List, SortedList),
sorted_value(SortedList, Value),
bubble_sort_helper(Value,SortedList, Solution).
bubble_sort_helper(A,List,List).
% this is what you call.
buuble_sort(List,Solution) :-
bubble_sort_helper([],List,Solution).

Every predicate call either succeeds (possibly several times) or fails. If you think declaratively and really describe what a sorted list is, there would only rarely seem to be a need to explicitly represent the truth value itself in a program. Rather, it would typically suffice to place a predicate call like "ascending(List)" in a Prolog program to describe the case of a sorted list. There seems to be no advantage to instead call a predicate like "ascending(List, T)" and then use T to distinguish the cases. Why not use the implicit truth value of the predicate itself directly? If you really need to reify the truth value, you can for example do it like this to avoid calling ascending/1 twice:
ascending(Ls, T) :-
( ascending(Ls) -> T = true
; T = false
).
Notice how the truth of ascending/1 is used to distinguish the cases.

Related

Repeat and Double elements in lists in Prolog

how can I write two predicates that are described below.
1) Define the double(X,Y) predicate, which is true if the list Y contains each of the elements X
repeated twice. Example: double([a,b],[a,a,b,b]) is true.
2) Define the predicate repeat(X,Y,N), which is true if the list Y contains each of the elements X
repeated N times. For example, for the question repeat([a,b],[a,a,a,b,b,b],3), Prolog answers true.
Could you give me the example of those predicates?
If you have repeat/3 you have double/2.
and thus:
multiple(X,N,R) :-
length(R,N),maplist(=(X),R).
repeat(Li,Lo,N) :-
maplist({N}/[Xi,Xo]>>multiple(Xi,N,Xo),Li,Nested),flatten(Nested,Lo).
But it doesn't run backwards due to the flatten/2 I think. Can that be improved?
double([], []).
double([X|Y], [X,X|Z]) :- double(Y,Z).
remove_if_same(_,R,0,R):- !.
remove_if_same(X,[X|Y],N,R) :- Nm1 is N-1,remove_if_same(X,Y,Nm1,R).
repeat([],[],_).
repeat([X|Xr],Y,N) :- remove_if_same(X,Y,N,R), repeat(Xr,R,N).
How double works?
If you've got two empty lists, then that is true, there is nothing to double from the first argument.
Otherwise, you're taking the head from the first list, and 2 head elements from the second list. If all these are the same (so if all are X) you're checking with recursion rest of elements, so accordingly Y and Z. So you'll check once again if lists are empty and so on, and if on any of the steps sth is not possible you return false.
About the repeat predicate, it's quite similar in reasoning.
2 things that I should explain:
The ! mark will make that the command-line interface(like swipl) will not search for other results of the remove_if_same. It would work same if we pass it to the repeat.
remove_if_same statement uses the accumulator (the 4th argument) to return at the end of the search the list without N same elements.

List with if - plus and minus

I should create a list with integer.It should be ziga_arnitika(L,ML).Which take L list (+) integer and will return the list ML only (-) integer the even numbers of list L.
Warning:The X mod Y calculates X:Y.
Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]
i know for example with not list to use if but not with lists,what i did is..:
something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).
You want to compute a list with elements satisfying some properties from a given list. Lists in Prolog have a very simple representation. The empty list is represent by []. A non-empty list is a sequence of elements separated by a comma. E.g. [1,2,3]. Prolog also provides handy notation to split a list between its head (or first element) and its tail (a list with the remaining arguments):
?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].
Walking a list (from its first element to its last element) can be done easily using a simple recursive predicate. The trivial case is when a list is empty:
walk([]).
If a list is not empty, we move to the list tail:
walk([Head| Tail]) :- walk(Tail).
However, if you try this predicate definition in virtually any Prolog system, it will warn you that Head is a singleton variable. That means that the variable appears once in a predicate clause. You can solve the warning by replacing the variable Head with an anonymous variable (which we can interpret as "don't care" variable). Thus, currently we have:
walk([]).
walk([_| Tail]) :- walk(Tail).
We can try it with our example list:
?- walk([1,2,3]).
true.
Prolog being a relational language, what happens if we call the walk/1 predicate with a variable instead?
?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...
Now back to the original problem: constructing a list from elements of other list. We want to process each element of the input list and, if it satisfies some property, adding it to the output list. We need two arguments. The simple case (or base case) is again when the input list is empty:
process([], []).
The general case (or recursive case) will be:
process([Head| Tail], [Head| Tail2]) :-
property(Head),
process(Tail, Tail2).
assuming a predicate property/1 that is true when its argument satisfies some property. In your case, being a even, negative integer. But not all elements will satisfy the property. To handle that case, we need a third clause that will skip an element that doesn't satisfy the property:
process([Head| Tail], List) :-
\+ property(Head),
process(Tail, List).
The \+/1 predicate is Prolog standard negation predicate: it's true when its argument is false.
Let's try our process/2 predicate it by defining a property/1 predicate that is true if the argument is the integer zero:
property(0).
A sample call would then be:
?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false
We have successfully written a predicate that extracts all the zeros from a list. Note that our query have a single solution. If we type a ; to ask for the next solution at the prompt, the Prolog top-level interpreter will tell us that there are no more solutions (the exact printout depends on the chosen Prolog system; some will print e.g. no instead of falsebut the meaning is the same).
Can you now solve your original question by defining a suitable property/1 predicate?
Update
You can combine the two recursive clauses in one by writing for example:
process([Head| Tail], List) :-
( % condition
property(Head) ->
% then
List = [Head| Tail2],
process(Tail, Tail2)
; % else
process(Tail, List)
).
In this case, we use the Prolog standard if-then-else control construct. Note, however, that this construct does an implicit cut in the condition. I.e. we only take the first solution for the property/1 predicate and discard any other potential solutions. The use of this control construct also prevents using the process/2 predicate in reverse (e.g. calling it with an unbound first argument and a bound second argument) or using it to generate pairs of terms that satisfy the relation (e.g. calling it with both arguments unbound). These issues may or may not be significant depending on the property that you're using to filter the list and on the details of the practical problem that you're solving. More sophisticated alternatives are possible but out of scope for this introductory answer.

Check if all numbers in a list are different in prolog

I want to create a rule in prolog that checks if there's a repeated number in a list.
For example:
for [1,2,3,4] it will return true.
for [1,2,3,3] it will return false because the 3 is repeated
I came up with this rule but it doesn't work
Different([]).
Different([H|T]):-
Member(H,T),
Different(T).
Any ideas?
a compact definition could be
all_diff(L) :- \+ (select(X,L,R), memberchk(X,R)).
i.e. all elements are different if we can't peek one and find it in the rest...
edit
Let's (marginally) improve efficiency: it's useless to check if X is member of the prefix sublist, so:
all_diff(L) :- \+ (append(_,[X|R],L), memberchk(X,R)).
The simplest way to check that all list members are unique is to sort list and check that length of the sorted list is equal of length of the original list.
different(X) :-
sort(X, Sorted),
length(X, OriginalLength),
length(Sorted, SortedLength),
OriginalLength == SortedLength.
Your solution doesn't work because of wrong syntax (facts and predicates should not begin with a capital letter) and a logic error. List is unique if head H is not a member of a tail T of a list and tail T is unique:
different([]).
different([H|T]):-
\+member(H,T),
different(T).
If all numbers in that list are integers, and if your Prolog implementation offers clpfd, there's no need to write new predicates of your own---simply use the predefined predicate all_different/1!
:- use_module(library(clpfd)).
Sample use:
?- all_different([1,2,3,4]).
true.
?- all_different([1,2,3,3]).
false.
Very Simple Answer...
The code:
unique([]).
unique([_,[]]).
unique([H|T]):-not(member(H,T)),unique(T).
Tests:
?-unique([1,2,3,4]).
true.
?-unique([1,2,3,3]).
false.
?-unique([a,b,12,d]).
true
?-unique([a,b,a]).
false
A neat way I came up with is the following:
If all members of a list are different from each other, then if I tell prolog to choose all pairs (I,J) such that I,J are members of the list and also I is equal to J, then for each element in the list it will only be able to find one such pair, which is the element with itself.
Therefore, if we can put all such pairs in a list, then the length of this list should be of the same length of the original list.
Here's my prolog code:
all_diff(L) :-
findall((I,J), (member(I, L), member(J, L), I == J), List),
length(L, SupposedLength),
length(List, CheckThis),
SupposedLength == CheckThis.
The rule provided in the question is very close to a correct answer with minimal library usage. Here's a working version that required only one change, the addition of \+ in the third row:
uniqueList([]).
uniqueList([H|T]):-
\+(member(H,T)),
uniqueList(T).
Explanation of the code for Prolog beginners: The member(H,L) predicate checks if element H is a member of the list L. \+ is Prolog's negation function, so the above code amounts to:
uniqueList([H|T]) returns true if: (H doesn't have a copy in T) and uniqueList(T)
Whereas the code by the original asker didn't work because it amounted to:
uniqueList([H|T]) returns true if: (H has a copy in T) and uniqueList(T)
*I renamed Different() to uniqueList() because it reads better. Convention is to reserve capital letters for variables.
This isn't very efficient, but for each number you can check if it appears again later. Like so:
Different([H|T]):-
CheckSingle(H, [T]),
Different([T]).
Checksingle(_,[]).
Checksingle(Elem, [H, T]):-
Elem != H,
Checksingle(Elem, [T]).

ERROR: "Out of global stack" when processing Prolog list of pairs

In SWI-Prolog, I have a list whose elements are pairs of the form Key-ValuesList. For instance, one such list may look like:
[1-[a,b],2-[],3-[c]]
I would like to transform this list into a nested list of pairs of the form Key-[Value], where Value is an element in ValuesList. The above example would be transformed into:
[[1-[a],2-[],3-[c]], [1-[b],2-[],3-[c]]]
My current solution is the following:
% all_pairs_lists(+InputList, -OutputLists).
all_pairs_lists([], [[]]).
all_pairs_lists([Key-[]|Values], CP) :-
!,
findall([Key-[]|R], (all_pairs_lists(Values,RCP), member(R,RCP)), CP).
all_pairs_lists([Key-Value|Values], CP) :-
findall([Key-[V]|R], (all_pairs_lists(Values,RCP), member(V,Value), member(R,RCP)), CP).
Using this predicate, a call of the form
all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
Binds the variable OutputLists to the desired result mentioned above. While it appears correct, this implementation causes an "Out of global stack" error when InputList has very long lists as values.
Is there a less stack consuming approach to doing this? It would seem like quite a common operation for this type of data structure.
Well, to sum it up, you're doing it wrong.
In Prolog, when we want to express a relation instead of a function (several results possible instead of one), we don't use findall/3 and member/2 directly. We rather state what the relation is and then maybe once it's done if we need a list of results we use findall/3.
Here what it means is that we want to express the following relation:
Take a list of Key-Values and return a list of Key-[Value] where Value is a member of the Values list.
We could do so as follows:
% The base case: handle the empty list
a_pair_list([], []).
% The case where the Values list is empty, then the resulting [Value] is []
a_pair_list([Key-[]|List], [Key-[]|Result]) :-
a_pair_list(List, Result).
% The case where the Values list is not empty, then Value is a member of Values.
a_pair_list([Key-[Not|Empty]|List], [Key-[Value]|Result]) :-
member(Value, [Not|Empty]),
a_pair_list(List, Result).
Once this relation is expressed, we can already obtain all the info we wish:
?- a_pair_list([1-[a, b], 2-[], 3-[c]], Result).
Result = [1-[a], 2-[], 3-[c]] ;
Result = [1-[b], 2-[], 3-[c]] ;
false.
The desired list is now just a fairly straight-forward findall/3 call away:
all_pairs_lists(Input, Output) :-
findall(Result, a_pair_list(Input, Result), Output).
The important thing to remember is that it's way better to stay away from extra logical stuff: !/0, findall/3, etc... because it's often leading to less general programs and/or less correct ones. Here since we can express the relation stated above in a pure and clean way, we should. This way we can limit the annoying use of findall/3 at the strict minimum.
As #Mog already explained clearly what the problem could be, here a version (ab)using of the basic 'functional' builtin for list handling:
all_pairs_lists(I, O) :-
findall(U, maplist(pairs_lists, I, U), O).
pairs_lists(K-[], K-[]) :- !.
pairs_lists(K-L, K-[R]) :- member(R, L).
test:
?- all_pairs_lists([1-[a,b],2-[],3-[c]],OutputLists).
OutputLists = [[1-[a], 2-[], 3-[c]], [1-[b], 2-[], 3-[c]]].

Counting similar facts in prolog

I want to return true, if a fact (A) is declared only once in the Prolog database, return false otherwise. For instance, if we have:
class('Person').
class('Person').
isUniqueClass(A) :- %%% This part I don't know how to do
And I query isUniqueClass('Person'). I want to return false. However, if we have:
class('Person').
isUniqueClass('Person') :- %%% Again same thing goes here
And I query isUniqueClass('Person'). I want it to return true.
A shorter version of #twinterer answer, using pattern matching:
isUniqueClass(C) :-
findall(C, class(C), [_]).
edit: refinement
Instead of 'calling' the predicate, metaprogramming should be done using the appropriate builtins, i.e.
isUniqueClass(C) :-
findall(C, clause(class(C), true), [_]).
In this case it doesn't any difference, because a fact can't have side effects...
You can use findall/3 to retrieve a list of all instances, then check the length of the list with length/2. If the list has length 1, then the fact was unique.

Resources