どう対処すればよいかわからない問題に直面しています。従業員用のカレンダーを生成する必要があります。各従業員には特定の仕事上の制約があります(個人的なものもあれば、一般的なものもあります)。
私が使用しているもの:
問題のユーザーはカレンダーを扱う人です。私はすべての制約に従うカレンダーを自動的に生成するソリューションを構築しようとしています。解決策は、各医師の大きな設定入力「医師の追加」と「制約の追加」であり、次に「カレンダーの生成」ボタンです。これはユーザーにとって本当に基本的なことです。
私の問題:
実際の計画を生成する方法がわからない、ニューラルネットワーク、遺伝的アルゴリズムなどについて読んでいましたが、これらはすべて正しい解決策のように見えますが、実際にはそうではありません。
GAを見ると、与えられた母集団(私の問題)の解を見つけるために作られていますが、開始母集団はすでに与えられた制約のセットに従う必要があり、その後最適化されます。その場合、私の最初の人口はすでに解決策です。 「最適化」する必要はありません。 1人が月曜の夜に3日間続けて働くことは問題ではありませんが、実際に正しく、他の人が同じ量を働いているということです。私の問題はすでにGAの出発点で解決されているので、GAは「高度」すぎると思います。
しかし、繰り返しになりますが、GAは本当にこれのために作成されたように見えるので、正しく理解していない可能性があります。
とにかく、私はGA(またはニューラルネットワーク、またはそのようなもの)を使用したことがないので、そのような学習曲線に取り組む前に、正しいアプローチをとっていることを確認したいと思います。
私の質問:
私のような問題に対する良いアプローチ/アルゴリズム/テクニックは何だと思いますか?ガス?ニューラルネットワーク?他に完全に異なる何か?
私はすべて耳を傾けており、必要に応じて詳細を表示しますが、私は自分をかなり明確にしたと思います:)
遺伝的アルゴリズムとニューラルネットワークはここでは適していません。これらは、問題の十分な近似解を見つけるためのメタヒューリスティックです。特に、どちらも候補ソリューションを評価するためのコスト関数を見つける必要があります。このようなコスト関数を取得したら、このコストを最適化するアルゴリズムを手動で作成する方が簡単な場合があります。
これは重要な考えです。2つのスケジュールが与えられた場合、スケジュールAまたはスケジュールBが「より良い」かどうかを判断する方法が必要です。さまざまな基準を挙げましたが、それらがどのように関連しているかは明確ではありません。 1つの基準を満たさないと、ソリューション全体が失敗しますか?または、部分的に制約に失敗しただけで、他の制約よりも悪い解決策になりますか?
最も基本的なレベルでは、週を個別のタイムスロットに分割し、すべてのスロットと医師の組み合わせを総当たりにすることができます。ただし、ハードフェイル制約を使用して、この検索スペースをより扱いやすいサイズに減らすことができます。勤務時間と夜勤の制限は、このような検索スペースの制限に適しているようです。その後、何百もの候補ソリューションが残ります。
最適な候補ソリューションを選択するには、それらをランク付けする必要があります。これは、1つのソフト制約が他のすべてのソフト制約よりも明確に優先されている場合、かなり簡単です。医師が特定のシフトを実行できない場合は、そのシフトを実行したくない医師よりも重要です。しかし、私はあなたのためにこれらのルールを決定することはできません-それは管理上の決定です。 2つのソフト制約の優先順位が明確でない場合は、さらに困難になります。その場合、単一のメトリックで2つの制約の重要性を統合するある種のコスト関数を考え出す必要があります。
おそらく、いくつかの優先順位付けされた基準に従って、空白のタイムテーブルを埋める貪欲なアルゴリズムを構築します。これは最適なソリューションではないかもしれませんが、「最適」が実際に何を意味するかを哲学するよりもはるかに簡単です。
最初のステップとして、週末の夜勤を記入し、週末の夜勤を最も長く行っていない医師を選択し、「私はそこで働けない」というユーザーの希望も考慮に入れます。これらの願いが週ごとであり、継続的でないと仮定すると、これは、週末の夜に1週間働けない医師が次の週に選ばれることを意味します。
他の夜にも同様の手順を使用できます。ユーザーの希望を尊重した後、最も長い間夜勤をしていない人に応じて医師に記入します。この手順は、3番目の種類の時間帯でも同様に繰り返され、日が変わります。 2人のユーザーの希望を調整できない場合は、ユーザーの希望が許可された頻度を追跡し、許可された希望の少ない医師を優先することができます。
残念ながら、私はこのシステムをゲームするいくつかの方法を見ることができます。週末の夜勤で働くように選択された医師が「そこで働けない」という要求を出した場合、その選択は1週間遅れ、同僚の負担で週末の夜勤の頻度が減ります。拒否されたリクエストの数を確認するウィッシュ解決手順が実装されている場合、ユーザーはいくつかの不可能なリクエストを入力して、通過したい1つのリクエストをブーストできます。しかし、誠意があると(そして医師がお互いにシフトを入れ替えられる柔軟性がある)と仮定すると、そのようなアルゴリズムは十分な解決策になるはずです。
シミュレーテッドアニーリング を使用できます。
最初の仕事に着手する前に、私はそのようなことをしました-参照 https://vimeo.com/20610875 (2:50から始まるデモ、6:15からアルゴリズムが説明されています)。
シミュレーテッドアニーリングは遺伝的アルゴリズムの一種であり、(@ amonが 彼の答え で維持しているように)理論的には適切ではなかったかもしれませんが、実際には非常にうまく機能し、ほぼ同じ用途でしたあなたのケース。
ソースコードは入手可能(C#)ですが、機能しているのは恐ろしいことです。恐らく、それは数年前のことであり、autodidactでした。保守性については何も知りませんでした。それでも非常に良い結果が得られました。
とにかくそれがどのように機能するか:
開始点として1possible(あまり良くないかもしれませんが、物理的には可能かもしれません)タイムスケジュールを生成します。この時点では、遺伝的アルゴリズムは必要ありません。最初に見つけたソリューションにブルートフォースすることができます。私は backtracking を使用しました。計算の複雑さは、毎日のロータを個別に解決することで克服できます。ソリューションがまったくない場合(場合によっては)、この時点でそれを検出します。
ソリューションのプールを作成します-たとえば、最初にこのエントリーレベルのソリューションの100コピーを作成します。
すべてのソリューションをランダムに変更します。医師にお互いのシフトを入れ替えさせ、ランダムな医師をシフトから外して、ランダムに対応可能な担当者を配置します。
fitness function を使用して各ソリューションを評価し、それがどれほど優れているかを判断します。ある男が別の男よりも多くの夜働いていますか?ペナルティポイントを差し引きます。誰かが月曜日にやりたかったのに、そうしなかったのですか?ペナルティポイントを再度差し引きます。
言う-20-最高のソリューションを5つずつコピーし、残りの80をそれらで上書きして、次の世代に持ち込みます。適者生存。
すすぎと繰り返し。
数値は明らかに任意です。シナリオに最適な設定を見つけるために、パラメータをいじる必要がある場合があります。
ソリューションの変更に関しては、シミュレーテッドアニーリングによって温度と呼ばれるものが導入されます。基本的には、最初はソリューションをかなり変更し(たとえば、常に一度にシフトを10回入れ替えるようにして)、次の反復で徐々に攻撃性を弱め、より微調整(たとえば、ダウン)する必要があることを意味します1世代あたり2回だけ微調整を試みました)。
遺伝的アルゴリズム ここで適用されます。私の学部課程の間、私の同僚の一人があなたの非常に類似した問題について論文を書きました。
Job Shop Scheduling と Open Shop Scheduling または Flow Shop Scheduling を探すこともできます。
遺伝的アルゴリズムを使用するには、完全なソリューションは必要ありません。N個のランダムな候補から始めて、それぞれに fitness function を適用できます。次に例を示します。
生成するN個の候補 Xの中から最良のものを選択 、それらは制約に与える影響が少ない候補です。それらを使用して、数世代にわたって crossing および mutating を実行すると、良い解決策が得られる可能性があります。
以上のことをすべて話し合った結果、交差よりも突然変異に依存する遺伝的アルゴリズムを使用するたびに、実装が簡単になり、パフォーマンスが大幅に向上するシミュレーテッドアニーリングを開発できました。遺伝的アルゴリズムのコスト/適合性と突然変異関数は、おそらくシミュレーテッドアニーリングで使用されるものと非常に似ています。私はそこから始めます、@ Konrad Morawskiの答えを見てください