+static void lmm_check_concurrency(lmm_system_t sys)
+{
+ // These checks are very expensive, so do them only if we want to debug SURF LMM
+ if (not XBT_LOG_ISENABLED(surf_maxmin, xbt_log_priority_debug))
+ return;
+
+ void* cnstIt;
+ xbt_swag_foreach(cnstIt, &(sys->constraint_set))
+ {
+ lmm_constraint_t cnst = (lmm_constraint_t)cnstIt;
+ int concurrency = 0;
+ void* elemIt;
+ xbt_swag_foreach(elemIt, &(cnst->enabled_element_set))
+ {
+ lmm_element_t elem = (lmm_element_t)elemIt;
+ xbt_assert(elem->variable->sharing_weight > 0);
+ concurrency += lmm_element_concurrency(elem);
+ }
+
+ xbt_swag_foreach(elemIt, &(cnst->disabled_element_set))
+ {
+ lmm_element_t elem = (lmm_element_t)elemIt;
+ // We should have staged variables only if concurrency is reached in some constraint
+ xbt_assert(cnst->concurrency_limit < 0 || elem->variable->staged_weight == 0 ||
+ lmm_cnstrs_min_concurrency_slack(elem->variable) < elem->variable->concurrency_share,
+ "should not have staged variable!");
+ }
+
+ xbt_assert(cnst->concurrency_limit < 0 || cnst->concurrency_limit >= concurrency, "concurrency check failed!");
+ xbt_assert(cnst->concurrency_current == concurrency, "concurrency_current is out-of-date!");
+ }
+
+ // Check that for each variable, all corresponding elements are in the same state (i.e. same element sets)
+ void* varIt;
+ xbt_swag_foreach(varIt, &(sys->variable_set))
+ {
+ lmm_variable_t var = (lmm_variable_t)varIt;
+
+ if (not var->cnsts_number)
+ continue;
+
+ lmm_element_t elem = &var->cnsts[0];
+ int belong_to_enabled = xbt_swag_belongs(elem, &(elem->constraint->enabled_element_set));
+ int belong_to_disabled = xbt_swag_belongs(elem, &(elem->constraint->disabled_element_set));
+ int belong_to_active = xbt_swag_belongs(elem, &(elem->constraint->active_element_set));
+
+ for (int i = 1; i < var->cnsts_number; i++) {
+ elem = &var->cnsts[i];
+ xbt_assert(belong_to_enabled == xbt_swag_belongs(elem, &(elem->constraint->enabled_element_set)),
+ "Variable inconsistency (1): enabled_element_set");
+ xbt_assert(belong_to_disabled == xbt_swag_belongs(elem, &(elem->constraint->disabled_element_set)),
+ "Variable inconsistency (2): disabled_element_set");
+ xbt_assert(belong_to_active == xbt_swag_belongs(elem, &(elem->constraint->active_element_set)),
+ "Variable inconsistency (3): active_element_set");
+ }
+ }
+}
+
+static inline void lmm_variable_remove(lmm_system_t sys, lmm_variable_t var)
+{
+ XBT_IN("(sys=%p, var=%p)", sys, var);
+ sys->modified = 1;
+
+ // TODOLATER Can do better than that by leaving only the variable in only one enabled_element_set, call
+ // lmm_update_modified_set, and then remove it..
+ if (var->cnsts_number)
+ lmm_update_modified_set(sys, var->cnsts[0].constraint);
+
+ for (int i = 0; i < var->cnsts_number; i++) {
+ lmm_element_t elem = &var->cnsts[i];
+ if (var->sharing_weight > 0)
+ lmm_decrease_concurrency(elem);
+ xbt_swag_remove(elem, &(elem->constraint->enabled_element_set));
+ xbt_swag_remove(elem, &(elem->constraint->disabled_element_set));
+ xbt_swag_remove(elem, &(elem->constraint->active_element_set));
+ int nelements = xbt_swag_size(&(elem->constraint->enabled_element_set)) +
+ xbt_swag_size(&(elem->constraint->disabled_element_set));
+ if (nelements == 0)
+ make_constraint_inactive(sys, elem->constraint);
+ else
+ lmm_on_disabled_var(sys, elem->constraint);
+ }
+
+ // Check if we can enable new variables going through the constraints where var was.
+ // Do it after removing all elements, so he first disabled variables get priority over those with smaller requirement
+ for (int i = 0; i < var->cnsts_number; i++) {
+ lmm_element_t elem = &var->cnsts[i];
+ if (xbt_swag_size(&(elem->constraint->disabled_element_set)))
+ lmm_on_disabled_var(sys, elem->constraint);
+ }
+
+ var->cnsts_number = 0;
+
+ lmm_check_concurrency(sys);
+
+ XBT_OUT();
+}
+
+static void lmm_var_free(lmm_system_t sys, lmm_variable_t var)
+{
+ lmm_variable_remove(sys, var);
+ xbt_mallocator_release(sys->variable_mallocator, var);
+}
+
+lmm_system_t lmm_system_new(bool selective_update)