How can you add elements to a list or compute them from the knowledge base without using findall or assert/retract in Prolog?

StackOverflow https://stackoverflow.com/questions/14949537

Question

I have a knowledge base that consists of students database in a file 'students.pl' like this:

% student(Name,Percent,List_of_Marks_in_3_subjects).
student('abc',83,[80,80,90]).
student('pqr',70,[70,60,80]).
student('xyz',76,[80,70,80]).

I want to access each student predicate from the knowledge base and calculate the average marks in each subject or average percentage, without using 'findall' or assert/retract. I may want to use backtracking like this:

find_score_all(X) :- student(Name,Percent,L),
    write(Percent),nl,
    fail.
find_score_all(_).

With this approach I can access each element and write it, but if I want to add each 'Percent' value as an element to a list or just use a predicate like 'Percent1 is Total + Percent' to total the percent values and then find its average, how can I do so? Note that I dont want to use findall or retract/assert and preferably find the average in one pass through the knowledge base since the knowledge base is very large.

Any help is appreciated.

No correct solution

OTHER TIPS

%solution for sum of percents, you can replace with any other calculation sum_percent predicate.
listing(student/3, convert_to_list/2, sum_percent, sum_percent/2).

% student(Name,Percent,List_of_Marks_in_3_subjects).
student('abc',83,[80,80,90]).
student('pqr',70,[70,60,80]).
student('xyz',76,[80,70,80]).

convert_to_list(X, R):-
    student(N, P, LM),
    not(member(st(N, P, LM), X)),
    convert_to_list([st(N, P, LM)|X], R).

convert_to_list(X, X).

sum_percent:-
    convert_to_list([], X),
    sum_percent(X, S),
    write(S).

sum_percent([], 0).
sum_percent([st(_,E,_)|T], S):-
    sum_percent(T, S2),
    S is E+S2.

if you want to add to a list then you should use findall, or better, library(aggregate). But if you fear about efficiency, you could use something like this

integrate(ave, Goal, Ave) :-
    State = state(0, 0, _),
    repeat,
    (   call(Goal, V),
        arg(1, State, C), U is C+1, nb_setarg(1, State, U),
        arg(2, State, S), T is S+V, nb_setarg(2, State, T),
        fail
    ;   arg(1, State, C), arg(2, State, S), Ave is S/C
    ).

:- meta_predicate integrate(+, :, ?).

test:

members(X) :- member(X, [1,2,3,4]).

?- integrate(ave, members, R).
R = 2.5 .

Of course, you'll need to add error handling (at least, when counter C == 0).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top