例如我有:
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) :-
答案 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。