SlideShare a Scribd company logo
1 of 44
Download to read offline
Alloy で パズル
明石工業高等専門学校 電気情報工学科 2年
                 仔竜 レアン
            (@favdragon_rean)
Alloyであそぼう!

   「抽象によるソフトウェア設計」って本の題名だけど、正直ソフトウェア設
    計をやる機会ってそんなにないってゆ~か~ 、ちょっと堅苦しくない?って
    かんじぃ~?


   もっとゲーム感覚で遊べないんです???
あった!!!

   パズル解けば楽しいんじゃね??
数独
Sudoku
数独ってどんなのだっけ?

                    5   3   4   6   7   8   9   1   2
      ペンシルパズルの一種
                    6   7   2   1   9   5   3   4   8
                    1   9   8   3   4   2   5   6   7
                    8   5   9   7   6   1   4   3   3
                    4   2   6   8   5   3   7   9   1
                    7   1   3   9   2   4   8   5   6
                    9   6   1   5   3   7   2   8   4
                    2   8   7   4   1   9   6   3   5
                    3   4   5   2   8   6   1   7   9
数独ってどんなのだっけ?

                      5   3   4   6   7   8   9   1   2
      ペンシルパズルの一種
                      6   7   2   1   9   5   3   4   8
      1~9の数字を埋めていく
                      1   9   8   3   4   2   5   6   7
                      8   5   9   7   6   1   4   3   3
                      4   2   6   8   5   3   7   9   1
                      7   1   3   9   2   4   8   5   6
                      9   6   1   5   3   7   2   8   4
                      2   8   7   4   1   9   6   3   5
                      3   4   5   2   8   6   1   7   9
数独ってどんなのだっけ?

                        5   3   4   6   7   8   9   1   2
      ペンシルパズルの一種
                        6   7   2   1   9   5   3   4   8
      1~9の数字を埋めていく
                        1   9   8   3   4   2   5   6   7
      太枠で囲まれている3x3のブ
       ロック内に同じ数字が複数     8   5   9   7   6   1   4   3   3
       入ってはいけない
                        4   2   6   8   5   3   7   9   1
                        7   1   3   9   2   4   8   5   6
                        9   6   1   5   3   7   2   8   4
                        2   8   7   4   1   9   6   3   5
                        3   4   5   2   8   6   1   7   9
数独ってどんなのだっけ?

                        5   3   4   6   7   8   9   1   2
      ペンシルパズルの一種
                        6   7   2   1   9   5   3   4   8
      1~9の数字を埋めていく
                        1   9   8   3   4   2   5   6   7
      太枠で囲まれている3x3のブ
       ロック内に同じ数字が複数     8   5   9   7   6   1   4   3   3
       入ってはいけない
                        4   2   6   8   5   3   7   9   1
      横の列で同じ数字が複数入っ
       てはいけない           7   1   3   9   2   4   8   5   6
                        9   6   1   5   3   7   2   8   4
                        2   8   7   4   1   9   6   3   5
                        3   4   5   2   8   6   1   7   9
数独ってどんなのだっけ?

                        5   3   4   6   7   8   9   1   2
      ペンシルパズルの一種
                        6   7   2   1   9   5   3   4   8
      1~9の数字を埋めていく
                        1   9   8   3   4   2   5   6   7
      太枠で囲まれている3x3のブ
       ロック内に同じ数字が複数     8   5   9   7   6   1   4   3   3
       入ってはいけない
                        4   2   6   8   5   3   7   9   1
      横の列で同じ数字が複数入っ
       てはいけない           7   1   3   9   2   4   8   5   6
      縦の列で同じ数字が複数入っ    9   6   1   5   3   7   2   8   4
       てはいけない
                        2   8   7   4   1   9   6   3   5
                        3   4   5   2   8   6   1   7   9
で、Alloyでどうやって解くの?
手続き型言語では

      パズルの解き方をガリゴリ書いていく
          既に入っている数字から消去法的に数字を入れていくとか
Alloyでは

        パズルの正答がどんな条件を満たすべきかを書き下していく
        すると、勝手にSAT Solverがパズルを解いてくれる!


        それってやばくね?
