職人15人・30現場の割り振りを、整数計画と順番決め(貪欲法)で比べた架空のデータ20組の実験

職人の割り振りの最適化とは、技能・移動距離・休みの条件を守ったまま、職人と現場の組み合わせを計算で決めることです。職人15人・30現場の1週間を架空のデータ20組で試すと、整数計画は1組あたり中央値0.065秒で、条件違反0件の割り振りを出しました。ベテランの順番決めを再現した方法では、20組とも枠が埋まらず、合計92枠が残りました。現場のまどの実験です。(2026年10月時点)
全体の流れと費用は現場管理アプリの独自開発のページにまとめています。
要点
- 職人15人・30現場・1週間の割り振りは、整数計画なら1組あたり中央値0.065秒で、条件違反0件の案が出ました(架空データ20組)。
- ベテランの順番決めを再現した方法では、20組すべてで枠が埋まらず、条件を守ったまま埋まらない枠が合計92件ありました。
- 順番決めで空き枠を無理に埋めると、片道20km超が71枠、週6日出勤が18人など、違反と残った空きが20組で107件になりました。
- 職人60人・現場120件に増やしても、整数計画の所要時間は中央値0.24秒で、3組とも最適解が出ました。
目次
職人15人・30現場の割り振りは、自動にすると何秒で組めますか?
1秒かかりませんでした。現場のまどの実験では、職人15人・30現場・1週間(月〜土)の架空のデータ20組を整数計画で解きました。1組あたり中央値0.065秒、最も遅い組でも0.14秒で、条件をすべて守る割り振りが出ています。
比べたのは、ベテランの手配担当の順番決めをPythonで再現した方法(貪欲法)です。人が手で1組を組む時間は、この実験では測っていません。結果は次のとおりで、順番決めは20組すべてで、条件を守ったまま埋まらない枠が残りました。
| 比べた数(20組) | 順番決めの再現(貪欲法) | 整数計画(CP-SAT) |
|---|---|---|
| 条件を守ったまま埋まらない枠(件) | 92 | 0 |
| 空き枠を無理に埋めた後の違反と空き(件) | 107 | 0 |
| 移動距離の合計の中央値(km、1組) | 703 | 668 |
| 同じ現場の担当替え(回、合計) | 95 | 61 |
| 1組を組む時間の中央値(秒) | 0.002 | 0.065 |
実験では、どんな条件で割り振ったのですか?
手配担当がホワイトボードの前で頭に入れている条件を、5つの決まりにしました。技能、自宅から現場までの距離、週の出勤日数などです。データは乱数で作った架空の会社で、実在の会社の数字ではありません。
- 現場の工種(大工・内装・電気・設備)の技能を持つ職人だけを入れる
- 自宅から現場まで、片道の直線距離20km以内
- 1人1日1現場で、出勤は週5日まで
- 2人で入る現場には、職長を1人入れる
- 現場ごとの必要人数(1〜2人)をちょうど満たす
職人15人は大工5・内装4・電気3・設備3人で、5人が職長、2人が2つの技能を持ちます。現場30件は1〜3日の工事で、必要な枠は1組52〜68枠でした。どの組も、5つの条件を守る割り振りが少なくとも1つある仕事だけを受けた状態にしています。
整数計画では、ある職人がある日にある現場へ入るなら1、入らないなら0という変数を置き、条件を式にします。目的は移動距離の合計と担当替えの少なさです。要点を少し短くすると次の数行で、全体は実験の台本とデータ(zip)の craftsman_assignment.py にあります。
for s, S in enumerate(sites):
for d in S['days']:
m.add(sum(x[w, s, d] for w in W if (w, s, d) in x) == S['crew']) # 必要人数ちょうど
for w in W:
for d in range(DAYS):
m.add(sum(v for (ww, s, dd), v in x.items() if ww == w and dd == d) <= 1) # 1日1現場
m.add(sum(v for (ww, s, dd), v in x.items() if ww == w) <= MAX_DAYS) # 週5日まで
ベテランの順番決めは、どこで行き詰まるのですか?
同じ日の職人の取り合いで行き詰まります。受注順に近い人から入れていくと、先に見た現場が人を取ってしまいます。その人が、後の現場にとって20km以内で唯一の候補だったことがあるからです。
再現したやり方では、日ごとに受注順で現場を見ます。そして①昨日と同じ人、②職長が要るなら近い職長、③近い順に空いている人、を入れます。1つ1つの判断は手配として自然ですが、週全体や後ろの現場を見ていません。
条件を守ったまま埋まらなかった92枠は、月曜3・火曜21・水曜24・木曜13・金曜12・土曜19でした。月曜以外のどの日にも出ています。
実際の手配では、この空き枠が前日夜の電話になります。遠い現場を頼むか、休みの日に出てもらうかで、条件を破って埋めることになります。
実験で空き枠を条件を外して埋めると、20組の合計で片道20km超が71枠、週6日出勤が18人、職長のいない2人の現場が10枠になりました。それでも8枠は埋まりませんでした。整数計画は週全体を一度に見るので、こうした取り合いを先に避けられます。
現場や職人が増えると、計算は遅くなりませんか?
少しずつ遅くなりますが、1秒には届きませんでした。職人60人・現場120件の1週間でも、整数計画の所要時間は中央値0.24秒で、3組とも最適解が出ています。
人数と現場の数は、15人・30件から60人・120件まで4段階に増やし、各3組の架空データで測りました。中央値は0.03秒、0.11秒、0.16秒、0.24秒で、12組の中で最も遅かったのは45人・90件の0.34秒です。どの組も、条件をすべて守る割り振りが出ました。
ただし、この実験は期間が1週間で、条件も5つだけです。期間を1か月に延ばしたり、重機や移動時間を条件に足したりすると、変数が増えて時間は延びます。そのときは計算に上限の秒数を決め、その時点で一番良い案を出す使い方にします。コードでは、上限を max_time_in_seconds で指定しています。
自動の割り振りに任せられないことは、何ですか?
職人どうしの相性、元請の担当者との相性、当日の体調のように、式にしていない事情です。計算は書かれた条件しか守らないので、出てきた案は手配担当が見て直し、確定する形にします。
国土交通省の資料では、2024年平均の建設業就業者のうち55歳以上が36.7%でした。手配の段取りがベテラン1人の頭の中にしかないと、その人が休むと組めなくなります。条件を5つの決まりのように書き出すと、それ自体が引き継ぎの資料になります。
この実験には限界もあります。データは架空で、距離は道路ではなく直線、移動時間や渋滞、雨の日は入れていません。重機とオペレーターの割り当ては重機とオペレーターの配車を前日夜の電話から外すにはで計算しています。ホワイトボードから移す順番は、職人の手配をアプリへ移す手順にまとめました。
割り振りを計算にする前の段階として、手配ボードで同じ職人を同じ日に2つの現場へ入れていないかを検査するルールと、その見逃しの数は職人の手配ミスは、ルールで何件見つけられる?に載せています。
職人の割り振りを自動にする相談をするには?
御社の職人と現場の条件で、割り振りの案がどこまで出せるかは、現場のまどの相談で一緒に確かめられます(無料で相談する)。何をどう頼むか決まっていなくても大丈夫です。御社のやり方に合わせて、進め方を一緒に考えます。準備は要りません。
よくある質問
- 職人の希望休も、条件に入れられますか?
- はい。希望休の日はその職人を入れない、という条件を1行足せば入ります。実験の「週5日まで」と同じ書き方です。
- 自動で出た割り振りは、そのまま職人に送るのですか?
- いいえ。案として画面に出し、手配の担当者が直してから確定する形にします。相性や当日の事情は、人が足すほうが確かです。
- 雨で現場が中止になったら、組み直せますか?
- はい。中止の現場を外して、もう一度計算すれば、条件を守った組み直し案が1秒かからずに出ます。実験の規模では1組0.14秒以内でした。
- 条件を守る割り振りが1つもないときは、どうなりますか?
- 計算は「解なし」と答えます。そのときは、どの条件をゆるめれば組めるかを画面に出し、人が決める形にします。
出典
- Google OR-Tools「Solving an Assignment Problem」(MIP と CP-SAT で割り当て問題を解く公式の例。2024-08-28 更新)(2026年10月16日確認)
- 国土交通省 改正建設業法「令和7年12月施行分」説明会資料(2026-01-27 掲載。建設業就業者の55歳以上 36.7%、令和6年平均、元データは総務省「労働力調査」)(2026年10月16日確認)
- 現場のまどの実験(2026年10月16日、架空データ20組・職人15人・現場30件・月〜土、OR-Tools 9.15 CP-SAT、Python 3.14、Ryzen 7 7735U)。台本は実験の台本とデータのzipの craftsman_assignment.py(2026年10月16日確認)


