0

现在我有一个单选谓词来定义我的搜索空间。

#const nRounds = 3.
#const nPlayers = 17.
#const nSeats = nRounds * nPlayers.
#const nRooms = 3.
#const nDecks = 6.

nSeats { seat(1..nPlayers, 1..nRooms, 1..nDecks) } nSeats.

当我开始遇到性能问题时,我想限制这个搜索空间。在我的设置中,每个玩家只能出现在 4 个“座位”谓词中,所以我想要以下内容:

#for i in 1..nPlayers
nRounds { seat(i, 1..nRooms, 1..nDecks) } nRounds.
#endfor

这基本上会在内部变成这样的东西:

nRounds { seat(1, 1..nRooms, 1..nDecks) } nRounds.
nRounds { seat(2, 1..nRooms, 1..nDecks) } nRounds.
nRounds { seat(3, 1..nRooms, 1..nDecks) } nRounds.
...

当然,我可以“自己拼写”,即使用另一种语言来生成这些行,但我不明白为什么这在 cligo 中不存在。

我首先要寻找一种方法来做到这一点的原因是因为我希望它会比我开始使用(nRooms*nDecks choose nRounds) * nPlayers的要小得多,而(nRooms*nDecks*nPlayers) choose nRounds*nPlayers这反过来又要好得多。{seat(P, R, D)}2^(nRooms*nDecks*nPlayers)

即使我的代码中的约束限制了我最终可以得到的实际可能集合,因此所有这三种表示形式都是等效的,但从这种手动搜索空间修剪中仍然可以获得性能优势,对吧?

4

1 回答 1

1

您正在寻找的“for 循环”是一条直截了当的规则:

nRounds { seat(S, 1..nRooms, 1..nDecks) } nRounds :- S = 1..nPlayers.

检查与您的代码的差异clingo --text

我还建议您将seat(P,R,D)谓词分成几个较小的谓词(取决于您的问题。就像每个玩家被分配一个房间p2r(P,R),每个房间都被分配给一个甲板r2d(R,D)。这样您以后可以在约束中节省很多不必要的组合。当然,我的两个谓词可能对您的问题没有意义,但我相信您会找到一个组合来拆分您的座位谓词。

于 2021-05-12T12:11:37.003 回答