Динамическое утверждение правил в SWI-прологе - PullRequest
7 голосов
/ 01 ноября 2010

Я пытаюсь динамически добавить правило в базу знаний, используя SWI-пролог, где тело правила заранее неизвестно.

Желаемое правило выглядит примерно так:

rule(a) :- fact(1), fact(2).

Обычно вы просто указали бы

assert((rule(a):-fact(1),fact(2))).

, но проблема в том, что факты решаются во время выполнения (число фактов также неизвестно до утверждения).

Вот почему я хотел быхотелось бы узнать, есть ли возможность утверждать правило, в котором тело состоит из списка фактов, таких как [факт (1), факт (2)]

Ответы [ 2 ]

5 голосов
/ 04 ноября 2010

Мы собираемся создать правило newrule(X) :- w,x,y,z(X).
Тело правила - это кортеж, конструкция в виде (w, x, y ...).

Для разных длин тела, начиная с без тела:

assert(goal).  
assert(goal:-cond).  
assert(goal:-(cond1,cond2)).

Оператор кортежа - запятая (`, '), как в ', '(a, b) ==(а, б) .

%%%%
%%%% Name: runtime.pl -- Runtime rule insertion.
%%%%
create_a_rule :- 
    Cond=[w,x,y,z(X)],
    Head=newrule(X),
    list_to_tuple(Cond,Body),
    dynamic(Head),
    assert(Head :- Body),
    listing(Head).

/*
This is a [l,i,s,t], and this is a (t,u,p,l,e).  
Convertng list to tuple:  
[]    -> undefined  
[x]   -> (x) == x  
[x,y] -> (x,y).  
[x,y,z..whatever] = (x,y,z..whatever)  
*/

list_to_tuple([],_) :- 
    ValidDomain='[x|xs]',
    Culprit='[]',
    Formal=domain_error(ValidDomain, Culprit),
    Context=context('list_to_tuple','Cannot create empty tuple!'),
    throw(error(Formal,Context)).

list_to_tuple([X],X).

list_to_tuple([H|T],(H,Rest_Tuple)) :-
    list_to_tuple(T,Rest_Tuple).

:- create_a_rule.
:- listing(newrule).

-

Есть два объявления.Первый листинг является результатом вызова listing() в create_a_rule().Второй листинг взят из команды listing() в последней строке источника.

?- [runtime].
:- dynamic newrule/1.

newrule(A) :-
    w,
    x,
    y,
    z(A).

:- dynamic newrule/1.

newrule(A) :-
    w,
    x,
    y,
    z(A).

% runtime compiled 0.01 sec, 1,448 bytes
true.
1 голос
/ 21 октября 2013

Предлагаемое изменение списка фрейзера:

list_to_tuple([X],X).

list_to_tuple([A,B],(A,B)).

list_to_tuple([A,B|T],(A,B,Rest_Tuple)) :-
    list_to_tuple(T,Rest_Tuple).

Эти пункты исключают необходимость исключения, если первая переменная является пустым списком: она просто потерпит неудачу.Это также означает, что вы никогда не нажмете assert при возврате.

Тем не менее, вы, тем не менее, можете ХОТИТЬ положение об исключении на месте, поэтому вы все равно можете использовать его для отлова случаев, когда была предпринята попытка объединения с [],(Впрочем, при возврате не ударится.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...