Counting similar facts in prolog - 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.

Related

How to count the predicates

I'm looking for a way to count the numbers of predicates.
Example:
%facts
has_subclass(thing,animal).
has_subclass(thing,tree).
has_subclass(thing,object).
% and I ask
count_has_subclass(thing,X).
% result
X = 3.
For facts like your example:
count_has_subclass(What, Count):-
findall(1, call(has_subclass(What, _)), L),
length(L, Count).
We can use findall/3 for this, and then use length/2 to obtain the length of the list:
count_has_subclass(What, N):-
findall(X, has_subclass(What, X), L),
length(L, N).
If it is however possible that has_subclass/2 yields the same values multiple times for a given key (like thing), then we can use for example sort/2 as a duplicate filter, like:
count_has_subclass(What, N):-
findall(X, has_subclass(What, X), L),
sort(L, S), %% remove duplicates
length(S, N).
Note that if What is a free variable, then you will count all yeilds of has_subclass(_, _). (optionally with a uniqness filter on the second parameter).
Using the standard setof/3 is a better option as it allows easy definition of a more general predicate that can enumerate solutions when the class argument is not bound. For example, assume the following database:
has_subclass(thing,animal).
has_subclass(thing,tree).
has_subclass(thing,object).
has_subclass(animal,cat).
has_subclass(animal,dog).
has_subclass(tree,pine).
has_subclass(tree,oak).
And the definition:
subclass_count(Class, Count) :-
setof(Subclass, has_subclass(Class, Subclass), Subclasses),
length(Subclasses, Count).
Sample call:
| ?- subclass_count(Class, Count).
Class = animal
Count = 2 ? ;
Class = thing
Count = 3 ? ;
Class = tree
Count = 2
yes
If you try instead one of the findall/3 solutions in the other answers, we get instead:
| ?- count_has_subclass(What, Count).
Count = 7
But note that this solution also have a sensible interpretation as returning the number of all existing subclasses when the class is not specified.
To build a list just to count solutions seems 'old style', but in traditional Prolog there is only the DB (assert/retract) alternative to overcome the 'stateless' nature of computations. Indeed findall/3 and friends builtins could be (naively) rewritten by means of assert/retract. But something have shown up since the early 80's ages :). I illustrate with SWI-Prolog, but - more or less naively - all of them could be implemented by assert/retract. Of course, most Prolog implementations have 'non logical' (or 'imperative', or 'impure') facilities to implement such basic task, without resorting to the heavyweight DB interface - like setarg/3, nb_setval/2 and others...
I digress... library(aggregate) should be shown first:
?- aggregate(count, T^has_subclass(thing,T), C).
C = 3.
This lib is well worth to study, does a lot more than - efficiently - counting...
Another, recent, addition is library(solution_sequences). It's not more efficient than setof/3 + length/2, guess, but interesting in its own. Counting is a bit more involved, and uses call_nth/2:
?- order_by([desc(C)],call_nth(has_subclass(thing,T),C)).
C = 3,
T = object ;
...
Some far simpler code of mine, based on nb_setarg/3 (and help from #false):
?- [carlo(snippets/lag)].
true.
?- integrate(count,has_subclass(thing,T),C).
C = 3.

How to make a list of pairs from facts in SWI-Prolog?

Assuming I have some facts like the following
person(jessica,19,usa).
person(james,18,uk).
person(eric,34,italy).
person(jake,24,france).
how can I create a predicate that creates a large list of pairs of all the names and their corresponding country like so:
?-filter(L).
L=[(jessica,usa),(james,uk),(eric,italy),(jake,france)]
The best solution is this one:
?- bagof((P,C), Age^person(P,Age,C), People).
People = [(jessica, usa), (james, uk), (eric, italy), (jake, france)].
This gives you the same result as findall/3, because findall/3 implicitly assumes existential quantification on all variables not present in the template ((P,C) is the template). In your case you only have one, the age variable. Notice what happens if you don't include that:
?- bagof((P,C), person(P,_,C), People).
People = [(james, uk)] ;
People = [(jessica, usa)] ;
People = [(jake, france)] ;
People = [(eric, italy)].
What happened here? The value of the second parameter was the same across each solution because we didn't inform bagof/3 that we didn't care what it was bound to or even if it was bound to just one thing. This property of bagof/3 and setof/3 (but not findall/3) sometimes turns out to be surprisingly useful, so I tend to prefer using bagof/3 over findall/3 if I only need to mark a variable or two.
It's more obvious if we add another person the same age to the database:
person(janet,18,australia).
?- bagof((P,C), person(P,Age,C), People).
Age = 18,
People = [(james, uk), (janet, australia)] .
?- bagof((P,C), person(P,_,C), People).
People = [(james, uk), (janet, australia)] ;
Assuming person/3 is ground and terminates, you can implement it without setof as:
notin(_, []).
notin(X, [Y|Ys]) :-
dif(X,Y),
notin(X,Ys).
lt_list(_, []).
lt_list(X, [Y|Ys]) :-
X #< Y,
lt_list(X,Ys).
f( [ Name-Location | Rest], Acc) :-
person(Name, _, Location),
lt_list( Name-Location, Acc ),
f(Rest, [Name-Location | Acc]).
f( [], Acc) :-
\+ (person(Name,_,Location), notin(Name-Location,Acc)).
When we query f, we get our solutions:
?- f(Xs,[]).
Xs = [jessica-usa, james-uk, jake-france, eric-italy] ;
false.
I used X-Y instead of (X,Y) for better readability. The predicate notin describes an element that is not contained in a list and lt_list describes an element that is smaller than anything in the list by the standard term order.
The idea is that the first rule generates persons that I have not seen yet. Using the term order makes sure that we don't generate all permutations of the list (try replacing lt_list by notin to see what happens). The second rule makes sure we only terminate if there are no more solutions to generate. Be aware that the rule contains negation, which can have some unwanted side-effects. Most of them are filtered out by only looking at ground terms, but I have not thought well, how bad the impact is in this solution.

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]]].

Do you really need to convert Truths to values in 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.

Resources