Alloy Analyzer チートシート(論理式の文法編)

Alloy Analyzer を使ってみようと思ってはや数ヶ月,いくつか文献を見たけど無定義で記号が使われたりしていたりでぶん投げ続けていますが,もう日本語で文献を調べるのはやめました.

初歩の初歩は [hoge lecture] でググるのが一番ですね.

ということで,ちまちまと Alloy Analyzer の記法を加筆修正していきます.

Alloy Analyzer の文法まとめ

オブジェクト

Alloy ではすべてのオブジェクト(スカラーや集合,二項関係など)を"関係"で表す.

  • 集合

    AddressBook = { (Book0), (Book1) }

    Name = { (Taro), (Hanako) }

    Address = { (Tokyo), (Osaka), (Fukuoka) }

  • スカラー:単行関係

    myAddr = { (Osaka) }

    myName = { (Taro) }

    myBook = { (Book0) }

  • 二項関係

    names = { (Book0, Taro), (Book0, Hanako) }

    ※当然だが関数ではない.

  • 三項関係

    addrs = { (Book0, Taro, Tokyo), (Book0, Hanako, Fukuoka), (Book1, Taro, Osaka), (Book1, Hanako, Fukuoka) }

特に,集合の元の個数は size,各元の列の個数を arity という.上記の三項関係の例の場合,size = 4, arity = 3 である.
また,n 項関係は列が n の,列名のない表と思える.ただし,列が入れ替われば当然 n 項関係としての意味合いは変わる.

定数扱いの集合

集合意味
none空集合
univ全体集合
iden恒等関係

定数扱いの集合の例

Name = { (N0), (N1), (N2) },

Addr = { (A0), (A1) }

のとき,

none = { },

univ = { (N0), (N1), (N2), (A0), (A1) },

iden = { (N0, N0), (N1, N1), (N2, N2), (A0, A0), (A1, A1) }

となる.

集合の演算子

演算子意味
+和集合
&共通部分
-差集合
in部分集合
=イコール
->直積

集合の演算の具体例

Name = { (N0), (N1), (N2) },

Alias = { (N1), (N2) },

Group = { (N0) },

RecentlyUsed = { (N0), (N2) }

Addr = { (A0), (A1) }

のとき,

演算演算結果
Alias + Group{ (N0), (N1), (N2) }
Alias & RecentlyUsed{ (N0) }
Name - RecentlyUsed{ (N1) }
Alias -> Addr{ (N1, A0), (N1, A1), (N2, A0), (N2, A1) }
RecentlyUsed in Aliasfalse
RecentlyUsed in Nametrue
Name = Group + Aliastrue

となる.

関係の Join

関係 p, q に対して,

  • p.q で「p の末尾と q の先頭での Join」を表し (dot join),
  • p[q] で q.p を表す (box join).

ただし,Join したあとは結びになった項は落とされる.

関係の Join の例

p = { (a, b), (a, c), (b, d) }, q = { (a, b, c), (b, c, d), (b, a, d), (c, c, b) }, r = { (c) }のとき,

JoinJoin 結果
p.q{ (a, c, d), (a, a, d) }
r.q{ (c, b) }
p[q]{ (c, c, d) }

単項演算子

ここでは

Node = { (N0), (N1), (N2), (N3) },

next = { (N0, N1), (N1, N2), (N2, N3) }

とする.

演算意味
~転置~next = { (N1, N0), (N2, N1), (N3, N2) }
^推移閉包. ^r = r + r.r + r.r.r + …^next = { (N0, N1), (N0, N2), (N0, N3), (N1, N2), (N1, N3), (N2, N3) }
*反射推移閉包. *r = iden + ^r*next = { (N0, N0), (N1, N1), (N2, N2), (N3, N3) } + ^next

制限とオーバーライド

特定の関係を取り出す手段に"制限"と"オーバーライド"がある.

Addr = { (A0) },

