従業員の勤務条件とシフト枠を登録すると、全部の条件を満たす割り当てを制約充足ソルバー(OR-Tools CP-SAT)が探すWebアプリ。全1画面。
このアプリの本体は「シフトを組む」ことではなく、組めなかったときの返し方にある。 条件同士が矛盾していて解が存在しない場合、ふつうのツールは「作成できません」で止まる。このアプリは 「この3つの条件は同時には満たせません」と矛盾の当事者だけを名指しし、そのうち1つを外して計算し直して、本当に解けることを確認してから出す。
小さな店のシフトが組めないとき、原因は「人が足りない」ではなく「条件同士が噛み合っていない」ことが多い。 金曜の閉め作業と土曜の開店作業を任せられるのが1人しかいなければ、その人の休息時間は自動的に10時間になる。 最低休息を11時間と決めている限り、この2枠は永久に埋まらない。人数を増やしても、鍵を任せられる人が増えなければ解決しない。
紙とエクセルでこれを詰めるのは、組み合わせが指数的に増えるので人間には向いていない。 そして「どこが悪いのか」が分からないまま、店長が毎月数時間かけて総当たりで探すことになる。
そこで、解けるシフトを出すことよりも「なぜ解けないかを、条件の名前で言い当てること」を中心に据えた。
CP-SATには、制約を「仮定(assumption)」として渡すと、矛盾したときに同時には成立し得ない仮定の組(UNSATコア)を返す機能がある。 このアプリは緩められる条件(各枠の必要人数、各人の週上限時間・連勤上限・最低休息)をすべて仮定として渡しているので、 返ってくる矛盾の原因は推測でも当てずっぽうでもなく、ソルバーが計算した結果そのものになる。
さらに「1つ緩めれば解ける」と言うだけでは信用できないので、実際にその条件を外してもう一度解き直し、解が出たことを確認してから画面に出している。
飲食店・小売など、数名〜十数名のスタッフを週単位で回している店の、翌週分のシフトを作る場面。
判断そのものは代行しない。労働条件を緩めるかどうかは経営判断であり、画面上部にも「本ツールは労務管理の意思決定を支援するものであり、労働基準法などの法令適合を保証するものではありません」と明記してある。
①従業員の勤務条件と、埋めたいシフト枠を登録する。

左が従業員。スキル・週の上限時間・最低休息時間・連勤上限・出られない曜日を1人ずつ入れる。右がシフト枠で、曜日・時間帯・必要なスキル・必要人数を入れる。 画面はこの1枚だけで、登録も実行も結果もここに出る。
②「スケジュールを作成」を押す。条件が矛盾していると、原因になっている条件だけが名指しで出る。

この例では「金曜18:00-22:00(開閉店)の必要人数1人」「土曜08:00-12:00(開閉店)の必要人数1人」「田中けんじさんの最低休息11時間」の3つが挙がっている。 開閉店を任せられるのが田中さん1人しかいないため、金曜の閉めから土曜の開店までが10時間になり、最低休息11時間と両立しない。人数の話ではなく、この3つが同時に立たないという話であることが読み取れる。
下の緑の枠が緩和案。3つのうち1つを外して計算し直した結果が入っており、「解けると言っているだけ」ではないことを示している。 なお、緩和で外れた開閉店の2枠は緩和案の表には現れない(必要人数を満たす条件そのものを外しているため)。埋まらない枠がどれかも、そこから分かる。
③条件を1つ緩めて、もう一度押す。今度は全枠が埋まる。

田中さんの最低休息を11時間から10時間に変えて再実行した結果。12枠すべてに担当が付き、金曜の閉めと土曜の開店も田中さんで埋まっている。 提示された条件を人が判断して直すと、そのまま答えになるという流れ。
④スマホでも同じ内容が読める。

矛盾している条件と緩和案は、店の現場でその場で確認することが多い情報なので、狭い画面でも折り返して読めるようにしてある(専用のモバイル用レイアウトは作っていない)。
PYTHONIOENCODING=utf-8 を設定せずに起動すると、矛盾した条件の説明が文字化けする(起動側で吸収しており、アプリ側では未対応)