+ if (not var->cnsts.empty())
+ lmm_update_modified_set(sys, var->cnsts[0].constraint);
+}
+
+int lmm_concurrency_slack(lmm_constraint_t cnstr)
+{
+ if (cnstr->concurrency_limit < 0)
+ return std::numeric_limits<int>::max();
+ return cnstr->concurrency_limit - cnstr->concurrency_current;
+}
+
+/** \brief Measure the minimum concurrency slack across all constraints where the given var is involved */
+int lmm_cnstrs_min_concurrency_slack(lmm_variable_t var)
+{
+ int minslack = std::numeric_limits<int>::max();
+ for (s_lmm_element_t const& elem : var->cnsts) {
+ int slack = lmm_concurrency_slack(elem.constraint);
+ if (slack < minslack) {
+ // This is only an optimization, to avoid looking at more constraints when slack is already zero
+ if (slack == 0)
+ return 0;
+ minslack = slack;
+ }
+ }
+ return minslack;
+}
+
+/* /Check if a variable can be enabled
+ *
+ * Make sure to set staged_weight before, if your intent is only to check concurrency
+ */
+int lmm_can_enable_var(lmm_variable_t var){
+ return var->staged_weight>0 && lmm_cnstrs_min_concurrency_slack(var)>=var->concurrency_share;
+}
+
+//Small remark: In this implementation of lmm_enable_var and lmm_disable_var, we will meet multiple times with var when
+// running lmm_update_modified_set.
+//A priori not a big performance issue, but we might do better by calling lmm_update_modified_set within the for loops
+// (after doing the first for enabling==1, and before doing the last for disabling==1)
+void lmm_enable_var(lmm_system_t sys, lmm_variable_t var){
+ xbt_assert(not XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug) || lmm_can_enable_var(var));
+
+ var->sharing_weight = var->staged_weight;
+ var->staged_weight = 0;
+
+ // Enabling the variable, move to var to list head. Subtlety is: here, we need to call lmm_update_modified_set AFTER
+ // moving at least one element of var.
+
+ xbt_swag_remove(var, &(sys->variable_set));
+ xbt_swag_insert_at_head(var, &(sys->variable_set));
+ for (s_lmm_element_t& elem : var->cnsts) {
+ xbt_swag_remove(&elem, &(elem.constraint->disabled_element_set));
+ xbt_swag_insert_at_head(&elem, &(elem.constraint->enabled_element_set));
+ lmm_increase_concurrency(&elem);
+ }
+ if (not var->cnsts.empty())
+ lmm_update_modified_set(sys, var->cnsts[0].constraint);
+
+ //When used within lmm_on_disabled_var, we would get an assertion fail, because transiently there can be variables
+ // that are staged and could be activated.
+ //Anyway, caller functions all call lmm_check_concurrency() in the end.
+}
+
+void lmm_disable_var(lmm_system_t sys, lmm_variable_t var){
+ xbt_assert(not var->staged_weight, "Staged weight should have been cleared");
+ // Disabling the variable, move to var to list tail. Subtlety is: here, we need to call lmm_update_modified_set BEFORE
+ // moving the last element of var.
+ xbt_swag_remove(var, &(sys->variable_set));
+ xbt_swag_insert_at_tail(var, &(sys->variable_set));
+ if (not var->cnsts.empty())