99 const std::map<
int, std::vector<std::pair<int, T>>>& adj,
137 const std::vector<int>& serviceNodes,
138 const std::vector<int>& joinNodes) {
139 detail::wf_check(linkMatrix);
140 const std::set<int> serviceSet(serviceNodes.begin(), serviceNodes.end());
141 const std::set<int> joinSet(joinNodes.begin(), joinNodes.end());
142 const std::map<int, std::vector<std::pair<int, T>>> adj = detail::wf_adjacency_prob(linkMatrix);
146 std::vector<BranchPattern<T>> patterns;
147 for (
typename std::map<
int, std::vector<std::pair<int, T>>>::const_iterator it = adj.begin();
148 it != adj.end(); ++it) {
149 if (it->second.size() <= 1)
continue;
150 std::vector<std::pair<int, T>> targets;
151 for (std::size_t k = 0; k < it->second.size(); ++k)
152 if (serviceSet.count(it->second[k].first)) targets.push_back(it->second[k]);
153 if (targets.size() < 2)
continue;
156 for (std::size_t k = 0; k < targets.size(); ++k) total += targets[k].second;
157 if (
num_abs(T(total - one)) > slack)
continue;
161 for (std::size_t k = 0; k < targets.size(); ++k) {
168 std::set<int> common = detail::wf_reachable_stop(p.
branchNodes[0], adj, joinSet);
169 for (std::size_t k = 1; k < p.
branchNodes.size(); ++k) {
170 const std::set<int> r = detail::wf_reachable_stop(p.
branchNodes[k], adj, joinSet);
172 std::set_intersection(common.begin(), common.end(), r.begin(), r.end(),
173 std::inserter(inter, inter.begin()));
176 std::set<int> joinPoints;
177 std::set_intersection(common.begin(), common.end(), joinSet.begin(), joinSet.end(),
178 std::inserter(joinPoints, joinPoints.begin()));
179 if (!joinPoints.empty()) {
182 }
else if (!common.empty()) {
187 patterns.push_back(p);
195 detail::wf_check(linkMatrix);
200 if (pattern.
forkNode < 0)
return false;
202 const std::map<int, std::vector<std::pair<int, T>>> adj = detail::wf_adjacency_prob(linkMatrix);
203 typename std::map<int, std::vector<std::pair<int, T>>>::const_iterator it =
205 if (it == adj.end())
return false;
206 std::set<int> forkTargets;
207 for (std::size_t k = 0; k < it->second.size(); ++k) forkTargets.insert(it->second[k].first);
208 for (std::size_t k = 0; k < pattern.
branchNodes.size(); ++k)
209 if (!forkTargets.count(pattern.
branchNodes[k]))
return false;
221 "calculate_branch_diversity requires transcendental arithmetic: the entropy of "
222 "the branch probabilities is a sum of p log p");
224 if (probs.size() < 2)
226 "calculate_branch_diversity: needs at least two alternatives, the Gini coefficient "
227 "divides by (n - 1)");
228 const std::size_t n = probs.size();
232 for (std::size_t k = 0; k < n; ++k)
233 if (probs[k] > zero) d.
entropy -= T(probs[k] * detail::num_log(probs[k]));
237 std::vector<T> sorted(probs);
238 std::sort(sorted.begin(), sorted.end());
240 for (std::size_t k = 0; k < n; ++k) sumProbs += probs[k];
242 for (std::size_t k = 0; k < n; ++k)
244 static_cast<long>(n) - 1) *
251 for (std::size_t k = 0; k < n; ++k)
252 if (probs[k] > maxProb) maxProb = probs[k];
BranchStats< T > get_branch_stats(const std::vector< BranchPattern< T > > &patterns)
Count, total, mean/max/min alternatives, and the mean entropy and balance.