使用Prolog的CLPFD基于约束结果生成列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Prolog的CLPFD基于约束结果生成列表相关的知识,希望对你有一定的参考价值。

我正在尝试使用约束(CLPFD)在Prolog中实现Skyscraper puzzle求解器。

我已经意识到一个很大的限制是计算最大开关在遍历每一行和每列时的次数,并将其与侧线相匹配。

这是一行的示例:

*2* [ _ | _ | _ | _ ] *3*   ->   *2* [ 1 | 4 | 3 | 2 ] *3*

列表[1, 4, 3, 2]适用于线索2,因为它有2个最大开关(0 - > 1 - > 4)。 它也适用于线索3,因为相同的列表反转 - [2, 3, 4, 1] - 有3个最大开关(0 - > 2 - > 3 - > 4)。

我设法编写了一个谓词,它返回列表中最大开关的数量。 问题是如何实际利用它来生成新约束?我无法直接传递我的列表/矩阵,因为它尚未初始化。

它可能应该是这样的:

calculate_max_switches(List, Switches),
% Generate a list whose Switches value is equal to the clue number.

谢谢。

答案

没有看到你的代码,这是我的提示,改编自my previous answer

:- use_module(library(clpfd)).

skyscrape_row(Left, Right, Heights) :-
    constraint_view(0, Heights, LHeights),
    sum(LHeights, #=, Left),
    reverse(Heights, Heights_),
    constraint_view(0, Heights_, RHeights),
    sum(RHeights, #=, Right).

constraint_view(_, [], []).
constraint_view(Top, [V|Vs], [R|Rs]) :-
    R #<==> V #> 0 #/ V #> Top,
    Max #= max(Top, V),
    constraint_view(Max, Vs, Rs).

适用于您的示例产量

?- L=[A,B,C,D], L ins 1..4, all_different(L), skyscrape_row(2,3,L), label(L).

A = 1,
B = 4,
C = 3,
D = 2,
L = [1, 4, 3, 2]
A = 2,
B = 4,
C = 3,
D = 1,
L = [2, 4, 3, 1]
A = 3,
B = 4,
C = 2,
D = 1,
L = [3, 4, 2, 1]

SWISH提供实时代码

以上是关于使用Prolog的CLPFD基于约束结果生成列表的主要内容,如果未能解决你的问题,请参考以下文章

Prolog 手动或自定义标签

Prolog约束逻辑编程 - 如何在给定整数列表的情况下在域变量列表上设置域?

在 Prolog 中使用约束和排列解决难题

如何将约束添加到由明确的子句语法生成的列表中?

从 Prolog 到 Haskell 的思考——生成真值组合列表

重复结果存储在Prolog的列表中