2

作業スケジューリングアプリケーションの場合、w週間(= 7w日)の可能な従業員スケジュールを多数生成する必要があります。従業員のスケジュールは、計画期間の各日のシフト(早朝、深夜、夜間、休日)のリストで構成されます。アプリケーションはJavaでプログラムされています。

現時点では、従業員のスケジュールを次のように表しています。

public class Schedule
{
    /** List with for every day of planning period the assigned shift */
    private Shift[] shiftlist = new Shift[Settings.schedule_days];

    /** Cost of schedule (for measuring its quality) */
    private double cost;

    // A list of variables, representing schedule properties
    // which are referenced often.
    // E.g.: number of workweekends, number of night shifts

    // Also some methods for updating / retrieving information
}

Shiftは、割り当てられたシフトを表す列挙型であり、次のように定義されます。

public enum Shift
{
    DAY, LATE, NIGHT, FREE;
}

列挙型宣言とプロパティを比較するメソッドにもいくつかのシフトプロパティがありますが、ここでは関係ないと思います。

すべての従業員は彼の可能なスケジュールのリストを持っています:

public class Employee
{
    /** Large set of possible schedules for planning period */
    public LinkedList<Schedule> generated_schedules;

    // Variables representing properties of employee
}

私の問題は、実際には50人の従業員がいて、従業員1人あたり100.000〜1.000.000の可能なスケジュールを生成したいということです。

スケジュールは実際にはすばやく生成され、コンピューターで8 GBのメモリを使用できるので、多くのスケジュールを保存できます。しかし、30〜40人の従業員の生成が終了すると、私の記憶はいっぱいになります。

誰かが私に与えた提案は、列挙型の配列の代わりに、割り当てられたシフトを表すために文字の配列を使用することです。これにより、使用するスペースが少なくなります。さらに、Scheduleオブジェクトのリストの代わりにchar配列のリストを使用する方が良いと彼は述べました。ただし、スケジュールのプロパティ(コストなど)をスケジュールの近くに保存することはできず、頻繁に再計算する必要があります。これは深刻な欠点になると思います。

この観察は確かに理にかなっていますか、それともより少ないスペースを使用するためにこの大量のデータを表現するためのより良い方法があると思いますか?

4

3 に答える 3

0

同様の「小さな」プロジェクトでの1つの経験:

ファイルシステムにも格納されている組み込みデータベースを使用することをお勧めします。SQLは醜いですが、手作業でコーディングされたコレクションウォークよりも優れたクエリを実行できます。メンテナンスが簡単です。

それで、メモリ消費の問題は議論の余地があります。

必要に応じて、たとえばeclipseLinkとORMなどのJPAを使用できます。

于 2012-09-14T12:14:56.273 に答える
0

メモリを削減したい場合は、現在最も多くのメモリを使用しているものと、そのデータ型についてどのような仮定を立てることができるかを判断する必要があります。この情報がなければ、あなたはただ推測しているでしょう。


一般的なアルゴリズムベースのアプローチを使用することをお勧めします。

例えば;

  • 1000のスケジュールのみを生成し、それらを評価できます。

  • トップ500、あなたは維持します

  • これらを使用して混合し、いくつかのランダムな突然変異を持つ次の1000を生成します。

最高のスコアが改善されなくなるまで繰り返します。

ポイントは; 別のアプローチを使用して、より少ない時間ではるかに少ないスケジュールを作成しながら、最適なソリューションに収束することができます。

于 2012-09-14T12:14:01.110 に答える
0

メモリ内のすべてのスケジュールを同時に必要とする場合、最もスペース効率の良いエンコーディングは、1 日あたり 2 ビットの BitSet を使用することです。

public class BitSetShiftList {
  private BitSet bitset;

  public void BitSetShiftList(int size) {
    bitset = new BitSet(size * 2);
  }

  public void setShift(int day, Shift shift) {
    int ordinal = shift.ordinal();
    assert ordinal >= 0 && ordinal <= 3;

    bitset.set(day * 2, (ordinal & 0x1) != 0);
    bitset.set(day * 2 + 1, (ordinal & 0x2) != 0);
  }

  public Shift getShift(int day) {
    int ordinal = (bitset.get(day * 2) ? 0x1 : 0x0) |
      (bitset.get(day * 2 + 1) ? 0x2 : 0x0);
    return Shift.values()[ordinal];
  }

}
于 2012-09-14T12:20:18.647 に答える