Prolog nth1匿名变量

Ben*_*373 8 prolog prolog-toplevel

我有一个带有整数和匿名变量的List,我试图找到一个特殊值的索引.问题是我用它nth1/3来找到索引Prolog为匿名变量分配值,因此我也找到了索引.

例如: List = [1,\_,1],我想要的结果是X = 1, X = 3nth1(X,List,1),而是说之前,我X = 1, X = 2, X = 3.

mat*_*mat 5

在您的要求中隐藏着一个有问题的问题:它们违反了称为单调性的重要声明性属性.我们的意思是,添加约束最多可以使解决方案更具体,而不是更一般.

例如,通过您发布的解决方案,我们得到:

?- list_el_index([_], 1, N).
false.

现在我通过对迄今为止免费的匿名变量强加一个额外的要求来添加一个约束:

?- Var = 1, list_el_index([Var], 1, N).
Var = 1,
N = 0 .

我的意思是:来吧!我们添加了一个约束,结果获得比以前更多的解决方案?这样的结果是不幸的,并且阻止我们以合乎逻辑的  方式推理这个程序.

该计划在其他方面也使我们失望.例如,让我们问:有哪些解决方案?

?- list_el_index(Ls, El, I).
nontermination

理想情况下,我们希望程序在这种情况下生成解决方案!这种普遍性是逻辑编程最重要的吸引力之一,并将其​​与更低级别的范例区分开来.


解决此类问题的一种方法是象征性地区分列表中出现的不同类型的元素.

例如,让我们使用:

  • u为了一个未知的价值.
  • i(I)整数 I.

通过这种新表示,您的解决方案将成为:

list_el_index([i(I)|_], I, 0).
list_el_index([_|Tail], Element, Index) :-
    list_el_index(Tail, Element, Index0),
    Index #= Index0+1.

我也冒昧来替代(is)/2通过(#=)/2,宣传和坚持更一般的整数运算,可以让我们更自由地重新排序的目标,如果需要的话.根据您的Prolog实现,您可能必须导入库才能从中受益  (#=)/2.

通过此表示,您的初始案例变为:

?- list_el_index([i(1),u,i(1)], 1, Index).
Index = 0 ;
Index = 2 ;
false.

这按预期工作!

重要的是,我们也可以更普遍地使用谓词,即生成可能的答案:

?- list_el_index(Ls, El, I).
Ls = [i(El)|_2994],
I = 0 ;
Ls = [_2992, i(El)|_3000],
I = 1 ;
Ls = [_2992, _2998, i(El)|_3006],
I = 2 ;
Ls = [_2992, _2998, _3004, i(El)|_3012],
I = 3 .

由于程序的单调性,我们可以通过迭代深化公平地列举解决方案:

?- length(Ls, _), list_el_index(Ls, El, I).
Ls = [i(El)],
I = 0 ;
Ls = [i(El), _4812],
I = 0 ;
Ls = [_4806, i(El)],
I = 1 ;
Ls = [i(El), _4812, _4818],
I = 0 ;
etc.

通过使用允许我们通过模式匹配来区分案例的表示,这已经成为可能.考虑使用这种方法使您的程序可以在所有方向上使用,并使逻辑推理适用.使用适当的包装器或常量非常容易应用,并大大增加了程序的通用性.