Как вы можете добавлять элементы в список или вычислять их из базы знаний, не используя findall или assert/retract в Prolog?

У меня есть база знаний, которая состоит из базы данных студентов в файле 'Students.pl', как это:

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

Я хочу получить доступ к каждому предикату учащегося из базы знаний и рассчитать средние оценки по каждому предмету или средний процент без использования "findall" или утверждения / отвода. Я могу хотеть использовать возвратный путь как это:

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

При таком подходе я могу получить доступ к каждому элементу и написать его, но если я хочу добавить каждое значение "Percent" в качестве элемента в список или просто использовать предикат, например "Percent1 is Total + Percent", для суммирования значений процента, а затем найти в среднем, как я могу это сделать? Обратите внимание, что я не хочу использовать findall или retract/assert и желательно найти среднее значение за один проход через базу знаний, поскольку база знаний очень велика.

Любая помощь приветствуется.

2 ответа

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

Если вы хотите добавить в список, вам следует использовать findall или, что лучше, библиотеку ( агрегат). Но если вы боитесь эффективности, вы можете использовать что-то вроде этого

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(+, :, ?).

тестовое задание:

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

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

Конечно, вам нужно добавить обработку ошибок (по крайней мере, когда счетчик C == 0).

Другие вопросы по тегам