Question

This question is based on a previous question of mine.Here is the previous question. So as you can see I'm now able to get the score for every key I put in the question but now I need to find the biggest score and add it with the sum of all the other scores of the documents. For example if I do a query I want the scores to be added in a list. For example it could look like this scores[1,2,3,2,1] then I want to extract the max from this list which is 3 and add it to the sum of the list which is 1+2+3+2+1 = 9.

I can't make it work. Append only works with lists as far as I know. Can I add the Acc from

score([Tag|Tags], Acc, Count, document(Title,_)) :-
    (   sub_string(case_insensitive, Tag, Title)  % Check for Tag in Title
    ->  Acc1 is Acc + 1                           % Increment acc if found
    ;   Acc1 = Acc                                % Otherwise, no increment
    ),
    score(Tags, Acc1, Count, document(Title,_)).  % Score remaining tags

to a list using member? I tried it but I couldn't make it work...

Here is an example: This is my query

?- document(T,_),score([rule],Acc,document(T,_)).

and as a result I will get

T = 'Rules; Semantic Technology; and Cross-Industry Standards',Acc = 1;
T = 'Rule Transformation and Extraction',Acc = 1;
T = 'Rules and Uncertainty',Acc = 1;
T = 'Rules and Rules',Acc = 2;

and so on... I want each of these Acc to be added in a list and then I want to extract the max Acc of this list.

Était-ce utile?

La solution

library(aggregate) could be a good starting point, but to put it to good use I think you need to decouple the tasks, and use sub_atom/5 that actually can 'search' multiple occurrences:

tags_count(Tags, Title, Count) :-
    downcase_atom(Title, Downcase),
    aggregate_all(count, (member(T,Tags), sub_atom(Downcase, _,_,_, T)), Count).

counters(Tags, L) :-
    findall(C, (document(T,_), tags_count(Tags,T,C)), L).

test:

document('Rules; Semantic Technology; and Cross-Industry Standards',_).
document('Rule Transformation and Extraction',_).
document('Rules and Uncertainty',_).
document('Rules and Rules',_).

?- counters([rule], L), max_list(L, Max), sum_list(L, Sum), Tot is Sum + Max.
L = [1, 1, 1, 2],
Max = 2,
Sum = 5,
Tot = 7.

edit Really, all work is done 'inside' aggregate_all/3

tags_tot_max_title(Tags, Tot, Max, Title) :-
    aggregate_all(info(sum(C), max(C, T)), (
        document(T, _), tags_count(Tags, T, C)
    ), info(Sum, max(Max, Title))),
    Tot is Sum + Max.

yields

?- tags_tot_max_title([rule], Tot, Max, Title).
Tot = 7,
Max = 2,
Title = 'Rules and Rules'.

Autres conseils

If you have the following query:

document(T,_),score([rule],Acc,document(T,_))

And you want to collect results over multiple such queries, and sort them (and assuming unique elements), you can use setof:

setof(doc(Acc, T), ((document(T, _), score([rule], Acc, document(T, _)), Accs)

The list Accs will be a collection of pairs doc(Acc, T) sorted in ascending order of Acc. [N.B., Conveniently, setof is smart about sorting lists even when the elements are compound terms. So terms such as doc(X, Y) will sort in order of X first then Y using the @ comparitors.] If you reverse the list and take the head, you'll get the maximum Acc along with the corresponding T:

reverse(Accs, [doc(MaxAcc, MaxT)|_])

You can put that together into a predicate:

max_doc_acc(Tags, MaxAcc, Doc) :-
    setof(doc(Acc, T), ((document(T,_), score(Tags, Acc, document(T,_)), Accs),
    reverse(Accs, [doc(MaxAcc, Doc)|_]).

And then query something like:

max_doc_acc([rule], MaxAcc, Doc).
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top