}
Sys.variable_free_all();
+}
+
+TEST_CASE("kernel::bmf Loop", "[kernel-bmf-loop]")
+{
+ lmm::BmfSystem Sys(false);
+ xbt_log_control_set("ker_bmf.thres:debug");
+
+ SECTION("Initial allocation loops")
+ {
+ /*
+ * Complex matrix whose initial allocation loops and is unable
+ * to stabilize after 10 iterations.
+ *
+ * The algorithm needs to restart from another point
+ */
+
+ std::vector<double> C = {1.0, 1.0, 1.0, 1.0, 1.0};
+ std::vector<std::vector<double>> A = {
+ {0.0918589, 0.980201, 0.553352, 0.0471331, 0.397493, 0.0494386, 0.158874, 0.737557, 0.822504, 0.364411},
+ {0.852866, 0.383171, 0.924183, 0.318345, 0.937625, 0.980201, 0.0471331, 0.0494386, 0.737557, 0.364411},
+ {0.12043, 0.985661, 0.153195, 0.852866, 0.247113, 0.318345, 0.0918589, 0.0471331, 0.158874, 0.364411},
+ {0.387291, 0.159939, 0.641492, 0.985661, 0.0540999, 0.383171, 0.318345, 0.980201, 0.0494386, 0.364411},
+ {0.722983, 0.924512, 0.474874, 0.819576, 0.572598, 0.0540999, 0.247113, 0.937625, 0.397493, 0.364411}};
+
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (auto c : C) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, c));
+ }
+ std::vector<lmm::Variable*> vars;
+ for (size_t i = 0; i < A[0].size(); i++) {
+ vars.push_back(Sys.variable_new(nullptr, 1, -1, A.size()));
+ }
+ for (size_t j = 0; j < A.size(); j++) {
+ for (size_t i = 0; i < A[j].size(); i++) {
+ Sys.expand_add(sys_cnst[j], vars[i], A[j][i]);
+ }
+ }
+ Sys.solve();
+
+ for (auto* rho : vars) {
+ REQUIRE(double_positive(rho->get_value(), sg_maxmin_precision));
+ }
+ }
+
+ Sys.variable_free_all();
+}
+
+TEST_CASE("kernel::bmf Stress-tests", "[.kernel-bmf-stress]")
+{
+ lmm::BmfSystem Sys(false);
+
+ SECTION("Random consumptions - independent flows")
+ {
+ int C = 5;
+ int N = 2;
+ auto data = GENERATE_COPY(chunk(C * N, take(100000, random(0., 1.0))));
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (int i = 0; i < C; i++) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, 1));
+ }
+ for (int j = 0; j < N; j++) {
+ for (int i = 0; i < C; i++) {
+ lmm::Variable* rho = Sys.variable_new(nullptr, 1);
+ Sys.expand_add(sys_cnst[i], rho, data[i * j + j]);
+ }
+ }
+ Sys.solve();
+ }
+
+ SECTION("Random consumptions - flows sharing resources")
+ {
+ int C = 5;
+ int N = 10;
+ auto data = GENERATE_COPY(chunk(C * N, take(100000, random(0., 1.0))));
+
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (int i = 0; i < C; i++) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, 1));
+ }
+ for (int j = 0; j < N; j++) {
+ lmm::Variable* rho = Sys.variable_new(nullptr, 1, -1, C);
+ for (int i = 0; i < C; i++) {
+ Sys.expand_add(sys_cnst[i], rho, data[i * j + j]);
+ }
+ }
+
+ Sys.solve();
+ }
+
+ SECTION("Random integer consumptions - flows sharing resources")
+ {
+ int C = 5;
+ int N = 10;
+ auto data = GENERATE_COPY(chunk(C * N, take(100000, random(1, 10))));
+
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (int i = 0; i < C; i++) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, 10));
+ }
+ for (int j = 0; j < N; j++) {
+ lmm::Variable* rho = Sys.variable_new(nullptr, 1, -1, C);
+ for (int i = 0; i < C; i++) {
+ Sys.expand_add(sys_cnst[i], rho, data[i * j + j]);
+ }
+ }
+ Sys.solve();
+ }
+
+ SECTION("Random consumptions - high number of constraints")
+ {
+ int C = 500;
+ int N = 10;
+ auto data = GENERATE_COPY(chunk(C * N, take(100000, random(0., 1.0))));
+
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (int i = 0; i < C; i++) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, 1));
+ }
+ for (int j = 0; j < N; j++) {
+ lmm::Variable* rho = Sys.variable_new(nullptr, 1, -1, C);
+ for (int i = 0; i < C; i++) {
+ Sys.expand_add(sys_cnst[i], rho, data[i * j + j]);
+ }
+ }
+ Sys.solve();
+ }
+
+ SECTION("Random integer consumptions - high number of constraints")
+ {
+ int C = 500;
+ int N = 10;
+ auto data = GENERATE_COPY(chunk(C * N, take(100000, random(1, 10))));
+
+ std::vector<lmm::Constraint*> sys_cnst;
+ for (int i = 0; i < C; i++) {
+ sys_cnst.push_back(Sys.constraint_new(nullptr, 10));
+ }
+ for (int j = 0; j < N; j++) {
+ lmm::Variable* rho = Sys.variable_new(nullptr, 1, -1, C);
+ for (int i = 0; i < C; i++) {
+ Sys.expand_add(sys_cnst[i], rho, data[i * j + j]);
+ }
+ }
+ Sys.solve();
+ }
+
+ Sys.variable_free_all();
+}
+
+TEST_CASE("kernel::AllocationGenerator Basic tests", "[kernel-bmf-allocation-gen]")
+{
+ SECTION("Full combinations")
+ {
+ Eigen::MatrixXd A(3, 3);
+ A << 1, .5, 1, 1, 1, .5, 1, .75, .75;
+ lmm::AllocationGenerator gen(std::move(A));
+ int i = 0;
+ std::vector<int> alloc;
+ while (gen.next(alloc))
+ i++;
+ REQUIRE(i == 3 * 3 * 3);
+ }
+
+ SECTION("Few options per player")
+ {
+ Eigen::MatrixXd A(3, 3);
+ A << 1, 0, 0, 0, 1, 0, 0, 1, 1;
+ lmm::AllocationGenerator gen(std::move(A));
+ int i = 0;
+ std::vector<int> alloc;
+ while (gen.next(alloc))
+ i++;
+ REQUIRE(i == 1 * 2 * 1);
+ }
}
\ No newline at end of file