盤面を表現する

                         5   3   4   6   7   8   9   1   2
      普通に考えたら、数値型の9x9
       の2次元配列で表現できる      6   7   2   1   9   5   3   4   8
                         1   9   8   3   4   2   5   6   7
      えっ、配列って何ですか?      8   5   9   7   6   1   4   3   3
                         4   2   6   8   5   3   7   9   1
      ちょっと何言ってるかよくわか
       んないですね・・・
                         7   1   3   9   2   4   8   5   6
                         9   6   1   5   3   7   2   8   4
                         2   8   7   4   1   9   6   3   5
                         3   4   5   2   8   6   1   7   9
Alloyは数字が苦手

       数値をある値と直接比較することはあっても、数値演算を
        することは多くない
       配列っぽいもの(Int -> Hoge , アトムのシークエンス)は一
        応あるが、結構使いにくい
           本の付録にちょっと書いてある程度にしか触れられていない
ところで

      使う数字って1~9ですよね?


      それくらいだったらシグネチャだと思ったら余裕じゃね?
こうなる
abstract sig Number{data: Number -> Number}
abstract sig Region1, Region2, Region3 extends Number{}

one sig N1, N2, N3 extends Region1 {}
one sig N4, N5, N6 extends Region2 {}
one sig N7, N8, N9 extends Region3 {}




       Java的に言うと、仮想クラスNumberを作って、それを継承す
        るクラスN1~N9を定義した感じ
       頭おかしい
       でも扱いやすい
Number
 Region1      Region2      Region3

  N1            N4          N7

  N2            N5          N8

  N3            N6          N9



  ※Abstractなので正確にはちょっと違う
盤面の表現

   「1行目,2列目に3という数字が入る」ことを、 N1->N2->N3 とい
    う3項関係で表す
   実体は、(N1,N2,N3)というTuple


   3項関係のイメージはとてもむずかしい


   とりあえず、N1.data[N2]とするとN3が取れる
   data[N1,N2]でもいいし
   N2.(N1.data)でもいい
   気分で書き分けるとたのしい
   ?
正答の条件


   1.   全てのマスが埋まっている
   2.   どの縦列を見ても、重複する数字はない
   3.   どの横列を見ても、重複する数字はない
   4.   どのブロックを見ても、重複する数字はない
正答の条件
①全てのマスが埋まっている
   all n1,n2: Number | one n1.data[n2]

      『どのような組み合わせのNumber n1,n2であっても、一つ
       のn1.data[n2]が存在する』
          (2つ以上は存在しない)
      n1,n2が取りうる値はN1~N9で、n1.data[n2]は、n1行目,
       n2列目に書かれている数値を表す
      要するに、「どんな(x,y)にも1つ数値が書かれている」とい
       うこと
正答の条件
①全てのマスが埋まっている
   all n1,n2: Number | one n1.data[n2]

   どのような組み合わせのNumber n1,n2であっても、
   一つのn1.data[n2]が存在する
正答の条件
①全てのマスが埋まっている
   all n1,n2: Number | one n1.data[n2]

   どのような組み合わせのNumber n1,n2であっても、
   一つのn1.data[n2]が存在する
正答の条件
①全てのマスが埋まっている
   all n1,n2: Number | one n1.data[n2]

   どのような組み合わせのNumber n1,n2であっても、
   一つのn1.data[n2]が存在する
正答の条件
②どの縦列を見ても、重複する数字はない
       「重複する数字はない」を「1,2,3,4,5,6,7,8,9全てを含
        む集合と等しい」と言い換えることができる
       9つのマスに9つの数字を入れるので、重複があると全て
        を含むことができないため
ところで

   na.(nb.data) というものは、実は『集合na,nbからそれぞれ選んだNumber A,B
    の全ての組み合わせにおいて、A行目B列目に入る数値の集合』を表しています。
    (N1とかN2は、要素1の集合と扱われる)
N1             data[N1]

data[N1]              data[N1]           N6

           N4             N5




     (例)
     Region2 = N4 + N5 + N6 とするときの、Region2.data[N1]は、
     Region2が3つの要素の集合なので、その全てを当てはめた、
     N4.data[N1] + N5.data[N1] + N6.data[N1] になる
ところで

   na.(nb.data) というものは、実は『集合na,nbからそれぞれ選んだNumber A,B
    の全ての組み合わせにおいて、A行目B列目に入る数値の集合』を表しています。
    (N1とかN2は、要素1の集合と扱われる)

   ところで、Number = N1 + N2 + /* … */ + N9 なので、
   Number.(nb.data) は「全ての行のnb列目に入る数字の集合」だ!!!
