第 6 章 HCC での処理アルゴリズムの設計 27
6.3 制約階層化の3つの手法案
6.3.1 書き換え規則アルゴリズム
ユーザに記述してもらう理想とする(制約の階層化を意識しない)ソースから,
Hybrid CCで矛盾の生じないソースへ変換するプリコンパイラをつくる.次頁に
載せている評価基準に従い,規則を保ちつつ書き換える処理系を作成する.
次頁の図はプリコンパイラからHCC処理系へと計算する処理の流れ図である.
計算の流れ概念図
階層構造間の評価基準として次を採用する.
¶ ³
if S(C1)≠φ then {
if S(C1)∩S(C2)≠φ then S(H)=S(C1)∩S(C2) else
S(H)=S(C1) }
else
S(H)=S(C2)
---C1,C2は制約
S(C)は制約Cから求まる解集合 S(H)は求める解集合
Strong C1 Weak C2
µ ´
上記のアルゴリズムは最もシンプルな2層の制約階層処理方式で,強い制約をC1, 弱い制約をC2とすると,
• C1が存在しないならばH =C2
• C1が存在し,C1∩C2の解が空集合にならなければH =C1∩C2
• ∩
簡単な例題における処理の流れ
以下のコードはボールを自由落下させ,地面に衝突しては繰り返すモデルである.
現状の処理系におけるユーザの記述
¶ ³
y = 10, y’ = 0, hence {
cont(y), if(y=0) then{
y’= -0.8*prev(y’) }else {
y’’= -9.8 }
µ} ´
階層化プリコンパイラ実行前のユーザの記述
¶ ³
y = 10, y’ = 0, hence {
cont(y),
weak y’’=-9.8,
strong if(y=0) then y’= -0.8*prev(y’)
µ} ´
階層化プリコンパイラ実行後のファイル
¶ ³
y = 10, y’ = 0, hence {
cont(y),
if(y=0) then y’=-0.8*prev(y’), /*以下を自動的に追加*/
if (y’=-0.8*prev(y’)) then { if(y=0) then{
if(y’’=-9.8 && y’=-0.8*prev(y’)) then { y’’=-9.8, y’=-0.8*prev(y’)
},
unless(y’’=-9.8 && y’=-0.8*prev(y’)) then{
y’=-0.8*prev(y’) }
} },
unless (y’=-0.8*prev(y’)) then y’’=-9.8
µ ´
4行目のif(y= 0) then y′ =−0.8∗prev(y′)は不必要に思うかもしれない.しか し,現状のHCC処理系のままでは追加部分のif文は解釈されいため必要となる.
問題点1
プリコンパイラ実行後のファイルはこのままではHCC処理系はエラーを起こし て終了してしまう.原因はソースコード最後の行のunless (y′ = −0.8∗prev(y’)) then y′′ =−9.8である.
下図の○の部分前までずっとunless (偽) then y′′ = −9.8がリダクションされ y′′ =−9.8という制約が有効になっていた.折り返しの部分を制約y′′ =−9.8を 用いて計算するとy′ =−0.8∗prev(y′)が真となる場合に遭遇する.これはHCC 処理系ではデフォルトエラーとなる.
問題1の改良と実行結果
これを回避するためにy′ =−0.8∗prev(y′)の部分にタグを代わりに使用し改良を 施す.この改良によって,同様な不具合はなく動くことを確認した.
問題点2
このコードは階層化プリコンパイラを実行後のソースである.
¶ ³
y = 10, y’ = 0, x = 0, x’ = 1, always {
cont(y),cont(x),
if(y=0) then {A, y’ = -0.8 * prev(y’)},
if(x=20) then {B, x’=-prev(x’)} else {C, x’’=0}, /*以下追加コード*/
if A then {
if(y’’=-9.8 && A) then { y’’=-9.8, y’=-0.8*prev(y’) },
unless(y’’=-9.8 && A) then{
y’=-0.8*prev(y’) }
},
if B then {
if(y’’=-9.8 && B) then { y’’=-9.8, x’=-prev(x’) },
unless(y’’=-9.8 && B) then{
x’=-prev(x’) }
},
if C then {
if(y’’=-9.8 && C) then { *
y’’=-9.8, x’’=0 *
}, *
unless(y’’=-9.8 && C) then{
x’’=0 }
},
unless (A||B||C) then y’’=-9.8 **
µ} ´
前頁のコードはweak制約を2変数にして検証を行ったものである.
この実験により,ある時間∗で示した行が真とならなければいけないところを∗∗
の行の条件が有効になることで妨げる結果となってしまった.
問題2の改良と実行結果
そこで∗∗の行の判定を変数ごとに区切って行う必要があると考え、Unless A then y′′ = −9.8としてユーザにweak制約で指定する変数を記述させる方法で改良し た.
考察
この書き換え規則によるプリコンパイラを作る方法での階層化は,グローバル変 数をデフォルト制約として扱う場合,有効である(有効性を示すコードを付録に 添付してある).しかし,デフォルト制約を時間ごとに切り替えることには不向き であり,3階層以上の階層構造を作るには問題2での改良は使用できない.例え 仮に3階層以上にも適用可能であったとしても,指定変数が増えすぎ,ユーザの 記述が煩雑となり可読性に優れる改良にはならないことが容易に推測されるため である.