假设您输入了图表的描述,例如“A就在B附近”,您想要更新您的知识库。
使用Prolog我决定使用这个解决方案:
:- dynamic edge/2.
store(Desc):- Desc=[A,is,near,B],
assert(edge(A,B)),
write(A-B).
store(Desc):- Desc=[A,is,near,B,that,is,near,C],
write(A-B),nl,
write(B-C),
assert(edge(A,B)),
assert(edge(B,C)).
我想将解析扩展到潜在的无限句,例如: '1接近2,接近3接近4等', 所以我想做的就是(用伪代码符号表达的想法):
procedure store(Sentence)
begin
foreach 'X is near Y' in Sentence assert edge(X,Y).
foreach 'X that is near Y' in Sentence assert edge(X,Y).
end
我如何在Prolog中实现这一目标?
答案 0 :(得分:1)
首先,您可以在一个步骤中进行模式匹配和统一。其次,您需要使谓词递归。 消费该句子中的第一个单词(即列表的第一个元素)并让递归目标处理其余的:
store([A, is, near, B]):-
assert_edge(A, B).
store([A, is, near, B, that|Other]):-
assert_edge(A, B),
store([B|Other]).
assert_edge(A, B):-
...
另一种方法是对setof/3
等列表使用append/3
和内置谓词:
?- L = [a, that, is, near, b, that, is, near, c, that, is, near, d],
setof(A-B, L1^L2^append(L1,[A, that, is, near, B|L2], L), Edges).
L = [a, that, is, near, b, that, is, near, c|...],
Edges = [a-b, b-c, c-d].
答案 1 :(得分:1)
DCG方法在这里可以很好地运作:
store --> [A], is_near(B), { assertz(edge(A, B)) }, and_near(B).
and_near(_) --> [].
and_near(A) --> [that], is_near(B), { assertz(edge(A, B)) }, and_near(B).
is_near(A) --> [is, near, A].
store(L) :- phrase(store, L).
然后您使用查询:
| ?- store([a, is, near, b, that, is, near, c, that, is, near, d]).
true ? ;
no
| ?- listing(edge).
% file: user_input
edge(a, b).
edge(b, c).
edge(c, d).
yes
| ?-
您还可以使用DCG提取到列表:
extract([edge(A,B)|Edges]) --> [A], is_near(B), and_near(B, Edges).
and_near(_, []) --> [].
and_near(A, [edge(A,B)|Edges]) --> [that], is_near(B), and_near(B, Edges).
is_near(A) --> [is, near, A].
extract(L, Edges) :-
phrase(extract(Edges), L).
| ?- extract([a,is,near,b,that,is,near,c,that,is,near,d], Edges).
Edges = [edge(a,b),edge(b,c),edge(c,d)] ? a
no
| ?-