2011-09-20 48 views
1

比如我有:从知识库中获取随机谓词。序言

upred(mary, have, knife). 
upred(john, have, sword). 
upred(sam, have, bowl). 
upred(sword, is, long). 

我怎样才能获得随机谓语?

% call this and get random predicate as Pred 
get_random_pred(Pred) :- 
+1

随机在...?!你能给Pred一个样本结果吗?谓词的参数应从哪组值中取出? – ThomasH

回答

5

有趣的是,这也是我最近一直担心的事情。我有一个部分解决方案,它依赖于动态存储并识别您希望随机获得的事实。我并不喜欢它,因为它取决于动态存储,也取决于元数据的制作,而元数据可以不受限制。但是,您的目的可能已足够。它也不能完全捕捉你的API,因为你必须提供一些线索,说明你感兴趣的事实。实际上,它可能会工作得很好,因为你不可能发现自己处于其中任何事实将会这样做,因为它可能会在下一次模式匹配时失败。

我的基本技巧是使用=..反汇编谓词,并使用asserta为每个事实分配一个索引值。如果你想让这个表现更好,你必须使用一些索引指令来告诉Prolog你希望它索引到我的random_fact的第三个字段,但是我没有那么做。对于小型数据库(不是WordNet),这可能是好的,但对于较大的数据库,您可能需要性能。

% random_fact(Head, Instantiation, Index) 
:- dynamic(random_fact/3). 

% fact_count(Head, Count) 
:- dynamic(fact_count/2). 

% one big side-effect to make it possible to query for a random predicate 
prepare_randomization_metadata(Goal) :- 
    findall(Goal, Goal, Occurrances), 
    prepare_randomization_metadata(Occurrances, 0), 
    Goal =.. [Head|_], 
    length(Occurrances, N), 
    asserta(fact_count(Head, N)). 

prepare_randomization_metadata([], _). 
prepare_randomization_metadata([Goal|Goals], N) :- 
    Goal =.. [Head|_], 
    asserta(random_fact(Head, Goal, N)), 
    N1 is N+1, 
    prepare_randomization_metadata(Goals, N1), !. 

所以,你可以看到,这里的引擎基本上是一个给定的目标,并建立一个小的元数据库。这可能可以通过一个比我更了解Prolog的人来改善。要使用它,你驾驶它就像这样:

?- prepare_randomization_metadata(upred(X, Y, Z)). 
true. 

现在,你必须在它的事实像这样的数据库:

random_fact(upred, upred(mary, have, knife), 0). 
random_fact(upred, upred(john, have, sword), 1). 
... 

这是你可以用Prolog的理智战胜了。所以如果你想第二个谓语,可以查询它像这样:

?- random_fact(upred, X, 1) 
X = upred(mary, have, knife) ; 
false. 

现在get_random_pred是很容易的,但我们需要一个额外的参数来识别“厚道”其实我们想:

get_random_pred(Head, Pred) :- 
    fact_count(Head, N), 
    % pick a random number between 0 and the # of facts we have for this pred 
    random(0, N, I), 
    random_fact(Head, Pred, I), !. 

我还不够好,但是Prolog告诉你为什么这有时候认为它有多种解决方案,但它确实有,所以我在最后插入了红色的裁剪。但是,如果你需要多种解决方案,编写一个能够完成这个任务的版本也很容易。

endless_random_facts(Head, Fact) :- repeat, get_random_pred(Head, Fact). 

例如:

?- get_random_pred(upred, X). 
X = upred(sword, is, long) ; 
X = upred(john, have, sword) ; 
X = upred(mary, have, knife) ; 
X = upred(john, have, sword) ; 
X = upred(john, have, sword) ; 

无论如何,我希望这会有所帮助,尽管不足。我只在SWI-Prolog中测试过。