Prolog:Select 从列表中随机规则并传递参数

Prolog: Select rule randomly from list and pass parameter

我正在尝试将 prolog 代码写入 select 列表中的随机规则,然后执行它。这是我让它工作的程度:

/* Rules */
rule1 :- write('1').
rule2 :- write('2').
rule3 :- write('3').

/* List of rules */
list([rule1,rule2,rule3]).

/* Rule to select random rule from list */
findRule :- random_between(0,2,Elem),
            list(L),
            nth0(Elem,L,Rule),
            Rule.

产生(例如)这个结果:

|: findRule.
2
true.

不过,我想给规则传递一个参数,例如:

/* Rules */
rule1(X) :- write(X), write('1').
rule2(X) :- write(X), write('2').
rule3(X) :- write(X), write('3').

/* List of rules */
list([rule1,rule2,rule3]).

/* Rule to select random rule from list */
findRule(X) :- random_between(0,2,Elem),
            list(L),
            nth0(Elem,L,Rule),
            Rule(X).

要产生这样的结果:

|: findRule(hallo).
hallo2
true.

这行不通。我已经考虑过用动态列表尝试同样的事情,但我想先检查一下,是否有更简单的问题解决方案..

使用call/2为了满足最后一个目标:

findRule(X):-
    random_between(0,2,Elem),
    list(L),
    nth0(Elem,L,Rule),
    call(Rule,X).

这真的取决于你的最终目标。解决您目前遇到的确切问题的最简单方法是使用第一个参数对规则进行索引,很可能是一个整数:

rule(1) :- ...
rule(2) :- ...
rule(3) :- ...

您的示例将变为:

rule(1, X) :- ...
rule(2, X) :- ...
rule(3, X) :- ...

evaluate_random(X) :-
    random_between(1, 3, I),
    rule(I, X).

这很好,因为您可以跳过很多内容,例如显式列表、按位置从列表中选择等等。如果您有更具体的用例,您还可以做很多其他事情来获得类似的结果。

编辑:

如果您的目标是使用证明树的 搜索策略 不同于解决方案的默认深度优先搜索 space,那么我建议阅读Richard O'Keefe 的 "The Craft of Prolog" 第二章。从本质上讲,它展示了如何以不同于深度优先的方式搜索解决方案:广度优先、局部或全局启发式排序等。要实现这一点,您需要保留搜索树中未探索节点的术语并挑选它们以不同于默认深度优先的方式输出。然而,这超出了您的问题范围:如有必要,请提出一个新的、更具体的问题。