na.data(nb)にN1~N9が含まれているか
を調べる関数(のようなもの)をつくる
pred complete(na: set Number, nb: set Number){
  Number = na.(nb.data)
}


   set Number を2つ引数にとる述語complete
   Number集合と、na.(nb.data)が一致すれば真
正答の条件
②どの縦列を見ても、重複する数字はない

all col: Number | complete[Number, col]

   こう書けるよね!
正答の条件
③どの横列を見ても、重複する数字はない

all row: Number | complete[row, Number]

   同様にこう書けるよね!
正答の条件
④どのブロックを見ても、重複する数字はない
   左上のブロックだけを考える
   左上のブロックの集合は、{1,2,3}行目{1,2,3}列目で表せ   5   3   4   6   7   8   9   1   2
    られる
                                        6   7   2   1   9   5   3   4   8
                                        1   9   8   3   4   2   5   6   7
   Region1 = N1,N2,N3 と宣言されている(!)
                                        8   5   9   7   6   1   4   3   3
                                        4   2   6   8   5   3   7   9   1
                                        7   1   3   9   2   4   8   5   6
                                        9   6   1   5   3   7   2   8   4
                                        2   8   7   4   1   9   6   3   5
                                        3   4   5   2   8   6   1   7   9
正答の条件
④どのブロックを見ても、重複する数字はない
    「ブロック1内で重複する数字がない」条件

complete[Region1,Region1]

   更に、全てのRegionについて言えるので、単に列挙すればいい

       complete[Region1,   Region1]
       complete[Region1,   Region2]
       complete[Region1,   Region3]
       complete[Region2,   Region1]
       complete[Region2,   Region2]
       complete[Region2,   Region3]
       complete[Region3,   Region1]
       complete[Region3,   Region2]
       complete[Region3,   Region3]
初期条件

   「最初から盤面に入ってい   pred puzzle() {
    る数字」の集合は、全ての       N1->N1->N5 +   N1->N2->N3 +   N1->N5->N7
    盤面上の数字の部分集合だ       + N2->N1->N6   + N2->N4->N1   + N2->N5->N9   + N2->N6->N5
    よ!といっています          + N3->N2->N9   + N3->N3->N8   + N3->N8->N6
                       + N4->N1->N8   + N4->N5->N6   + N4->N9->N3
   要するに、ここに書いた番       + N5->N1->N4   + N5->N4->N8   + N5->N6->N3   + N5->N9->N1
    号は盤面内にあることがこ       + N6->N1->N7   + N6->N5->N2   + N6->N9->N6
    れで保証されます           + N7->N2->N6   + N7->N7->N2   + N7->N8->N8
                       + N8->N4->N4   + N8->N5->N1   + N8->N6->N9   + N8->N9->N5
                       + N9->N5->N8   + N9->N8->N7   + N9->N9->N9   in data
                   }
正答の条件
                  pred complete(na: set Number, nb: set Number){
                      Number in na.(nb.data)
                  }
   まとめるとこうなるよ!
                  pred rules(){
                      all n1,n2: Number | one n1.data[n2]
                      all row: Number | complete[row, Number]
                      all col: Number | complete[Number, col]
                      complete[Region1, Region1]
                      complete[Region1, Region2]
                      complete[Region1, Region3]
                      complete[Region2, Region1]
                      complete[Region2, Region2]
                      complete[Region2, Region3]
                      complete[Region3, Region1]
                      complete[Region3, Region2]
                      complete[Region3, Region3]
                  }
完成したソースコード
abstract sig Number{data: Number -> Number}
abstract sig Region1, Region2, Region3 extends Number{}
one sig N1, N2, N3 extends Region1 {}
one sig N4, N5, N6 extends Region2 {}
one sig N7, N8, N9 extends Region3 {}
pred complete(na: set Number, nb: set Number){
    Number = na.(nb.data)
}
pred rules(){                                   pred puzzle() {
    all n1,n2: Number | one n1.data[n2]             N1->N1->N5 + N1->N2->N3 + N1->N5->N7
    all row: Number | complete[row, Number]         + N2->N1->N6 + N2->N4->N1 + N2->N5->N9   + N2->N6->N5
    all col: Number | complete[Number, col]         + N3->N2->N9 + N3->N3->N8 + N3->N8->N6
    complete[Region1, Region1]                      + N4->N1->N8 + N4->N5->N6 + N4->N9->N3
    complete[Region1, Region2]                      + N5->N1->N4 + N5->N4->N8 + N5->N6->N3   + N5->N9->N1
    complete[Region1, Region3]                      + N6->N1->N7 + N6->N5->N2 + N6->N9->N6
    complete[Region2, Region1]                      + N7->N2->N6 + N7->N7->N2 + N7->N8->N8
    complete[Region2, Region2]                      + N8->N4->N4 + N8->N5->N1 + N8->N6->N9   + N8->N9->N5
    complete[Region2, Region3]                      + N9->N5->N8 + N9->N8->N7 + N9->N9->N9   in data
    complete[Region3, Region1]                  }
    complete[Region3, Region2]                  pred solve{ rules[] puzzle[] }
    complete[Region3, Region3]                  run solve
}
これだけなんです!

   あとは実行するだけで、数独を解いてくれるらしいですよ!
   Alloyまじかっけー




   と、言うわけでやってみますね!
・・・
やばすぎなのでは

   Alloyさんちょっと何言ってるかわかんないですね・・・


   Numberの3項関係として解答されるので、人間が見てもわけがわからな
    い!!!




   と、言うわけでビジュアライザーつくりました
ちゃんと動いた!

   解き方は全く与えていないのに、正答の条件を定義するだけでちゃんと解が求
    まる!
   ちょっと書き換えるだけで、与えた盤面が正しいかどうかを調べるようにもで
    きそう
まとめ

   Alloyでパズルを解くには、“解き方を書く”のはなく、“解いた結果の条件”を
    与えてやるとうまくいく
   @qnighyさんはもっと短く(10行程度+問題の入力)解いてました、ぱない
       https://gist.github.com/3478314


   「解くことができる数独の問題」を作ることもできる(らしい)


   他にも、色々なパズルが解ける(らしい)ので、是非挑戦してみるといいかも?
参考にしたページ

   「Alloy4.0で数独パズル」
http://toshi.way-nifty.com/log/2008/05/alloy40_3b9e.html
ご清聴
ありがとうございました

More Related Content

Similar to Alloyでパズル

わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうかわんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうかMasami Yabushita
 
PFDS 9.3.1
PFDS 9.3.1PFDS 9.3.1
PFDS 9.3.1rf0444
 
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版Masami Yabushita
 
Haskell で nクィーン問題を解く
Haskell で nクィーン問題を解くHaskell で nクィーン問題を解く
Haskell で nクィーン問題を解くmitstream
 
金大アルゴリズム勉強会#004資料
金大アルゴリズム勉強会#004資料金大アルゴリズム勉強会#004資料
金大アルゴリズム勉強会#004資料Takumi Murano
 
素数大富豪に関する自由研究まとめ
素数大富豪に関する自由研究まとめ素数大富豪に関する自由研究まとめ
素数大富豪に関する自由研究まとめNi sei
 

Similar to Alloyでパズル (6)

わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうかわんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
わんくま勉強会東京#82 あおいたんのパズルを数学しましょうか
 
PFDS 9.3.1
PFDS 9.3.1PFDS 9.3.1
PFDS 9.3.1
 
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版T82 aoitan あおいたんのパズルを数学しましょうか_修正版
T82 aoitan あおいたんのパズルを数学しましょうか_修正版
 
Haskell で nクィーン問題を解く
Haskell で nクィーン問題を解くHaskell で nクィーン問題を解く
Haskell で nクィーン問題を解く
 
金大アルゴリズム勉強会#004資料
金大アルゴリズム勉強会#004資料金大アルゴリズム勉強会#004資料
金大アルゴリズム勉強会#004資料
 
素数大富豪に関する自由研究まとめ
素数大富豪に関する自由研究まとめ素数大富豪に関する自由研究まとめ
素数大富豪に関する自由研究まとめ
 

