このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

自然数の区間をAlloyで書いてみる

今日もちょっとAlloyで遊んでみます。

ある目的から、自然数区間 {0, 1, 2, ..., n} の性質の一部を抽象した構造が欲しくなりました。その構造とは次のものです。

  1. サクセッサ(後者関数)に基づく全順序(線形順序)
  2. 2点間の距離

2点間の距離とは、x, y∈{0, 1, 2, ..., n} として、次のように定義されます。

  • δ(x, y) = |x - y|

ここでは便宜上引き算と絶対値で表現してますが、事前に引き算や絶対値を要求しているわけではありません。

とりあえず、サクセッサ(名前はnextにします)と順序<(名前はlt)、それと定数ゼロ(zero)、最後の数(last)を定義してみます。

-- 自然数の区間 {0, 1, 2, ..., n}
module interval

sig Interv {
 -- 後者
 next: lone Interv,
 -- 順序 <
 lt: set Interv
}

-- ゼロと最後の数
one sig zero, last extends Interv {}

-- nextに関する公理
fact next {
 -- lastのnextは存在しない
 no last.next

and
 -- last以外ではnextが定義されている
 all x: (Interv - last) |
   one x.next

and
 -- ゼロからの可達性
 zero.*next = Interv

}

-- ltに関する公理
fact lt {
 lt = ^next
}

不等号「<」に相当する関係ltを上では定義してますが、nextの推移的閉包に過ぎないし、^next と書いても同じなんで、下に出てくるコードでは特にltを定義はしてません。

さて、δ(x, y) = |x - y| に相当する関係が x.delta[y] = z となるように定義します。基本的に、δ(x, x) = 0 からはじまる再帰的な定義です。x ≦ y のときだけを考えた補助関数δ0を先に定義して、それの対称化としてδを定義しました。もっとうまいやり方/Alloyらしい書き方があるかも知れませんが、とりあえず最初に思いついた方法です。

-- 自然数の区間 {0, 1, 2, ..., n}
module interval

sig Interv {
 -- 後者
 next: lone Interv,
 -- 距離
 private delta0: Interv ->one Interv,
 delta: Interv ->one Interv
}

-- ゼロと最後の数
one sig zero, last extends Interv {}

-- nextに関する公理
fact next {
 -- lastのnextは存在しない
 no last.next

and
 -- last以外ではnextが一意に定義されている
 all x: (Interv - last) |
   one x.next

and
 -- ゼロからの可達性
 zero.*next = Interv

}

-- delta0に関する公理
fact delta0 {
 all x, y: Interv |
 {
   x.delta0[x] = zero
   -- x ≦ y ならば、定義されている範囲内で
   -- δ0(x, y.next) = δ0(x, y).next
   y in x.*next implies
     (x.delta0[y.next] in (x.delta[y]).next)
 }
}

-- deltaに関する公理
fact delta {
 all x, y: Interv |
   -- x ≦ y ならば、δ = δ0
   y in x.*next implies (delta = delta0)
   -- それ以外では、δ(x, y) = δ(y, x)
   else x.delta[y] = y.delta0[x]
}

このくらいの定義(Alloyコード)でも、未定義部分を考慮してなかったり、「<」と「≦」を取り違えたりと、何度も何度もAlloyアナライザーに事例(モデルインスタンス)を作らせないと正しく書けません。これ(↑)で正しい自信もありませんが、基数が2, 3の台集合上の構造としては意図どおりになっているみたいです。