510 likes | 616 Views
Disciplined Software Engineering Lecture #13. Software Engineering Institute Carnegie Mellon University Pittsburgh, PA 15213 Sponsored by the U.S. Department of Defense. 設計検証 , 第2部. この講義は設計検証の第2部である。 話題は: トレース表 シンボリック実行 ケースチェッキング 数学的なプログラム検証 プログラムの証明. トレース表.
E N D
Disciplined Software Engineering Lecture #13 • Software Engineering Institute • Carnegie Mellon University • Pittsburgh, PA 15213 • Sponsored by the U.S. Department of Defense
設計検証, 第2部 • この講義は設計検証の第2部である。 • 話題は: • トレース表 • シンボリック実行 • ケースチェッキング • 数学的なプログラム検証 • プログラムの証明
トレース表 • トレース表は実行表と似ているがより一般的である。 • トレース表は個々のケースの検証よりもむしろ一般的なプログラム動作を調べる。 • トレース表は以下を使用する • シンボリック実行 • ケースチェッキング
シンボリック実行- 1 • シンボリック実行では • プログラムはシンボリックに表現される。 • プログラム動作は分析的に調べられる。 • シンボリック実行により一般的検証をする事が出来る。 • シンボリック実行は常に実際的であるとは限らない。
シンボリック実行- 2 • シンボリック実行のアプローチ手順は以下のとおりである • 代数的シンボルをプログラム変数に割り当てる • これらのシンボルを用いて1つ以上の方程式でプログラムを記述し直す • これらの方程式の動作を分析する
シンボリック実行- 3 • 尋ねるべきいくつかの質問 • プログラムはある結果に収束するか? • プログラムは正常および異常の双方の入力値に対してどのように動作するか? • プログラムは常に望ましい結果を作り出すか?
シンボリック実行例 • 次のような簡単なプログラム部分が与えられるとする • begin • V1 = V2 • V2 = V4 • V3 = V1 • V4 = V3 • end • V1, V2, V3, and V4のいろいろな値に対する結果はどんなものになるだろうか?
シンボリックトレース表 • この例に対するトレース表このようになる: • したがって、入力 A, B, C, Dに対する結果は B, D, B, B である。 V1 # 命令 V3 V4 V2 A C D B 初期値 1 V1 = V2 B 2 V2 = V4 D 3 B V3 = V1 4 B V4 = V3 最終値 B B D B
シンボリック実行演習 • 次のようなプログラムがどの値で終了するか決定せよ。 • Calculate(x: real) • if x>0 • x=sqrt(x)-1 • else • x= -x • if x<>0 • Calculate(x) • end.
演習結果- 1 • 変数は x1 および x2 によって表現することが出来る。 • 各サイクルの結果に対する方程式は • if x1>0: x2 = sqrt(x1) -1 • ifx1 <= 0:x2 = -x1 • である。
演習結果- 2 • x1 = 0 に対して, プログラムは第1サイクルで終了する。 • x1 = 1 に対して, プログラムは第1サイクルで終了する。 • x1 = -1 に対して, プログラムは第2サイクルで終了する。
演習結果- 3 • 後ろ向きに動かすと • x2が1であるためには, x1は4であるべきであろう。 • x2が4であるためには, x1は25であるべきであろう。 • X2が25であるためには, x1は676になるべきであろう。 • X2が676であるためには, x1は458329であるべきであろう。 • など • したがって、プログラムは入力値 +/- の 1, 4, 25, 676, 458329, 等に対して終了する。
演習結果- 4 • X1の他の大きな正または負の値に対して, x2 の値は • -1 と +1の間のゼロでないある数に収束するであろう。 • -1と +1の間のゼロでない値に対して何が起こるか?
演習結果- 5 • x1=a, a は非常に小さな数とすると • x2=sqrt(a)-1, 負の数 • 次に、 x2 は正にする • 次の2サイクルで, x2 は近似的に sqrt(a)/2, あるいは aより少し大きな数になる。 • したがって、小さな x1に対して, x2の値は、次第にx1より大きくなる。 • したがって X2 の値は 0に到達せず、1より小さなある数に収束するであろう。
演習結果- 6 • 値が収束する時, x1 = x2 = x でかつその結果は 次の方程式で与えられるであろう • sqrt(x) - 1 = -x • この方程式に対する解はつぎである • x = [3 - sqrt(5)]/2 = 0.381966 • したがって, プログラムは +/- 0.381966 の間を巡回することになるであろう。
シンボリック実行の利点 • シンボリックな証明は一般性を持ち得る • シンボリックな証明は典型的には他の方法より少ない作業で済む • シンボリックな証明はテストケースを実行するよりエラーを起こすことが少ない
シンボリック実行の欠点 • シンボリック実行はアルゴリズム的かつ代入問題を除いて使用することは難しい。 • シンボリック実行の証明は手作業であり、したがってエラーを起こしやすい。 • シンボリック実行は複雑な論理に対して使用することは難しい。
ケースチェッキング - 1 • ケースチェッキングには次のステップがある • 1. プログラムを調べ、プログラム動作のいろいろな カテゴリを決定する • 2. これらのカテゴリに対して、チェックすべきケースを 識別する • 3. 各ケースをチェックしそれらが全ての可能な状況を カバーしていることを保証する
ケースチェッキング - 2 • 4. トレース表をそれだけでか、シンボリック実行 あるいは帰納法による証明を併用するかによって、各ケースについてプログラム動作を調べる • 5. 全てのケースが検証されるとプログラム動作が 検証されたことになる
トレース表の例- 1 • ClearSpacesプログラムの要求は • 文字列から先頭および末尾の空白を除く • 埋め込まれた空白はそのままにしておく • 空の文字列に対しては状態値を0にする • 1空白からなる文字列に対しては状態値を1にする • 2つ以上の空白の文字列に対しては状態値を2にする • 空白以外の文字を含む文字列に対しては状態値を 3にする
トレース表の例- 2 • プログラムで末尾の空白を取り除くための部分は次である。 ClearSpaces(var Input: string; State: int) Length = length(Input) if Length > 0 repeat(until State=3 or Length=0) if Input[Length-1] = ‘ ‘ Length = Length - 1 if State < 2 State=State+1 else State = 3 until State=3 or Length=0
トレース表の例- 3 • 末尾の空白のケースを定義するため次の約束事を確立する • 1. メッセージ文字列は非空白文字で始まりかつ 終わる文字列である • 2. 入力文字列はm個のメッセージ文字とt個の後続 空白文字からなる • 3. m は >0 または 0 である • 4. t は >0 または 0 である
トレース表の例- 4 • 従って、全部で4つのケースがある。 • 1. 0-0: m = 0, t = 0 • 2. 0-t: m = 0, t > 0 • 3. m-0: m > 0, t = 0 • 4. m-t: m > 0, t > 0
トレース表の例- 5 • 戦略は最も適当な手法を何でも使うことによって • 各ケースでのプログラム動作を検証することである • 1. 0-0のケースは実行テーブルを用いて単独で チェックする • 2. 他のケースでは帰納的な証明を用いてチェック する • 3. 第12講で述べた実行表の手法を使って、 トレース表で各証明を行いなさい
プログラムの正当性の検証 • これらの手法はプログラムを数学の定理として扱うことに基づく • 設計や設計レビューで特に有用である • プログラム検証にはしばしば高度な推論が必要となるので、作業を注意深くチェックすることが重要である。
正当性検証 • 正当性検証アプローチでは次のことを行う. • すべてのプログラムケースを識別する • トレース表を用いて、全てのケースに対してプログラムが満足しなければならない全ての条件を評価する • 適切な所では帰納法による証明を用いる • 全てのケースについて全ての条件が満足されたら • プログラムは検証されたことになる • この検証アプローチはほとんどの設計構成体に適用できるが、本講ではループについてのみ述べる
ForLoop の検証- 1 • ForLoopは次の形式であると仮定する • ForLoop • for n = First to Last • begin • nPart • end
ForLoop の検証- 2 • for-loop条件では次の質問に対する答えが真であることが必要である • ForLoop = • FirstPart+SecondPart+...+LastPart • であるか?
ForLoop の例 - 1 • 次のプログラムがnの階乗を生成することを検証せよ • factorial(n) • begin • x=1 • for i=1 to n • x = x*i • return = x • end
ForLoop の例- 2 • 第一にケースを識別する。 • ケースはn=1とn>1である • n = 1 のケースに対しては • ForLoop = 1! = 1 • FirstPart+SecondPart+...=FirstPart = 1*1=1 • n=1のケースはかくして正しい
ForLoop の例- 3 • n>1 例えば3 に対しては • ForLoop = 3! = 6 • FirstPart+SecondPart+ThirdPart = 1*1*2*3 = 6 • n=3のケースはかくして真である
ForLoop の例- 4 • 次に、nの全てのより大きな値に対しての実行を検証するため、帰納法による証明を用いなさい • n=kに対して動作が検証されたと仮定する • ForLoop = k! • そして • FirstPart+...LastPart = 1*1*2*3*4*...*k = k!
ForLoop の例- 5 • さて、k+1に対しては • ForLoop = k!*(k+1) = (k+1)! • FirstPart+...LastPart = 1*1*2*3*4*...*k*(k+1) • = (k+1)! • かくてプログラムはk+1のとき正しい。従って帰納法によりn>=1なる全ての値に対して正しい
WhileLoop の検証- 1 • WhileLoopは次の形式を持つと仮定する • WhileLoop • while WhileTest • begin • LoopPart • end
WhileLoop の検証- 2 • 質問1。 WhileTestのどんなアーギュメントに対してもループが終了することが保証されるか? • 質問2。 WhileTestが真の時、次が成り立つか? • WhileLoop = LoopPart followed by WhileLoop? • (注: WhileLoop は LoopPart に WhileLoop が続く) • 質問3. WhileTestが偽の時、次が起こるか? • WhileLoop はidentityであるか • (注:identityとは条件が全く変わらないことをいう)
WhileLoop の例- 1 • 浮動小数点数を標準形にするため、プログラムの最初の部分を使いなさい。 • Expは正の整数である • Mant は小数点の前にゼロ以外の正の10進数字が来る • NormalizeReal(Mant, Exp, NegEx) • while Mant >= 10do • Mant= Mant/10 • ifNegEx then Exp=Exp-1 • elseExp = Exp + 1
WhileLoop の例- 2 • Expの値は重要ではないので、関心があるのは3つのケースである。 • 1. Mant <10 • 2. Mant = 10 • 3. Mant > 10 • これらのケースのそれぞれがNegEx が真と偽に対して調べられる
WhileLoop の例- 3 • 質問1. WhileTestのどんなアーギュメントに対してもループの終了が保証されるか ? • ケース1. Mant < 10ならwhileテストは直ちに成立しないのでループは終了する • ケース2.Mant = 10 ならwhileテストは1サイクルの後に成立しないのでループは終了する • どちらのケースでもNegExの値に関係なく終了する
WhileLoop の例- 4 • 質問1。続き • ケース3, Mant > 10のときは帰納法で示される • Mant = k*10**n, ここで 1 <= k < 10 • n=1なら1サイクル後にテストは条件が成立しなくなる • ある値n=mに対してテストが真ならmサイクル後にMant=k になる • かくてn=m+1に対してはmサイクル後にMant = k*10 となりもう1サイクル後にWhileTestは条件が成立しなくなる • NegExの値は結果に影響しないので質問1は全てのn>=1に対して成立する
WhileLoop の例- 5 • 質問2。 WhileTest が真の時、次は起こるか? • WhileLoop = LoopPart followed by WhileLoop? • (注: WhileLoop は LoopPart に WhileLoop が続く) • ケース1. Mant < 10は、WhileTestが決して真にならないのでこの条件はあてはまらない
WhileLoop の例- 6 • 他のケースを調べるため、このプログラムがWhileLoopと同じ結果になることをチェックしなさい(次のOHPで述べる) • Mant = Mant/10 • if NegEx then Exp=Exp-1 • else Exp = Exp + 1 • while Mant >= 10 do • Mant = Mant/10 • if NegEx then Exp=Exp-1 • else Exp = Exp + 1
WhileLoop の例- 7 • 質問2. WhileTestが真の時、次がおこるか? • WhileLoop = LoopPart followed by WhileLoop? • (注: WhileLoop は LoopPart に WhileLoop が続く) • ケース2 Mant = 10の時、NegExの値は関係ない • WhileLoop は1サイクルおこり, Mant = 1になる • LoopPart followed by WhileLoop はMant = 10で始まり LoopPart は値1で, そして WhileLoop は同じく値1で終わる。 • どちらも同じ結果になるので、答えは真である。
WhileLoop の例- 8 • 質問2。続き • ケース3、Mant > 10 の場合は帰納法で示される • Mant = k*10**n, ここで 1<=k<10 • n = 1の時は WhileLoop は1サイクルおこり、そしてLoopPart followed by WhileLoopは一度もおこらない。 • n > 1 のときは LoopPart followed by WhileLoopは1つ少ないサイクルおこり同じ結果となる。 • 質問2はかくて全てのケースで満足される。
WhileLoop の例 - 9 • 質問3 . WhileTestが偽のとき、WhileLoop はidentityであるか? • ケース1. Mant < 10 はWhileTestが偽となる唯一のケースである. • このケースはプログラムが実行されないので、条件は乱されないままである。それがIdentityの定義である。 • 質問3はかくて満足される。
RepeatUntil の検証- 1 • RepeatUntil は次の形式を持つ。 • RepeatUntil • begin • LoopPart • UntilTest • end
RepeatUntil の検証- 2 • Repeat-untilの検証は 次の3つの質問に対する答えが真の時満足される。 • 質問1. ループの終了がUntilTestのいかなるアーギュメントに対しても保証されるか? • 質問2. LoopPart のあとのUntilTest が偽のとき, • RepeatUntil = • LoopPart followed by RepeatUntil • であるか?
RepeatUntil の検証- 3 • 質問 3. LoopPart のあとのUntilTest が真のとき • RepeatUntil = LoopPartであるか? • The repeat-until の検証はWhileLoop と同じ論理形式に従うので例を示すことは省略する。
プログラム検証に対するコメント- 1 • 正しく行えば、これらの検証法は全く一般性を有しており、従ってプログラムの正当性を保証できる。 • 検証法は技巧が必要であり、スキルを必要とする。 • これらの手法を使おうとするのが望ましいが、疑いがあるときはトレース表や実行表を使ってチェックしなさい。
プログラム検証に対するコメント- 2 • 訓練をつめば、プログラム検証を非常に素早く行うことができるようになる。 • 起こり得る全てのケースを注意深く実行することで、 ほとんどの欠陥を手早く見つけることができる • ループ終了テストは他の方法では無限ループを確認することが困難なので特に重要である。
講義13の演習課題 • さあ、最後レポートにとりかかろう • 中間レポートを作成したプロセスを更新して、それを使って最後レポートを作成しよう。 • 更新したプロセス、作業の計画、作業の実データ、そして最後レポートを提出しよう。 • レポートの仕様は付録Dにある。