简体   繁体   English

ECLiPSe CLP中的自定义启发式

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM