n-queen更好的合金模型?

时间:2017-04-01 20:14:14

标签: alloy

以下是n-queens问题的合金模型(实际上,4皇后问题)。我想知道是否有更好的解决方案?请注意,在我的解决方案中,我反复使用nextprev来消除对角线上的皇后;这看起来很笨拙。

open util/ordering[Row]

sig Row {}

one sig Column0 {
    row: Row
}

one sig Column1 {
    row: Row
}

one sig Column2 {
    row: Row
}

one sig Column3 {
    row: Row
}

fact {
   #Row = 4
}

fact {
    Column0.row != Column1.row
    Column0.row != Column2.row
    Column0.row != Column3.row
    Column1.row != next.(Column0.row)
    Column2.row != next.next.(Column0.row)
    Column3.row != next.next.next.(Column0.row)
    Column1.row != prev.(Column0.row)
    Column2.row != prev.prev.(Column0.row)
    Column3.row != prev.prev.(Column0.row)

    Column1.row != Column2.row
    Column1.row != Column3.row
    Column2.row != next.(Column1.row)
    Column3.row != next.next.(Column1.row)
    Column2.row != prev.(Column1.row)
    Column3.row != prev.prev.(Column1.row)

    Column2.row != Column3.row
    Column3.row != next.(Column2.row)
    Column3.row != prev.(Column2.row)
}

pred Show {}

run Show for 4

1 个答案:

答案 0 :(得分:2)

这一切都取决于你的意思更好。 您的解决方案具有一些优势:针对4个皇后/ 4x4主板进行了优化,概念数量最少,生成的实例具有良好的默认图形可视化,但也有其缺点。 (不适用于不同数量的皇后/行/列,以及" klunky约束")

我向您展示了我提出的另一种解决方案,它有其缺点(更多的概念+约束中的量化可能会减慢分析速度),但也有它的优点:简洁和更具可读性的约束和灵活性(适用于任何数量的COLS /行/皇后)

one sig Board{
    cols: seq Column,
    rows: seq Row,
    q: set Queen
}
sig Row {
  id:Int
}{
   id=Board.rows.idxOf[this]
   this in Board.rows.elems
}

sig Column {
  id:Int
}{
  id=Board.cols.idxOf[this]
  this in Board.cols.elems
}
sig Queen{
    x:Column,
    y:Row
}
pred aligned[q1,q2:Queen]{
   q1.y=q2.y 
   or 
   q1.x=q2.x  
   or some a,b:Int{
       add[q1.x.id,a]= q2.x.id 
       add[q1.y.id,b]= q2.y.id
       a=b or a=sub[0,b]
    } 
}
pred Show {
   no disj q1,q2:Queen| aligned[q1,q2]
}
run Show for exactly 4 Row, exactly 4 Column, exactly 4 Queen   

请注意,如果没有适当的主题,通过分析获得的实例将难以可视化。您可以导入一个可以生成良好可视化的文件:https://pastebin.com/wwKP6g9h

注意2:您需要禁止整数溢出或将整数带宽设置得足够大,以使对齐谓词中的添加符合预期行为

注3:添加了id字段,以便在主题中显示行/列的id作为属性(序列不支持)。

编辑必须手动为此模型分配seq的范围才能使用n> 4。

以下是没有序列的替代实现(对于那些不想为分配额外范围而烦恼的人)

one sig Board{
    cols: set Column,
    rows: set Row,
    q: set Queen
}
sig Row {
  id: disj Int
}{
   this in Board.rows
}

fact id{
    all r:Row| (sub[r.id,1] in Row.id or r.id=1) and r.id>0
    all c:Column| (sub[c.id,1] in Column.id or c.id=1) and c.id>0
}

sig Column {
  id: disj Int
}{
  this in Board.cols
}
sig Queen{
    x:Column,
    y:Row
}
pred aligned[q1,q2:Queen]{
   q1.y=q2.y 
   or 
   q1.x=q2.x  
   or some a,b:Int{
       add[q1.x.id,a]= q2.x.id 
       add[q1.y.id,b]= q2.y.id
       a=b or a=sub[0,b]
    } 
}
pred Show {
   no disj q1,q2:Queen| aligned[q1,q2]
}
run Show for exactly 4 Row, exactly 4 Column, exactly 4 Queen