Decision Management 問題をGUIで解く

##はじめに
以下のサイトに問題が載っており、何人もの方が各々のツールで解いています。
https://dmcommunity.org/challenge/challenge-apr-2020/
この問題は、簡単なナーススケジューリング問題でもあり、GUIだけで解くことも可能です。GUIだけで解いた方はいないようですので、スケジュールナースを使って解いてみます。
##問題
上記サイトから引用します。
>
In a hospital, there has to be a doctor present at all times. In order to make sure this is the case, a planning is made for the next 7 days, starting on a monday. Each day consists of three shifts: an early shift, a late shift and a night shift.
>
Every shift needs to be assigned to a doctor. In total there are 5 doctors: every doctor has a list of available days, and some have special requirements. In general, the following rules apply:
>
1. A doctor can only work one shift per day.
2. A doctor should always be available for his shift (see table below)
3. If a doctor has the night shift, they either get the next day off, or the night shift again.
4. A doctor either works both days of the weekend, or none of the days.
5. A planning should be made in which every requirement is fulfilled.
>
|Name|Available|
|:---|:---|--:|
|Fleming|	Friday, Saturday, Sunday|
|Freud|	Every day early or late, never night|
|Heimlich|	Every day but neven the night shift on weekends|
|Eustachi|	Every day, every shift|
|Golgi|	Every day, every shift but at max 2 night shifts|


##問題の解き方
###スタッフの定義
スタッフの名前をコピペします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/16ab5f87-49ff-4785-5ba5-15e167512300.png)

##Dayの定義
月曜日から日曜までの一週間を定義しますが、スケジュールナースでは、制約開始日、制約終了日、表示開始日の3つをエントリします。
###制約開始日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/92c30d66-1942-1da7-4a38-a7077d4e1984.png)

###制約終了日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/6d02fec5-b495-2bdb-1385-77d43f72816f.png)

###表示開始日
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/db3ffeef-9d18-899f-e7e8-1131dcbe1768.png)

12月7日から、12月13日を使って月曜日から始まる一週間を定義しました。

##シフトの定義
問題文では、
1. an early shift
2. a late shift
3. a night shift
の3つを定義しています。スケジュールナースには、Least One/Most One 制約が組み込まれており、シフトがアクティブになるのは最小1個、最大1個となることが必要です。従って、休みに相当するシフトの定義も必要となります。以下のように4つのシフトを定義しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/f7885f31-906b-3ec5-9127-1ab91544668d.png)

以上で、スタッフ、Day,シフトの定義が完了しました。
##制約を一つづつ入力していく
##求解してみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/09e15e8f-c550-65e9-cbfe-2306c7232498.png)

この状態で求解してみると、プロジェクトファイルを作成しろと言ってくるので、適当な名前を付けて保存した後、求解します。すると、次のような画面となります。
未だ、制約を入れていないので、何であってもリーガルな解です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/7c2e1b5b-c32e-9338-f61e-5188cc48635f.png)

##スタッフの予定を制約する
Flemingさんは、金土日しか働かないので、月－木間は、休みを予定に入れてしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/603d41be-a94c-6b98-b702-d9a95defe4db.png)

FreudさんとHeimlichさんは、never night の日があります。シフト定義ではそのラベルがありませんので、定義を以下で追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/7eb49989-b38c-6b1a-9d96-c25228a590e0.png)

夜Xというラベルが出来たので、それを使って制約します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/4f291bca-0497-81a5-4f2e-e0d81de5d409.png)

##行制約　夜勤禁止パターン
次の制約を考えてみます。
 If a doctor has the night shift, they either get the next day off, or the night shift again.　夜勤の次の日は、休みか夜勤　
は、
夜勤の次の日は、（早晩または遅番）禁止
に等価です。
これは、次のように制約できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/82fd4d92-e9a7-2563-a8f1-967ace0c4956.png)

##行制約　週末1日出勤禁止パターン
A doctor either works both days of the weekend, or none of the days.
週末は、両方働くか、両方働かないかのいずれか。
は、
１．土曜日働いたら日曜日働かないことを禁止
２．日曜日働いたら土曜日働かないことを禁止
と等価です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/0c9cac5d-1073-4954-7409-c6b684e4b47b.png)
図中、✓は、否定を表しています。most one/least one　制約により
　　働くシフト集合＝✓休み
です。
##行制約　夜勤回数制約
Golgiさんは、夜勤回数が2回に制限されています。
この実装は、まず、夜勤回数という属性を定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/76b854ab-9f93-c448-ede4-431bfa344710.png)

すると、スタッフのところに属性項目が出現するので、Golgiさんだけ回数を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/e59f9078-0750-01ae-52d2-b29008893d47.png)

行制約は、制約タイプを最大ー最小数を指定します。上で数字があるのは、Golgiさんだけなので、Golgiさんだけ制約されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/0a4932cf-f3fb-5f01-ffdf-2aa096324d99.png)

以上で行制約の実装が終了しました。
##列制約　各シフトで1人を実装
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/b4384545-ddee-6da0-d926-f3dd451eb237.png)

以上で、制約全体の記述が終了しました。
##解
10解を出してみました。注意することは、解は、制約を満足しさえすれば、その他は、
何が出力されてもリーガルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/57589ded-74fb-cdb5-16f1-230553bad815.png)

##まとめ
例えば、一番目の解は、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916040/d27972e8-c6b7-bf3e-8b34-0f6a752961e8.png)

となっており、一見してGolgiさんは、実用的にはありえない勤務パターンであることがわかります。つまり実用的にするには、まだまだ制約を追加する必要がある、ということです。

英語版になりますが、動画は以下です。
https://youtu.be/pHYFd5IE0U0