関連記事
- OCL 演算 includes/excludes
集合を要素とする集合
VDM++ の set 型には、「集合を要素とする」集合を定義できます。これに準拠した事例を紹介します。
s1 = VDM_Set([1,2,3])
s2 = VDM_Set([4])
s3 = VDM_Set([])
s4 = VDM_Set([5,6])
print "s1:",s1
print "s2:",s2
print "s3:",s3
print "s4:",s4ss = VDM_Set([s1,s2,s3,s4])
print ">>> VDM_Set([s1,s2,s3,s4])"
print ss
まず、4つの集合 s1/s2/s3/s4 を作成します。次に、これらを要素とする集合 ss を作成します。このコードを実行すると、
s1: {1, 2, 3}
s2: {4}
s3: {}
s4: {5, 6}
>>> VDM_Set([s1,s2,s3,s4])
{{4}, {1, 2, 3}, {}, {5, 6}}
4つの集合を要素とする集合が得られます。このとき、要素の順序には、意味がありません。
要素の帰属関係
VDM++ の set 型には、集合に対する要素の帰属関係を定義できます。数学の世界では、ある要素 e が集合 S に含まれるか否かを、e∈S および e∉S と表現します。これを VDM++ では、次のように表現します。
3 in {3,1,2} = true
整数 3 は、集合の要素に含まれるので、true になります。
3 not in {3,1,2} = false
整数 3 は、集合の要素に「含まれる」ので、false になります。
0 not in {3,1,2} = true
整数 0 は、集合の要素に含まれないので、true になります。
{1,2} in {{1,2},{},{3}} = true
集合 {1,2} は、集合の要素に含まれるので、true になります。このように「集合を要素とする」集合に対しても、要素の帰属関係を判定できます。
事例:演算 in
VDM++ での演算 in に準拠した事例を紹介します。
s1 = VDM_Set(range(1,4))e = 3
print ">>> %s in %s"%(e,s1)
X = e in s1
print X; assert X is Truee = 0
print ">>> %s in %s"%(e,s1)
X = e in s1
print X; assert X is False
任意の要素が「含まれる」ことを判定するには、演算子 in を利用します。このコードを実行すると、
>>> 3 in {1, 2, 3}
1
>>> 0 in {1, 2, 3}
0
整数 3 は、集合 s の要素に含まれますが、整数 0 は、その要素に含まれません。
《Note》Python 2.5.x では、bool 型の値は、True/False と表示されます。ただし、Jython 1.x/2.2.x では、それぞれ 1/0 と表示されます。□
s1 = VDM_Set(range(1,4))e = 3
print ">>> %s not in %s"%(e,s1)
X = e not in s1
print X; assert X is Falsee = 0
print ">>> %s not in %s"%(e,s1)
X = e not in s1
print X; assert X is True
任意の要素が「含まれない」ことを判定するには、演算子 not in を利用します。このコードを実行すると、
>>> 3 not in {1, 2, 3}
0
>>> 0 not in {1, 2, 3}
1
整数 3 は、集合 s の要素に含まれませんが、整数 0 は、その要素に含まれます。
集合を要素とする集合についても、要素の帰属関係を判定できます。
s0 = VDM_Set()
s1 = VDM_Set(range(1,2))
s2 = VDM_Set(range(2,4))
ss = VDM_Set([s0,s1,s2])e = VDM_Set([2,3])
print ">>> %s in %s"%(e,s1)
X = e in ss
print X; assert X is Truee = VDM_Set([3])
print ">>> %s in %s"%(e,s1)
X = e in ss
print X; assert X is False
集合 ss は、3つの集合を要素とする集合です。このコードを実行すると、
>>> {2, 3} in {{}, {1}, {2, 3}}
1
>>> {3} in {{}, {1}, {2, 3}}
0
整数 {2,3} は、集合 ss の要素に含まれますが、整数 {3} は、その要素に含まれません。
《付記》集合 ss は、3つの集合を要素として含み、これらの(要素としての)集合の中には整数 3 を要素として含む集合があります。しかし、集合 {3} のように、整数 3 を要素とする集合は、これら(要素としての)3つの集合には含まれません。なぜなら、整数 3 と「整数 3 を要素とする」集合とは、別のオブジェクトだからです。これは、1つの文字と「1つの文字からなる」文字列とが、別のオブジェクトである状況と似ています。□
演算 in を実現する
VDM++ での演算 in に準拠するように、メソッド VDM_Set.__contains__ を実現します。
class VDM_Set:
def __contains__(s1,e):
"""
e in set s1
; A * set of A -> bool
;
; Membership
; tests if e is a member of the set s1
e not in set s1
; A * set of A -> bool
;
; Not membership
; tests if e is not a member of the set s1
"""
return e in s1.list
メソッド __contains__ では、演算子 in の動作を規定します。指定された e が、リスト s1.list に含まれるかを判定して、その結果をリターン値とします。
《Tips》演算子 in を実現するのに、Set 型で規定された他の演算子 in を再利用していることに注意してください。なぜなら、s1.list が VDM_Set のインスタンスなら、再帰的に __contains__ が呼び出される可能性があるからです。□
《Note》以前は、__contains__ 役割を __getitem__ が兼ねていました。今後は、関係演算子 in は __contains__ で、添字演算子 [] は __getitem__ で、役割分担を明確するのがよいでしょう。□
《Tips》OCL では、in と似た演算 includes が規定されています。
includes: Collection(t) × t → Boolean v∈C□
includes(object: T): Boolean
post: result = (self->count(object) > 0)
《Tips》OCL では、not in と似た演算 excludes が規定されています。
excludes: Collection(t) × t → Boolean v∉C□
excludes(object: T): Boolean
post: result = (self->count(object) = 0)