61 const std::size_t n = pred.
rows();
62 if (pred.
cols() != n)
throw InputError(
"fj_dag_makespan: pred must be square");
63 if (n < 1)
throw InputError(
"fj_dag_makespan: at least one task is required");
64 if (n > 20)
throw InputError(
"fj_dag_makespan: the completed-set sweep enumerates 2^n states");
65 if (rate.
rows() != n || rate.
cols() != n)
66 throw InputError(
"fj_dag_makespan: the rate table must be n by n");
68 for (std::size_t i = 0; i < n; ++i)
69 for (std::size_t k = 0; k < n; ++k)
70 if (!(rate(i, k) > zero))
71 throw InputError(
"fj_dag_makespan: all completion rates must be positive");
74 std::vector<std::size_t> predmask(n, 0);
75 std::vector<long> indeg(n, 0);
76 for (std::size_t j = 0; j < n; ++j)
77 for (std::size_t i = 0; i < n; ++i)
78 if (!(pred(i, j) == zero)) {
79 predmask[j] |= (
static_cast<std::size_t
>(1) << i);
82 std::vector<bool> seen(n,
false);
83 std::size_t remaining = n;
84 for (std::size_t pass = 0; pass < n; ++pass) {
86 for (std::size_t i = 0; i < n; ++i)
87 if (!seen[i] && indeg[i] == 0) { pick = i;
break; }
91 for (std::size_t j = 0; j < n; ++j)
92 if (!(pred(pick, j) == zero) && indeg[j] > 0) --indeg[j];
96 throw InputError(
"fj_dag_makespan: the precedence relation contains a cycle");
98 const std::size_t nmask =
static_cast<std::size_t
>(1) << n;
99 std::vector<std::size_t> eligmask(nmask, 0);
100 std::vector<bool> closed(nmask,
false);
101 for (std::size_t mask = 0; mask < nmask; ++mask) {
104 for (std::size_t i = 0; i < n; ++i) {
105 const std::size_t bit =
static_cast<std::size_t
>(1) << i;
108 if ((predmask[i] & mask) != predmask[i]) { ok =
false;
break; }
109 }
else if ((predmask[i] & mask) == predmask[i]) {
114 if (ok) eligmask[mask] = em;
117 std::vector<T> p(nmask, zero), D(nmask, zero);
120 out.
I.assign(n, zero);
121 out.
Cend.assign(n, zero);
122 out.
E.assign(n, zero);
124 for (std::size_t mask = 0; mask < nmask; ++mask) {
125 if (!closed[mask])
continue;
126 std::vector<std::size_t> elig;
127 for (std::size_t i = 0; i < n; ++i)
128 if (eligmask[mask] & (
static_cast<std::size_t
>(1) << i)) elig.push_back(i);
129 const std::size_t k = elig.size();
130 if (k == 0)
continue;
132 for (std::size_t idx = 0; idx < k; ++idx) Ttot += rate(elig[idx], k - 1);
134 D[mask] += p[mask] / Ttot;
135 for (std::size_t idx = 0; idx < k; ++idx) {
136 const std::size_t i = elig[idx];
137 const T b = rate(i, k - 1) / Ttot;
138 const std::size_t nxt = mask | (
static_cast<std::size_t
>(1) << i);
139 const T contrib = b * D[mask];
140 p[nxt] += p[mask] * b;
143 out.
Cend[i] += contrib;
145 const std::size_t fresh = eligmask[nxt] & ~eligmask[mask];
146 for (std::size_t j = 0; j < n; ++j)
147 if (fresh & (
static_cast<std::size_t
>(1) << j)) out.
I[j] += contrib;
151 out.
C = D[nmask - 1];
152 for (std::size_t i = 0; i < n; ++i) out.
E[i] = out.
Cend[i] - out.
I[i];