+ /* Not mandatory but a safe check to assure we have a proper solution */
+ if (not is_bmf(rho)) {
+ fprintf(stderr, "Unable to find a BMF allocation for your system.\n"
+ "You may try to increase the maximum number of iterations performed by BMF solver "
+ "(\"--cfg=bmf/max-iterations\").\n"
+ "Additionally, you could adjust numerical precision (\"--cfg=bmf/precision\").\n");
+ fprintf(stderr, "Internal states (after %d iterations):\n", it);
+ fprintf(stderr, "A:\n%s\n", debug_eigen(A_).c_str());
+ fprintf(stderr, "maxA:\n%s\n", debug_eigen(maxA_).c_str());
+ fprintf(stderr, "C:\n%s\n", debug_eigen(C_).c_str());
+ fprintf(stderr, "C_shared:\n%s\n", debug_vector(C_shared_).c_str());
+ fprintf(stderr, "phi:\n%s\n", debug_eigen(phi_).c_str());
+ fprintf(stderr, "rho:\n%s\n", debug_eigen(rho).c_str());
+ xbt_abort();
+ }
+
+ XBT_DEBUG("BMF done after %d iterations", it);
+ return rho;
+}
+
+/*****************************************************************************/
+
+void BmfSystem::get_flows_data(Eigen::Index number_cnsts, Eigen::MatrixXd& A, Eigen::MatrixXd& maxA,
+ Eigen::VectorXd& phi)
+{
+ A.resize(number_cnsts, variable_set.size());
+ A.setZero();
+ maxA.resize(number_cnsts, variable_set.size());
+ maxA.setZero();
+ phi.resize(variable_set.size());
+
+ int var_idx = 0;
+ for (Variable& var : variable_set) {
+ if (var.sharing_penalty_ <= 0)
+ continue;
+ bool active = false;
+ bool linked = false; // variable is linked to some constraint (specially for selective_update)
+ for (const Element& elem : var.cnsts_) {
+ if (const auto& cnst_hook = selective_update_active ? elem.constraint->modified_constraint_set_hook_
+ : elem.constraint->active_constraint_set_hook_;
+ not cnst_hook.is_linked())
+ continue;
+ /* active and linked variable, lets check its consumption */
+ linked = true;
+ double consumption = elem.consumption_weight;
+ if (consumption > 0) {
+ int cnst_idx = cnst2idx_[elem.constraint];
+ A(cnst_idx, var_idx) += consumption;
+ // a variable with double penalty must receive half share, so it max weight is greater
+ maxA(cnst_idx, var_idx) = std::max(maxA(cnst_idx, var_idx), elem.max_consumption_weight * var.sharing_penalty_);
+ active = true;
+ }
+ }
+ /* skip variables not linked to any modified or active constraint */
+ if (not linked)
+ continue;
+ if (active) {
+ phi[var_idx] = var.get_bound();
+ idx2Var_[var_idx] = &var;
+ var_idx++;
+ } else {
+ var.value_ = 1; // assign something by default for tasks with 0 consumption
+ }
+ }
+ // resize matrix to active variables only
+ A.conservativeResize(Eigen::NoChange_t::NoChange, var_idx);
+ maxA.conservativeResize(Eigen::NoChange_t::NoChange, var_idx);
+ phi.conservativeResize(var_idx);
+}
+
+template <class CnstList>
+void BmfSystem::get_constraint_data(const CnstList& cnst_list, Eigen::VectorXd& C, std::vector<bool>& shared)
+{
+ C.resize(cnst_list.size());
+ shared.resize(cnst_list.size());
+ cnst2idx_.clear();
+ int cnst_idx = 0;
+ for (const Constraint& cnst : cnst_list) {
+ C(cnst_idx) = cnst.bound_;
+ if (cnst.get_sharing_policy() == Constraint::SharingPolicy::NONLINEAR && cnst.dyn_constraint_cb_) {
+ C(cnst_idx) = cnst.dyn_constraint_cb_(cnst.bound_, cnst.concurrency_current_);
+ }
+ cnst2idx_[&cnst] = cnst_idx;
+ // FATPIPE links aren't really shared
+ shared[cnst_idx] = (cnst.sharing_policy_ != Constraint::SharingPolicy::FATPIPE);
+ cnst_idx++;
+ }
+}
+
+void BmfSystem::do_solve()
+{
+ if (selective_update_active)
+ bmf_solve(modified_constraint_set);
+ else
+ bmf_solve(active_constraint_set);
+}
+
+template <class CnstList> void BmfSystem::bmf_solve(const CnstList& cnst_list)
+{
+ idx2Var_.clear();
+ cnst2idx_.clear();
+ Eigen::MatrixXd A;
+ Eigen::MatrixXd maxA;
+ Eigen::VectorXd C;
+ Eigen::VectorXd bounds;
+ std::vector<bool> shared;
+ get_constraint_data(cnst_list, C, shared);
+ get_flows_data(C.size(), A, maxA, bounds);
+
+ auto solver = BmfSolver(std::move(A), std::move(maxA), std::move(C), std::move(shared), std::move(bounds));
+ auto rho = solver.solve();
+
+ if (rho.size() == 0)
+ return;