Как вы можете добавлять элементы в список или вычислять их из базы знаний, не используя 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(_).

При таком подходе я могу получить доступ к каждому элементу и записать его, но если я хочу добавить каждое значение «Процент» в качестве элемента в список или просто использовать предикат, например «Процент1 - это общее + процент», чтобы суммировать процентные значения, а затем найти это среднее, как я могу это сделать? Обратите внимание, что я не хочу использовать findall или retract/assert и предпочтительно нахожу среднее значение за один проход через базу знаний, поскольку база знаний очень велика.

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


person shujin    schedule 19.02.2013    source источник
comment
Вы описываете цикл, управляемый сбоем, но такие циклы не могут передавать информацию от итерации к итерации, кроме как через утверждение/ретракт (если вы не используете расширение, такое как библиотека глобальных переменных SWI). Почему вам запрещено использовать стандартные практики?   -  person Daniel Lyons    schedule 19.02.2013
comment
Можете ли вы добавить числовой идентификатор от 1 до N к каждому студенческому факту в базе данных?   -  person Sergii Dymchenko    schedule 19.02.2013
comment
@ j4n-bur53 В этом ответе по ссылке используется утверждение. В этом вопросе говорится, что в теме не следует использовать findall или assert.   -  person shujin    schedule 01.07.2016
comment
@ j4n-bur53 Этот вопрос [ссылка] (stackoverflow.com/questions/7647758/) ответы используют поиск и выполняют проход по всей базе знаний для каждого поиска, что отличается от этого случая.   -  person shujin    schedule 01.07.2016
comment
Возможно, вы ожидаете решения потока. stackoverflow.com/a/38152802/502187 Следует ожидать, что в будущих реализациях систем Prolog эти потоки получат более широкое распространение. а также дешевле по скорости и памяти.   -  person Mostowski Collapse    schedule 01.07.2016


Ответы (1)


если вы хотите добавить в список, вам следует использовать 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).

person CapelliC    schedule 19.02.2013