使用にあたっては、制限があります。
それは、排他的オブジェクトの集合であるということです。
シフト集合の時間和については、何らこの要件は、ありませんでした。なぜなら、シフト集合は、無条件に排他的オブジェクト集合になるからです。
例えば、
深準=深夜 |準夜
というシフト集合を考えたとき、深夜または、準夜勤となり、どちら一方がアサートされます。
両方同時に成立することはあり得ません。(一日内でのシフトは、唯一一つだけアサートされる、という原則の元で定義されています。)一方が成立したとき一方は成立しないこうした集合を排他的といういいます。ANDを取ると空集合となるのが特徴です。排他集合のとき、
成立するのは常に一つなので、一日の加算和時間は、
加算和=深夜*深夜の時間+準夜勤*準夜勤の時間+...
という式で書くことができます。
シフトのときは、何もしなくてもこれが成立していたので特に意識する必要はありません。
しかし、ユーザが書くフェーズオブジェクトが、排他的となる保証はありません。時間制約もしくは、整数計数を行う場合にはこれを意識する必要があります。
排他的オブジェクトの要件は、フルデコードして、少なくとも一つのフェーズで違うことです。
例えば、
午前働
午後働
前後働
の集合である働き集合は、3つのフェーズオブジェクトを持っています。この3つから2つを取る全ての組み合わせで、違う必要があります。実際、3C2=3通りの組み合わせ全てで違うので問題ない、ということが言えます。
午後働
前後働
の集合である働き集合は、3つのフェーズオブジェクトを持っています。この3つから2つを取る全ての組み合わせで、違う必要があります。実際、3C2=3通りの組み合わせ全てで違うので問題ない、ということが言えます。
排他的オブジェクトではない例、
午前カウント
午後カウント
の集合を考えましょう。ブランクは全てにマッチすると考えるので、排他的ではありません。
中々難しいですが、論よりランしても問題ありません。排他的オブジェクトかどうかは、次のC++アルゴリズムでチェックしており、違反する場合はエラーとなりコンパイル出来ません。なお、next_combinationについては、こちら。
bool phase_object_aggregate::do_exclusive_check(constraints& c)
{
vector>> input;
make_bitset_vec(c, input);
vector ca, cb;
for (size_t i = 0;i < input.size();i++) {
ca.push_back(i);
}
cb.push_back(0);
cb.push_back(1);
do
{//全ての2項組み合わせをチェックする
vector ::iterator im;
vector>> temp_list;
for (im = cb.begin();im != cb.end();im++) {
int j = (*im);
temp_list.push_back(input[j]);
}
assert(temp_list.size() == 2);
assert(temp_list[0].size() == temp_list[1].size());
bool success = false;
for (auto m = 0;m < temp_list[0].size();m++) {
if (temp_list[0][m]!=0 && temp_list[1][m]!=0) {//マッチチェックは両方0でないときだけ
bitset b = temp_list[0][m] & temp_list[1][m];//排他性のチェック ANDを取って空集合でなければアウト
if (b == 0) {
success=true;//一つのPhaseでもマッチしなかったらOK
}
}
}
if (!success) {//全Phaseで空集合でない →アウト
return false;
}
} while (stdcomb::next_combination(ca.begin(), ca.end(), cb.begin(), cb.end()));
set_exclusive_check_done();
return true;//全組み合わせでOKのときだけOK
}


0 件のコメント:
コメントを投稿