从知识库中获取随机谓词。序言

时间:2011-09-20 19:36:48

标签: random prolog predicate

例如我有:

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

2 个答案:

答案 0 :(得分: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中测试过。

答案 1 :(得分:0)

SWI-Prolog具有nth_clause/3,所以我想一个简单的解决方案是:

?- I is random(4)+1, nth_clause(upred(_,_,_), I, R), clause(H, B, R).
I = 1,
R = <clause>(0000018B7AECE610),
H = upred(mary, have, knife),
B = true.

?- I is random(4)+1, nth_clause(upred(_,_,_), I, R), clause(H, B, R).
I = 2,
R = <clause>(0000018B7AECC690),
H = upred(john, have, sword),
B = true.

您还可以使用谓词属性number_of_clauses / 1。