2010-10-31 33 views
7

Tôi đang cố gắng thêm quy tắc động vào cơ sở kiến ​​thức bằng cách sử dụng SWI-prolog trong đó phần thân của quy tắc chưa được biết trước.Xác nhận quy tắc động trong SWI-prolog

Nguyên tắc mong muốn trông giống như sau:

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

Thông thường bạn chỉ cần nhà nước

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

nhưng vấn đề là các sự kiện được quyết định tại thời gian chạy (số lượng thực tế cũng không được biết trước khi xác nhận).

Đó là lý do tôi muốn biết liệu có một khả năng để khẳng định một nguyên tắc mà cơ thể bao gồm một danh sách các sự kiện như [thực tế (1), thực tế (2)]

Trả lời

4

Chúng tôi sẽ tạo quy tắc newrule(X) :- w,x,y,z(X).
Phần thân của quy tắc là một bộ túp, một cấu trúc ở dạng (w, x, y ...).

Đối với chiều dài cơ thể khác nhau, bắt đầu với không có cơ thể:

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

Nhà điều hành tuple là dấu phẩy (`, '), như trong ', '(a, b) == (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). 

-

Có hai danh sách. Danh sách kết quả đầu tiên từ số listing() được gọi trong số create_a_rule(). Danh sách thứ 2 là từ lệnh listing() tại dòng nguồn cuối cùng.

?- [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. 
+2

Cảm ơn bạn rất nhiều vì giải pháp hoàn hảo và rất phức tạp! – Tom

+0

@Tom: nếu câu trả lời là "hoàn hảo", tại sao bạn không * chấp nhận * nó? –

+0

Vị từ ['assert'] (http://www.swi-prolog.org/pldoc/man?predicate=assert/1) trong câu trả lời này không được chấp nhận trong SWI-Prolog. –

1

thay đổi đề nghị niêm yết frayser của:

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

Những khoản lọai trừ nhu cầu cho một ngoại lệ nếu biến đầu tiên là một danh sách rỗng: nó chỉ đơn giản là sẽ thất bại. Nó cũng có nghĩa là bạn sẽ không bao giờ đánh một khẳng định khi backtracking.

Tuy nhiên, bạn vẫn có thể sử dụng mệnh đề ngoại lệ tại chỗ, vì vậy bạn vẫn có thể đặt nó vào để bắt các trường hợp có sự hợp nhất cố gắng với []. (Tuy nhiên, nó sẽ không bị ảnh hưởng khi quay ngược lại.)

Các vấn đề liên quan