Name = { (N0), (N1), (N2) },

Alias = { (N0), (N1) },

address = { (N0, N1), (N1, N2), (N2, A0) },

workAddress = { (N0, N1), (N1, A1) }

とする.

演算意味
p <: qq の 1 要素目の p への制限Alias <: address = { ((N0, N1), (N1, N2) }(address のうち,左側が Alias に入っているやつ)
p :> qp 最終要素の q への制限address :> Name = { ((N0, N1), (N1, N2) }(address のうち,右側が Name に入っているやつ)
p ++ qp の中で,q と同じ 1 要素目を持つものを q の関係で置き換えるaddress ++ workAddress = { (N0, N1), (N1, A1), (N2, A0)}

意味合い的に,以下のようにも書ける:

p ++ q = p - (domain[q] <: p) + q ( p から,q と 1 列目がかぶっているものを引いておいて,その代わり q で置き換える).

bool 値の演算子

p, q を bool 値とする.

演算意味
!p, not pp でない
p && q, p and qp かつ q
p || q p or qP または q

F, G, H を論理式とする.

演算意味
F => GF && G ?!F || G ではなく??
F => G else H, F implies G else H(F && G) || ((!F) && H)
F <=> G, F iff GF => G and G => F

含意ではなく,if - else - っぽい.

限量子

  • all x: e | F
    F holds for all x in e.
  • all x: e1, y: e2 | F
    F holds for all x in e1 and all y in e2.
  • all x, y: e | F
    F holds for all x and y in e.
  • all disj x, y: e | F
    F holds for all dictinct element x and y in e.(多分)

なお,all の他には以下もある.

限量子意味
allfor all
somefor at least one
nono
loneat most one
oneexactly one

限量子は | までかかるように思われる.

  • some n: Name, a: Address | a in n.address

    ある n: Name とある a: Address があって,a は n の住所である.
    言い換えると,AddressBook は空でない.

集合の宣言

x: hoge e の形.hoge のところに色々入る.

宣言意味
x: set ex は e の部分集合
x: one ex は e の部分集合であって唯一の元をもつ
x: lone ex は e の部分集合であって元を高々一つもつ
x: some ex は e の空でない部分集合
x: ex: one e と同じ意味.x は e の元,に近いといえば近い.

関係の宣言

r: A hoge -> fuga B の形.

これが意味するところは,「A is mapped to fuga elements of B, and hoge elements of A is mapped to B」である.

例えば,members: Name lone -> some Addr は,どの Name にも必ず Addr が対応していて,かつどの Addr も高々一つの Name に対応している(どの Addr も,それを参照する Name を持たないか,持つとしてもちょうど 1 つだけである)とうことである.

hoge, fuga が省略されたときは,hoge も fuga も set として扱われる.

表現の限量子

some, no, lone, one を用いる.

no (address.Addr - Name) は,Addr へ飛ぶのは Name の元以外にない,といっている.

前に出した例では以下のようになる:

Addr = { (A0) },

Name = { (N0), (N1), (N2) },

address = { (N0, N1), (N1, N2), (N2, A0) }

とすると,address.Addr = { (N2) } なので,no (address.Addr - Name) が成り立っている.

集合,関係の生成

{ n: Name | no n.^address & Addr } の意味は,Addr へ推移されないような Name 全体の集合.

{ n: Name, a: Address | n -> a in ^address} の意味は,n -> a が address の推移閉包に含まれるということ.言い換えると, 到達可能な( 名前, アドレス )全体.

if と let

if は Alloy では f implies e1 else e2 と書く.

let は一時変数.

基数

意味
#r関係 r に含まれるタプルの個数
0, 1, ...整数
+プラス
-マイナス
=イコール
<小なり
>大なり
=<less than or equal to
>=greater than or equal to

all b: Bag | #b.marbles =< 3 は,どのバッグにも大理石が 3 個以下入っている,ということ.


ちまちま更新します.

コメント