[英]Custom heuristic in ECLiPSe CLP
Consider the following puzzle: 考虑以下难题:
A cell is either marked or unmarked. 单元格已标记或未标记。 Numbers along the right and bottom side of the puzzle denote the total sum for a certain row or column.
拼图右侧和底部的数字表示特定行或列的总和。 Cells contribute (if marked) to the sum in its row and column: a cell in position (i,j) contributes i to the column sum and j to the row sum.
单元格对其行和列中的总和作出贡献(如果标记):位置(i,j)中的单元格对列之和贡献i,对行和数贡献j。 For example, in the first row in the picture above, the 1st, 2nd and 5th cell are marked.
例如,在上图中的第一行中,标记了第一,第二和第五个单元格。 These contribute 1 + 2 + 5 to the row sum (thus totalling 8), and 1 each to their column sum.
它们为行和贡献了1 + 2 + 5(因此总计为8),为他们的列和贡献了1。
I have a solver in ECLiPSe CLP for this puzzle and I am tyring to write a custom heuristic for it. 我在ECLiPSe CLP中有一个求解器,可以解决这个难题,我想为此写一个自定义的启发式方法。
The easiest cells to start with, I think, are those for which the column and row hint are as low as possible. 我认为,最简单的单元格是列和行提示尽可能低的单元格。 In general, the lower
N
is, the fewer possibilities exist to write N
as a sum of natural numbers between 1 and N
. 一般来说,较低的
N
是,较少可能性存在写N
为1和之间的自然数的总和N
。 In the context of this puzzle it means the cell with the lowest column hint + row hint
has lowest odds of being wrong, so less backtracking. 在此难题的背景下,这意味着
column hint + row hint
最低的单元格出错的可能性最低,因此回溯更少。
In the implementation I have a NxN
array that represents the board, and two lists of size N that represent the hints. 在实现中,我有一个
NxN
数组,它代表木板,以及两个大小为N的列表,它们代表提示。 (The numbers to the side and on the bottom.) (数字在侧面和底部。)
I see two options: 我看到两个选择:
Write a custom selection predicate for search/6 . 为search / 6编写一个自定义选择谓词。 However, if I understand correctly, I can only give it 2 parameters.
但是,如果我理解正确,我只能给它两个参数。 There's no way to calculate the row + column sum for a given variable then, because I need to be able to pass it to the predicate.
那么就无法计算给定变量的行和列之和,因为我需要能够将其传递给谓词。 I need 4 parameters.
我需要4个参数。
Ignore search/6 and write an own labelling method. 忽略search / 6并编写自己的标记方法。 That's how I have it right now, see the code below.
这就是我现在的方式,请参见下面的代码。
It takes the board (the NxN
array containing all decision variables), both lists of hints and returns a list containing all variables, now sorted according to their row + column sum. 它使用板(包含所有决策变量的
NxN
数组),提示列表和返回包含所有变量的列表,现在根据它们的行+列总和进行排序。 However, this possibly cannot get any more cumbersome, as you can see. 但是,如您所见,这可能再麻烦不过了。 To be able to sort, I need to attach the sum to each variable, but in order to do that, I first need to convert it to a term that also contains the coordinates of said variable, so that I convert back to the variable as soon as sorting is done...
为了能够排序,我需要将总和附加到每个变量,但是要做到这一点,我首先需要将其转换为也包含所述变量的坐标的项,以便我可以将其转换为排序完成后...
lowest_hints_first(Board,RowArr,ColArr,Out) :-
dim(Board,[N,N]),
dim(OutBoard,[N,N]),
( multifor([I,J],[1,1],[N,N]), foreach(Term,Terms), param(RowArr,ColArr) do
RowHint is ColArr[I],
ColHint is RowArr[J],
TotalSum is RowHint + ColHint,
Term = field(I,J,TotalSum)
),
sort(3,<,Terms,SortedTerms), % Sort based on TotalSum
terms_to_vars(SortedTerms,Board,Out), % Convert fields back to vars...
( foreach(Var,Out) do
indomain(Var,max)
).
terms_to_vars([],_,[]).
terms_to_vars([field(I,J,TotalSum)|RestTerms],Vars,[Out|RestOut]) :-
terms_to_vars(RestTerms,Vars,RestOut),
Out is Vars[I,J].
In the end this heuristic is barely faster than input_order. 最后,这种启发式方法仅比input_order快。 I suspect its due to the awful way it's implemented.
我怀疑它是由于其可怕的实现方式。 Any ideas on how to do it better?
关于如何做得更好的任何想法? Or is my feeling that this heuristic should be a huge improvement incorrect?
还是我觉得这种启发式方法应该是一个巨大的改进,这是不正确的吗?
I see you are already happy with the improvement suggested by Joachim; 我看到您已经对Joachim建议的改进感到满意; however, as you ask for further improvements of your heuristic, consider that there is only one way to get 0 as a sum, as well as there is only one way to get 15. There is only one way to get 1 and 14, 2 and 13;
但是,当您要求进一步改进启发式方法时,请考虑只有一种方法得出0作为总和,只有一种方法得出15。只有一种方法得出1和14、2。和13; two ways to get 3 and 12. In general, if you have K ways to get sum N, you also have K ways to get 15-N.
有两种方法得到3和12。通常,如果您有K种方法获得总和N,那么您也有K种方法获得15-N。
So the difficult sums are not the large ones, they are the middle ones. 因此,困难的总和不是大的,而是中等的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.