外部制約の例  
   

例で、外部制約の記述の仕方を見ていきます。

1. AならばBは、どう記述する?


例えば、AさんがA勤務なら、BさんもA勤務である。というような、制約です。これは、GUIのペア制約そのものです。
また、XX日が勤務なら△日は勤務ではない、という具合に、実務場面で、よく出くわす記述でもあります。 プログラムならば、if 〜 という記述ですが、制約ではどう記述すればよいでしょうか?

結論から書くと

AならばBは、!A | B 

になります。感覚で言うと、AならばBは、A & B としたくなります。でもこれは、間違いです。
試しに、
次のように記述しました。菅原がB勤務なら、渡辺もB勤務 という意図の記述のつもりで、

for (day in 全日){
        $And(X[菅原][day][B],X[渡辺][day][B] );
}

すると、全日、一緒のシフトになってしまいました。

そのように記述してしますから当然ですね。
欲しい記述は、菅原がB勤務だった場合には、渡辺もB勤務であって、全日同じ勤務Bである、という上の記述とは異なります。

AならばBは、(逆に考えて)A &!B が禁止と考えます。つまり菅原がB勤務であって、渡辺がB勤務でない、が禁止。

すると
!(A&!B)=!A | B
になりました。

真理値表でも考えてみましょう。

A B 結果 備考
菅原B勤務、かつ渡辺B勤務はあり
菅原B勤務、かつ渡辺Bでないはあってはならない
0 0 菅原B勤務でない かつ、渡辺B勤務でないはあってもよい
0 1 1 菅原B勤務でない かつ、渡辺B勤務はあってもよい

AB+!A!B+!AB
= AB+ !A(!B+B)
=AB+!A
=AB+!A(1+B)
=AB+!AB+!A
=B(A+!A)+!A
=B+!A

となり、いずれの考え方でも、!A |Bになりました。(Q.E.D.)

これは、論理包含と言われるもので、Weipediaに議論が詳しく載っています。(最後に、論理学における「P ならば Q」は、「P でない、と Q である、の少なくとも一方が正しい」の短い言い換えなのである と言い切っています。)

よって、次のような記述が正しい記述になります。

for (day in 全日){
        $Or( $Inv(X[菅原][day][B]),
             X[渡辺][day][B] 
       );//菅原がシフトBなら渡辺もシフトB

        //上の例の検証のために次を追加
        if (day in 木){//菅原の木曜日はシフトBを強制
                $And(X[菅原][day][B]);
        }
}

結果、次のように意図通りに、動作しました。



AならばB ソフト制約記述の仕方

ソフト制約の記述が、ハード制約とは真逆であることは、前に述べました。この場合、上の真逆は、望ましくない状態、つまり、A &!B をエラーとしてカウントすればよいことが分かります。
.

for (day in 全日){
        S20:$And( X[菅原][day][B],
             $Inv(X[渡辺][day][B]) 
       );//菅原がシフトBかつ、渡辺がシフトBでない、は望ましくない

        //上の例の検証のために次を追加
        if (day in 木){//菅原の木曜日はシフトBを強制
                $And(X[菅原][day][B]);
        }else {
                $And(X[菅原][day][C]);
        }

}

この結果は次です。


木曜日のシフトが菅原と渡辺でシフト2で一致しており、ハード制約で実施した場合と同じ結果となっています。


外来から深夜入りも可能(ただしMax2名まで)

この制約もGUIでは不可能な制約です。この仕様の背景を看護師長さんに教えてもらいました。

「自分で作成すると(スケジュールナースを使わずに)、希望などにより内科外来に行ける人がいなくなり、深夜入りの人に行って貰っています。
日中の様子が分からないまま深夜に入るので、できたら半分の人が分かればいいかなと考えただけです。外来→深夜パターンも禁止し作成できるならそのほうが望ましいです。」

外来勤務は、4名です。 このスタッフ全員が深夜勤務入りしてしまうと日勤の様子が分かる人がいなくなるので最大2名を許容の範囲としたい(できれば0)という要求です。これをどのように考え実装すればよいでしょうか?

考え方の手順としては、

  1. 「できれば」0に注目し、ソフト制約であることを見破る
  2. ソフト制約であるなら、エラーをカウントすればよい
  3. エラーは、望ましくない勤務パターンとすればよい
  4. エラーをカウントしその日のエラーが2個までならソフトエラー範囲。3個は、ハードエラー(解なし)とする 


と考えていけば実装できそうです。このように行と列と両方に跨る制約は、外部制約の出番です。



[Prev] [Next] [Index] [Home]