添字の連続した部分の表現 ======================== 添字の連続した 3 つの部分の変数を記述してみましょう. 添字が等差数列の場合は単純です.:: >>> i = Element(value=range(5), name='i') # i in (0, 1, 2, 3, 4) >>> x = Variable(index=i, name='x') >>> i3 = Element(set=i.set[:-2], name='i3') # i3 in (0, 1, 2) >>> x[i3] + x[i3+1] + x[i3+2] ((x[i3]+x[(i3+1)[i3]][i3])[i3]+x[(i3+2)[i3]][i3]): x[0]+x[1]+x[2] x[1]+x[2]+x[3] x[2]+x[3]+x[4] では,文字列のように添字の順番に規則性がない場合はどうでしょうか. このような場合,連続した 2 つの部分であれば `pysimple.Set.next` メソッドを利用して表現することができます.:: >>> S = Set(value='ABCDE', name='S') >>> s = Element(set=S, name='s') # s in (A, B, C, D, E) >>> y = Variable(index=s, name='y') >>> s2 = Element(set=S[:-1], name='s2') # s2 in (A, B, C, D) >>> y[s2] + y[S.next(s2)] (y[s2]+y[S.next(s2)[s2]][s2]): y['A']+y['B'] y['B']+y['C'] y['C']+y['D'] y['D']+y['E'] しかし,この方法は 3 つの場合には適用できません. これは Set.next(Element) の戻り値は Parameter となるため, Set.next(Set.next(Element)) は Set.next(Parameter) となるためです.:: s3 = Element(set=S[:-2], name='s3') # s3 in (A, B, C) >>> S.next(S.next(s3)) TypeError: unhashable type: 'Parameter' これを回避する方法として,2 つ先の添字を対応させる Parameter を自分で作成してしまう方法が考えられます.:: >>> next2 = Parameter(index=s3, value={_s: S.next(S.next(_s)) for _s, in s3.set}, name='next2') >>> next2 next2['A']='C' next2['B']='D' next2['C']='E' >>> y[s3] + y[S.next(s3)] + y[next2[s3]] ((y[s3]+y[S.next(s3)[s3]][s3])[s3]+y[next2[s3]][s3]): y['A']+y['B']+y['C'] y['B']+y['C']+y['D'] y['C']+y['D']+y['E'] この考え方は汎用化することができ,連続した N つの部分の表現も可能となります.:: >>> N = 3 >>> k = Element(value=range(len(S)-N+1), name='k') >>> sk = Element(set=S[:N], name='sk') >>> nextk = Parameter(index=(k,sk), value={(kk, ssk): v for kk, in k.set for (ssk,), (v,) in zip(S[:N], S[kk:])}, name='nextk') >>> nextk nextk[0,'A']='A' nextk[0,'B']='B' nextk[0,'C']='C' nextk[1,'A']='B' nextk[1,'B']='C' nextk[1,'C']='D' nextk[2,'A']='C' nextk[2,'B']='D' nextk[2,'C']='E' >>> Sum(y[nextk[k,sk]], sk) Sum(y[nextk[k,sk]][k,sk], sk): y['A']+y['B']+y['C'] y['B']+y['C']+y['D'] y['C']+y['D']+y['E']