Alloyでパズル

  • 1. Alloy で パズル 明石工業高等専門学校 電気情報工学科 2年 仔竜 レアン (@favdragon_rean)
  • 2. Alloyであそぼう!  「抽象によるソフトウェア設計」って本の題名だけど、正直ソフトウェア設 計をやる機会ってそんなにないってゆ~か~ 、ちょっと堅苦しくない?って かんじぃ~?  もっとゲーム感覚で遊べないんです???
  • 3.
  • 4.
  • 5. あった!!!  パズル解けば楽しいんじゃね??
  • 7. 数独ってどんなのだっけ? 5 3 4 6 7 8 9 1 2  ペンシルパズルの一種 6 7 2 1 9 5 3 4 8 1 9 8 3 4 2 5 6 7 8 5 9 7 6 1 4 3 3 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 8. 数独ってどんなのだっけ? 5 3 4 6 7 8 9 1 2  ペンシルパズルの一種 6 7 2 1 9 5 3 4 8  1~9の数字を埋めていく 1 9 8 3 4 2 5 6 7 8 5 9 7 6 1 4 3 3 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 9. 数独ってどんなのだっけ? 5 3 4 6 7 8 9 1 2  ペンシルパズルの一種 6 7 2 1 9 5 3 4 8  1~9の数字を埋めていく 1 9 8 3 4 2 5 6 7  太枠で囲まれている3x3のブ ロック内に同じ数字が複数 8 5 9 7 6 1 4 3 3 入ってはいけない 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 10. 数独ってどんなのだっけ? 5 3 4 6 7 8 9 1 2  ペンシルパズルの一種 6 7 2 1 9 5 3 4 8  1~9の数字を埋めていく 1 9 8 3 4 2 5 6 7  太枠で囲まれている3x3のブ ロック内に同じ数字が複数 8 5 9 7 6 1 4 3 3 入ってはいけない 4 2 6 8 5 3 7 9 1  横の列で同じ数字が複数入っ てはいけない 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 11. 数独ってどんなのだっけ? 5 3 4 6 7 8 9 1 2  ペンシルパズルの一種 6 7 2 1 9 5 3 4 8  1~9の数字を埋めていく 1 9 8 3 4 2 5 6 7  太枠で囲まれている3x3のブ ロック内に同じ数字が複数 8 5 9 7 6 1 4 3 3 入ってはいけない 4 2 6 8 5 3 7 9 1  横の列で同じ数字が複数入っ てはいけない 7 1 3 9 2 4 8 5 6  縦の列で同じ数字が複数入っ 9 6 1 5 3 7 2 8 4 てはいけない 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 13. 手続き型言語では  パズルの解き方をガリゴリ書いていく  既に入っている数字から消去法的に数字を入れていくとか
  • 14. Alloyでは  パズルの正答がどんな条件を満たすべきかを書き下していく  すると、勝手にSAT Solverがパズルを解いてくれる!  それってやばくね?
  • 15. 盤面を表現する 5 3 4 6 7 8 9 1 2  普通に考えたら、数値型の9x9 の2次元配列で表現できる 6 7 2 1 9 5 3 4 8 1 9 8 3 4 2 5 6 7  えっ、配列って何ですか? 8 5 9 7 6 1 4 3 3 4 2 6 8 5 3 7 9 1  ちょっと何言ってるかよくわか んないですね・・・ 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 16. Alloyは数字が苦手  数値をある値と直接比較することはあっても、数値演算を することは多くない  配列っぽいもの(Int -> Hoge , アトムのシークエンス)は一 応あるが、結構使いにくい  本の付録にちょっと書いてある程度にしか触れられていない
  • 17. ところで  使う数字って1~9ですよね?  それくらいだったらシグネチャだと思ったら余裕じゃね?
  • 18. こうなる abstract sig Number{data: Number -> Number} abstract sig Region1, Region2, Region3 extends Number{} one sig N1, N2, N3 extends Region1 {} one sig N4, N5, N6 extends Region2 {} one sig N7, N8, N9 extends Region3 {}  Java的に言うと、仮想クラスNumberを作って、それを継承す るクラスN1~N9を定義した感じ  頭おかしい  でも扱いやすい
  • 19. Number Region1 Region2 Region3 N1 N4 N7 N2 N5 N8 N3 N6 N9 ※Abstractなので正確にはちょっと違う
  • 20. 盤面の表現  「1行目,2列目に3という数字が入る」ことを、 N1->N2->N3 とい う3項関係で表す  実体は、(N1,N2,N3)というTuple  3項関係のイメージはとてもむずかしい  とりあえず、N1.data[N2]とするとN3が取れる  data[N1,N2]でもいいし  N2.(N1.data)でもいい  気分で書き分けるとたのしい  ?
  • 21. 正答の条件 1. 全てのマスが埋まっている 2. どの縦列を見ても、重複する数字はない 3. どの横列を見ても、重複する数字はない 4. どのブロックを見ても、重複する数字はない
  • 22. 正答の条件 ①全てのマスが埋まっている all n1,n2: Number | one n1.data[n2]  『どのような組み合わせのNumber n1,n2であっても、一つ のn1.data[n2]が存在する』  (2つ以上は存在しない)  n1,n2が取りうる値はN1~N9で、n1.data[n2]は、n1行目, n2列目に書かれている数値を表す  要するに、「どんな(x,y)にも1つ数値が書かれている」とい うこと
  • 23. 正答の条件 ①全てのマスが埋まっている all n1,n2: Number | one n1.data[n2] どのような組み合わせのNumber n1,n2であっても、 一つのn1.data[n2]が存在する
  • 24. 正答の条件 ①全てのマスが埋まっている all n1,n2: Number | one n1.data[n2] どのような組み合わせのNumber n1,n2であっても、 一つのn1.data[n2]が存在する
  • 25. 正答の条件 ①全てのマスが埋まっている all n1,n2: Number | one n1.data[n2] どのような組み合わせのNumber n1,n2であっても、 一つのn1.data[n2]が存在する
  • 26. 正答の条件 ②どの縦列を見ても、重複する数字はない  「重複する数字はない」を「1,2,3,4,5,6,7,8,9全てを含 む集合と等しい」と言い換えることができる  9つのマスに9つの数字を入れるので、重複があると全て を含むことができないため
  • 27. ところで  na.(nb.data) というものは、実は『集合na,nbからそれぞれ選んだNumber A,B の全ての組み合わせにおいて、A行目B列目に入る数値の集合』を表しています。 (N1とかN2は、要素1の集合と扱われる)
  • 28. N1 data[N1] data[N1] data[N1] N6 N4 N5 (例) Region2 = N4 + N5 + N6 とするときの、Region2.data[N1]は、 Region2が3つの要素の集合なので、その全てを当てはめた、 N4.data[N1] + N5.data[N1] + N6.data[N1] になる
  • 29. ところで  na.(nb.data) というものは、実は『集合na,nbからそれぞれ選んだNumber A,B の全ての組み合わせにおいて、A行目B列目に入る数値の集合』を表しています。 (N1とかN2は、要素1の集合と扱われる)  ところで、Number = N1 + N2 + /* … */ + N9 なので、  Number.(nb.data) は「全ての行のnb列目に入る数字の集合」だ!!!
  • 30. na.data(nb)にN1~N9が含まれているか を調べる関数(のようなもの)をつくる pred complete(na: set Number, nb: set Number){ Number = na.(nb.data) }  set Number を2つ引数にとる述語complete  Number集合と、na.(nb.data)が一致すれば真
  • 32. 正答の条件 ③どの横列を見ても、重複する数字はない all row: Number | complete[row, Number]  同様にこう書けるよね!
  • 33. 正答の条件 ④どのブロックを見ても、重複する数字はない  左上のブロックだけを考える  左上のブロックの集合は、{1,2,3}行目{1,2,3}列目で表せ 5 3 4 6 7 8 9 1 2 られる 6 7 2 1 9 5 3 4 8 1 9 8 3 4 2 5 6 7  Region1 = N1,N2,N3 と宣言されている(!) 8 5 9 7 6 1 4 3 3 4 2 6 8 5 3 7 9 1 7 1 3 9 2 4 8 5 6 9 6 1 5 3 7 2 8 4 2 8 7 4 1 9 6 3 5 3 4 5 2 8 6 1 7 9
  • 34. 正答の条件 ④どのブロックを見ても、重複する数字はない 「ブロック1内で重複する数字がない」条件 complete[Region1,Region1]  更に、全てのRegionについて言えるので、単に列挙すればいい complete[Region1, Region1] complete[Region1, Region2] complete[Region1, Region3] complete[Region2, Region1] complete[Region2, Region2] complete[Region2, Region3] complete[Region3, Region1] complete[Region3, Region2] complete[Region3, Region3]
  • 35. 初期条件  「最初から盤面に入ってい pred puzzle() { る数字」の集合は、全ての N1->N1->N5 + N1->N2->N3 + N1->N5->N7 盤面上の数字の部分集合だ + N2->N1->N6 + N2->N4->N1 + N2->N5->N9 + N2->N6->N5 よ!といっています + N3->N2->N9 + N3->N3->N8 + N3->N8->N6 + N4->N1->N8 + N4->N5->N6 + N4->N9->N3  要するに、ここに書いた番 + N5->N1->N4 + N5->N4->N8 + N5->N6->N3 + N5->N9->N1 号は盤面内にあることがこ + N6->N1->N7 + N6->N5->N2 + N6->N9->N6 れで保証されます + N7->N2->N6 + N7->N7->N2 + N7->N8->N8 + N8->N4->N4 + N8->N5->N1 + N8->N6->N9 + N8->N9->N5 + N9->N5->N8 + N9->N8->N7 + N9->N9->N9 in data }
  • 36. 正答の条件 pred complete(na: set Number, nb: set Number){ Number in na.(nb.data) }  まとめるとこうなるよ! pred rules(){ all n1,n2: Number | one n1.data[n2] all row: Number | complete[row, Number] all col: Number | complete[Number, col] complete[Region1, Region1] complete[Region1, Region2] complete[Region1, Region3] complete[Region2, Region1] complete[Region2, Region2] complete[Region2, Region3] complete[Region3, Region1] complete[Region3, Region2] complete[Region3, Region3] }
  • 37. 完成したソースコード abstract sig Number{data: Number -> Number} abstract sig Region1, Region2, Region3 extends Number{} one sig N1, N2, N3 extends Region1 {} one sig N4, N5, N6 extends Region2 {} one sig N7, N8, N9 extends Region3 {} pred complete(na: set Number, nb: set Number){ Number = na.(nb.data) } pred rules(){ pred puzzle() { all n1,n2: Number | one n1.data[n2] N1->N1->N5 + N1->N2->N3 + N1->N5->N7 all row: Number | complete[row, Number] + N2->N1->N6 + N2->N4->N1 + N2->N5->N9 + N2->N6->N5 all col: Number | complete[Number, col] + N3->N2->N9 + N3->N3->N8 + N3->N8->N6 complete[Region1, Region1] + N4->N1->N8 + N4->N5->N6 + N4->N9->N3 complete[Region1, Region2] + N5->N1->N4 + N5->N4->N8 + N5->N6->N3 + N5->N9->N1 complete[Region1, Region3] + N6->N1->N7 + N6->N5->N2 + N6->N9->N6 complete[Region2, Region1] + N7->N2->N6 + N7->N7->N2 + N7->N8->N8 complete[Region2, Region2] + N8->N4->N4 + N8->N5->N1 + N8->N6->N9 + N8->N9->N5 complete[Region2, Region3] + N9->N5->N8 + N9->N8->N7 + N9->N9->N9 in data complete[Region3, Region1] } complete[Region3, Region2] pred solve{ rules[] puzzle[] } complete[Region3, Region3] run solve }
  • 38. これだけなんです!  あとは実行するだけで、数独を解いてくれるらしいですよ!  Alloyまじかっけー  と、言うわけでやってみますね!
  • 40. やばすぎなのでは  Alloyさんちょっと何言ってるかわかんないですね・・・  Numberの3項関係として解答されるので、人間が見てもわけがわからな い!!!  と、言うわけでビジュアライザーつくりました
  • 41. ちゃんと動いた!  解き方は全く与えていないのに、正答の条件を定義するだけでちゃんと解が求 まる!  ちょっと書き換えるだけで、与えた盤面が正しいかどうかを調べるようにもで きそう
  • 42. まとめ  Alloyでパズルを解くには、“解き方を書く”のはなく、“解いた結果の条件”を 与えてやるとうまくいく  @qnighyさんはもっと短く(10行程度+問題の入力)解いてました、ぱない  https://gist.github.com/3478314  「解くことができる数独の問題」を作ることもできる(らしい)  他にも、色々なパズルが解ける(らしい)ので、是非挑戦してみるといいかも?
  • 43. 参考にしたページ  「Alloy4.0で数独パズル」 http://toshi.way-nifty.com/log/2008/05/alloy40_3b9e.html