Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
BMF sharing penalty/priority
authorBruno Donassolo <bruno.donassolo@inria.fr>
Thu, 3 Mar 2022 14:41:04 +0000 (15:41 +0100)
committerBruno Donassolo <bruno.donassolo@inria.fr>
Mon, 7 Mar 2022 09:23:25 +0000 (10:23 +0100)
src/kernel/lmm/bmf.cpp
src/kernel/lmm/bmf_test.cpp
src/kernel/lmm/maxmin_test.cpp

index 27f4736..53b2e73 100644 (file)
@@ -381,9 +381,10 @@ void BmfSystem::get_flows_data(int number_cnsts, Eigen::MatrixXd& A, Eigen::Matr
       linked             = true;
       double consumption = elem.consumption_weight;
       if (consumption > 0) {
-        int cnst_idx            = cnst2idx_[elem.constraint];
-        A(cnst_idx, var_idx)    = consumption;
-        maxA(cnst_idx, var_idx) = elem.max_consumption_weight;
+        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;
       }
     }
index 184eb04..ea17675 100644 (file)
@@ -65,6 +65,33 @@ TEST_CASE("kernel::bmf Basic tests", "[kernel-bmf-basic]")
     REQUIRE(double_equals(rho_2->get_value(), (3.0 / 2.0) / 10.0, sg_maxmin_precision));
   }
 
+  SECTION("Variable penalty/priority")
+  {
+    /*
+     * A variable with twice the penalty gets half of the share
+     *
+     * In details:
+     *   o System:  a1 * p1 * \rho1  +  a2 * p2 * \rho2 < C
+     *   o consumption_weight: a1=1 ; a2=1
+     *   o sharing_penalty:    p1=1 ; p2=2
+     *
+     * Expectations
+     *   o rho1 = 2* rho2 (because rho2 has twice the penalty)
+     *   o rho1 + rho2 = C (because all weights are 1)
+     */
+
+    lmm::Constraint* sys_cnst = Sys.constraint_new(nullptr, 3);
+    lmm::Variable* rho_1      = Sys.variable_new(nullptr, 1);
+    lmm::Variable* rho_2      = Sys.variable_new(nullptr, 2);
+
+    Sys.expand(sys_cnst, rho_1, 1);
+    Sys.expand(sys_cnst, rho_2, 1);
+    Sys.solve();
+
+    REQUIRE(double_equals(rho_1->get_value(), 2, sg_maxmin_precision));
+    REQUIRE(double_equals(rho_2->get_value(), 1, sg_maxmin_precision));
+  }
+
   SECTION("Disable variable doesn't count")
   {
     /*
@@ -347,6 +374,37 @@ TEST_CASE("kernel::bmf Advanced tests", "[kernel-bmf-advanced]")
     REQUIRE(double_equals(rho_2->get_value(), 1e6 / 2.0, sg_maxmin_precision));
   }
 
+  SECTION("Proportional fairness")
+  {
+    /*
+     * 3 flows sharing 2 resources with crosstraffic
+     *
+     * Regular max-min would give B/2 for every flow.
+     * BMF is equivalent to proportional fairness in this case, and give a quite
+     * different sharing.
+     *
+     */
+
+    lmm::Constraint* sys_cnst  = Sys.constraint_new(nullptr, 1);
+    lmm::Constraint* sys_cnst2 = Sys.constraint_new(nullptr, 1);
+    lmm::Variable* rho_1       = Sys.variable_new(nullptr, 1, -1, 2);
+    lmm::Variable* rho_2       = Sys.variable_new(nullptr, 1, -1, 2);
+    lmm::Variable* rho_3       = Sys.variable_new(nullptr, 1, -1, 2);
+
+    double epsilon = 0.05;
+    Sys.expand(sys_cnst, rho_1, 1.0);
+    Sys.expand(sys_cnst2, rho_1, epsilon);
+    Sys.expand(sys_cnst, rho_2, 1.0);
+    Sys.expand(sys_cnst2, rho_2, epsilon);
+    Sys.expand(sys_cnst2, rho_3, 1.0);
+    Sys.expand(sys_cnst, rho_3, epsilon);
+    Sys.solve();
+
+    REQUIRE(double_equals(rho_1->get_value(), 1.0 / (2.0 + 2 * epsilon), sg_maxmin_precision));
+    REQUIRE(double_equals(rho_2->get_value(), 1.0 / (2.0 + 2 * epsilon), sg_maxmin_precision));
+    REQUIRE(double_equals(rho_3->get_value(), 1.0 / (1.0 + epsilon), sg_maxmin_precision));
+  }
+
   Sys.variable_free_all();
 }
 
index b654e2e..828d098 100644 (file)
@@ -422,5 +422,46 @@ TEST_CASE("kernel::lmm dynamic constraint shared systems", "[kernel-lmm-shared-s
     REQUIRE(double_equals(rho_3->get_value(), 2, sg_maxmin_precision));
   }
 
+  Sys.variable_free_all();
+}
+
+TEST_CASE("kernel::lmm shared systems with crosstraffic", "[kernel-lmm-shared-crosstraffic]")
+{
+  lmm::System Sys(false);
+
+  SECTION("3 flows, 3 resource: crosstraffic")
+  {
+    /*
+     * 3 flows sharing 2 constraints, single
+     *
+     * In details:
+     *   o System:  a1 * \rho1 + a2 * \rho2 + epsilon * \rho3 < C1
+     *              epsilon * \rho1 + epsilon * \rho2 + a3 * \rho3 < C2
+     *   o consumption_weight: a1=1, a2=1, a3=1, epsilon=0.05
+     *   o C1 = C2 = 1
+     *
+     * Expectations
+     *   o rho1 = rho2 = rho3 = 1/2
+     */
+    lmm::Constraint* sys_cnst  = Sys.constraint_new(nullptr, 1);
+    lmm::Constraint* sys_cnst2 = Sys.constraint_new(nullptr, 1);
+    lmm::Variable* rho_1       = Sys.variable_new(nullptr, 1, -1, 2);
+    lmm::Variable* rho_2       = Sys.variable_new(nullptr, 1, -1, 2);
+    lmm::Variable* rho_3       = Sys.variable_new(nullptr, 1, -1, 2);
+
+    double epsilon = 0.05;
+    Sys.expand(sys_cnst, rho_1, 1.0);
+    Sys.expand(sys_cnst2, rho_1, epsilon);
+    Sys.expand(sys_cnst, rho_2, 1.0);
+    Sys.expand(sys_cnst2, rho_2, epsilon);
+    Sys.expand(sys_cnst2, rho_3, 1.0);
+    Sys.expand(sys_cnst, rho_3, epsilon);
+    Sys.solve();
+
+    REQUIRE(double_equals(rho_1->get_value(), 1.0 / (2.0 + epsilon), sg_maxmin_precision));
+    REQUIRE(double_equals(rho_2->get_value(), 1.0 / (2.0 + epsilon), sg_maxmin_precision));
+    REQUIRE(double_equals(rho_3->get_value(), 1.0 / (2.0 + epsilon), sg_maxmin_precision));
+  }
+
   Sys.variable_free_all();
 }
\ No newline at end of file