Запись базы данных Пролога
У меня есть этот факторный предикат.
fact(0, 1).
fact(N, F) :- N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N.
Как изменить этот предикат таким образом, чтобы при каждом запросе результат расчета сохранялся в базе данных? Новые запросы должны использовать сохраненные результаты, если они доступны.
2 ответа
То, что вы ищете, обычно называется запоминанием, но в контексте Пролога называется табулированием. Удобно, что есть библиотека для этого, называемая таблингом для SWI Prolog.
:- use_module(library(tabling)).
:- table fact/2.
fact(0, 1).
fact(N, F) :- N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N.
Вы можете проверить, что памятка работает, запустив trace
до ваших звонков fact
, Обратите внимание, что два :-
Строки называются директивами и запускаются компилятором, поэтому запуск их в repl не будет работать.
редактировать
Если вы не хотите использовать библиотеку табулирования, вы можете сделать это с помощью asserta. Это вставит факт вверху базы данных, как если бы вы ввели его в файл самостоятельно.
fact(0, 1).
fact(N, F) :-
N > 0,
N1 is N-1,
fact(N1, F1),
F is F1 * N,
asserta(fact(N, F)).
Пролог сначала увидит новый предикат и будет использовать его вместо пересчета факториала. Еще раз, вы можете проверить это путем отслеживания.
Как сказал jcolemang, все, что вам нужно, это табулирование / запоминание. Хотя действительно есть библиотеки, которые являются рекомендуемым и эффективным (не только с точки зрения времени, но в основном с точки зрения производительности) способом, вполне понятно, что вы можете реализовать его самостоятельно.
Можно использовать assert для добавления динамических фактов в базу данных пролога, но вам нужно объявить их как таковые, имея :-dynamic(fact)
в файле, который позволит вам добавлять / удалять факты.
Тем не менее, это приводит к снижению производительности. Альтернативой может быть наличие справочной таблицы / кэша, которая будет сохраняться при вызовах. Словарь может храниться с использованием глобальных изменяемых переменных (yikes!), Которые более эффективны, чем динамические факты. Как всегда, неплохо бы минимизировать код, который напрямую использует переменные / побочные эффекты - в вашем факториальном примере вы могли бы просто иметь предикат-обертку, который выбирает словарь и возвращает его в конце вызова, например
factorial(N, F):-
get_global_dict(D),
real_factorial(N, F, D, DF),
store_global_dict(DF).