python-constraint 学校の時間割
以下の問題を解いてみましょう。
問題
学校の時間割
ある学校では、次の科目を月曜日から金曜日の$5$日間の授業時間に割り当てる必要があります。
各科目は$1$回ずつ行われ、各科目の授業は$1$日1時間だけです。
- 数学(Math)
- 英語(English)
- 理科(Science)
- 社会(SocialStudies)
- 体育(PhysicalEducation)
条件:
- 数学は月曜日か火曜日に行われる必要があります。
- 英語は水曜日に行われる必要があります。
- 体育は金曜日に行われる必要があります。
この条件に従って、時間割を作成してください。
解法
Python-Constraintライブラリを使って、条件に合った時間割を求めます。
コード
以下のコードを実行して、解を求めます。
1 | from constraint import Problem, AllDifferentConstraint |
このコードでは、指定された条件に従って$5$日間の学校の時間割を作成します。
結果として、各曜日にどの科目を割り当てるかが表示されます。
ソースコード解説
以下は、ソースコードの詳細な説明です。
1. 必要なライブラリのインポート
1 | from constraint import Problem, AllDifferentConstraint |
constraintライブラリからProblemとAllDifferentConstraintをインポートしています。Problemは制約充足問題を定義するためのクラスです。AllDifferentConstraintはすべての変数に異なる値を割り当てる制約を定義するためのクラスです。
2. 科目と曜日のリスト定義
1 | # 科目のリスト |
subjectsは授業科目のリストです。daysは曜日のリストです。
3. 問題の作成
1 | # 問題を作成 |
Problemクラスのインスタンスを作成し、問題を定義します。
4. 変数の追加
1 | # 各曜日に科目を割り当てる |
- 各曜日に対して、可能な科目を変数として追加します。
addVariableメソッドを使用して、各曜日(変数)がsubjectsのいずれかの科目(値)を取ることを指定します。
5. 制約の追加
1 | # 各曜日には異なる科目が割り当てられるように制約を追加 |
AllDifferentConstraintを使用して、すべての曜日に異なる科目が割り当てられるように制約を追加します。
6. 特定の制約を定義
1 | # 数学は月曜日か火曜日に行われる必要がある |
- 特定の制約条件を関数として定義します。
math_on_monday_or_tuesdayは、数学が月曜日か火曜日に行われる制約です。english_on_wednesdayは、英語が水曜日に行われる制約です。pe_on_fridayは、体育が金曜日に行われる制約です。
7. 制約の追加
1 | # 制約を追加 |
- 定義した制約関数を問題に追加します。
math_on_monday_or_tuesdayを月曜日と火曜日に対して追加します。english_on_wednesdayを水曜日に対して追加します。pe_on_fridayを金曜日に対して追加します。
8. 解の求解
1 | # 解を求める |
getSolutionsメソッドを使用して、問題のすべての解を求めます。
9. 結果の表示
1 | # 結果を表示 |
- 解が見つかった場合、すべての解を表示します。
- 解が見つからなかった場合、その旨を表示します。
まとめ
このコードは、制約充足問題を用いて学校の時間割を作成するものです。
与えられた制約(曜日ごとに異なる科目を割り当て、特定の曜日に特定の科目を割り当てる)を満たすすべての解を求め、表示します。
結果解説
[実行結果]
{'Monday': 'SocialStudies', 'Tuesday': 'Math', 'Friday': 'PhysicalEducation', 'Wednesday': 'English', 'Thursday': 'Science'}
{'Monday': 'Science', 'Tuesday': 'Math', 'Friday': 'PhysicalEducation', 'Wednesday': 'English', 'Thursday': 'SocialStudies'}
{'Monday': 'Math', 'Tuesday': 'SocialStudies', 'Friday': 'PhysicalEducation', 'Wednesday': 'English', 'Thursday': 'Science'}
{'Monday': 'Math', 'Tuesday': 'Science', 'Friday': 'PhysicalEducation', 'Wednesday': 'English', 'Thursday': 'SocialStudies'}
これは、学校の時間割問題に対する解がいくつか見つかったことを示しています。
各解は、月曜日から金曜日までの各曜日にどの科目が割り当てられているかを示しています。
各解は異なる時間割を示していますが、いずれも指定された制約を満たしています。
それぞれの解について説明します:
解1:
- 月曜日: 社会(SocialStudies)
- 火曜日: 数学(Math)
- 水曜日: 英語(English)
- 木曜日: 理科(Science)
- 金曜日: 体育(PhysicalEducation)
解2:
- 月曜日: 理科(Science)
- 火曜日: 数学(Math)
- 水曜日: 英語(English)
- 木曜日: 社会(SocialStudies)
- 金曜日: 体育(PhysicalEducation)
解3:
- 月曜日: 数学(Math)
- 火曜日: 社会(SocialStudies)
- 水曜日: 英語(English)
- 木曜日: 理科(Science)
- 金曜日: 体育(PhysicalEducation)
解4:
- 月曜日: 数学(Math)
- 火曜日: 理科(Science)
- 水曜日: 英語(English)
- 木曜日: 社会(SocialStudies)
- 金曜日: 体育(PhysicalEducation)
これらの解は、以下の制約をすべて満たしています:
- 数学は月曜日か火曜日に行われる。
- 英語は水曜日に行われる。
- 体育は金曜日に行われる。
このように、制約を満たしつつ複数の異なる時間割が存在することがわかります。

