1 /* A few tests for the maxmin library */
3 /* Copyright (c) 2007-2019. The SimGrid Team. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include "simgrid/msg.h"
9 #include "src/kernel/lmm/maxmin.hpp"
10 #include "src/surf/surf_interface.hpp"
12 #include "xbt/module.h"
13 #include "xbt/sysdep.h"
17 XBT_LOG_NEW_DEFAULT_CATEGORY(surf_test, "Messages specific for surf example");
19 namespace lmm = simgrid::kernel::lmm;
21 #define PRINT_VAR(var) XBT_DEBUG(#var " = %g", (var)->get_value())
22 #define SHOW_EXPR(expr) XBT_DEBUG(#expr " = %g",expr)
25 /* ==l1== L2 ==L3== */
28 enum method_t { MAXMIN, LAGRANGE_RENO, LAGRANGE_VEGAS };
30 static lmm::System* new_system(method_t method)
32 /* selective update would need real actions instead of NULL as a first parameter to the variable constructor */
35 return lmm::make_new_maxmin_system(false);
38 return lmm::make_new_lagrange_system(false);
40 xbt_die("Invalid method");
46 static double diff_lagrange_test_1(double x)
48 return -(3 / (1 + 3 * x * x / 2) - 3 / (2 * (3 * (a_test_1 - x) * (a_test_1 - x) / 2 + 1)) +
49 3 / (2 * (3 * (b_test_1 - a_test_1 + x) * (b_test_1 - a_test_1 + x) / 2 + 1)));
52 static double dichotomy(double min, double max, double min_error)
54 double overall_error = 2 * min_error;
56 double min_func = diff_lagrange_test_1(min);
57 double max_func = diff_lagrange_test_1(max);
59 if (min_func > 0 && max_func > 0)
61 if (min_func < 0 && max_func < 0)
63 if (min_func > 0 && max_func < 0)
68 while (overall_error > min_error) {
69 SHOW_EXPR(overall_error);
70 xbt_assert(min_func <= 0 || max_func <= 0);
71 xbt_assert(min_func >= 0 || max_func >= 0);
72 xbt_assert(min_func <= 0 || max_func >= 0);
79 double middle = (max + min) / 2.0;
80 if (fabs(min - middle) < 1e-12 || fabs(max - middle) < 1e-12) {
83 double middle_func = diff_lagrange_test_1(middle);
85 SHOW_EXPR(middle_func);
87 if (middle_func < 0) {
89 min_func = middle_func;
90 overall_error = max_func - middle_func;
91 } else if (middle_func > 0) {
93 max_func = middle_func;
94 overall_error = middle_func - min_func;
99 return ((min + max) / 2.0);
102 static void test1(method_t method)
107 if (method == LAGRANGE_VEGAS)
108 lmm::Lagrange::set_default_protocol_function(lmm::func_vegas_f, lmm::func_vegas_fp, lmm::func_vegas_fpi);
109 else if (method == LAGRANGE_RENO)
110 lmm::Lagrange::set_default_protocol_function(lmm::func_reno_f, lmm::func_reno_fp, lmm::func_reno_fpi);
112 lmm::System* Sys = new_system(method);
113 lmm::Constraint* L1 = Sys->constraint_new(nullptr, a);
114 lmm::Constraint* L2 = Sys->constraint_new(nullptr, b);
115 lmm::Constraint* L3 = Sys->constraint_new(nullptr, a);
117 lmm::Variable* R_1_2_3 = Sys->variable_new(nullptr, 1.0, -1.0, 3);
118 lmm::Variable* R_1 = Sys->variable_new(nullptr, 1.0, -1.0, 1);
119 lmm::Variable* R_2 = Sys->variable_new(nullptr, 1.0, -1.0, 1);
120 lmm::Variable* R_3 = Sys->variable_new(nullptr, 1.0, -1.0, 1);
122 Sys->update_variable_weight(R_1_2_3, 1.0);
123 Sys->update_variable_weight(R_1, 1.0);
124 Sys->update_variable_weight(R_2, 1.0);
125 Sys->update_variable_weight(R_3, 1.0);
127 Sys->expand(L1, R_1_2_3, 1.0);
128 Sys->expand(L2, R_1_2_3, 1.0);
129 Sys->expand(L3, R_1_2_3, 1.0);
131 Sys->expand(L1, R_1, 1.0);
132 Sys->expand(L2, R_2, 1.0);
133 Sys->expand(L3, R_3, 1.0);
135 if (method == MAXMIN) {
139 if (method == LAGRANGE_VEGAS) {
140 x = 3 * a / 4 - 3 * b / 8 + sqrt(9 * b * b + 4 * a * a - 4 * a * b) / 8;
141 /* Computed with mupad and D_f=1.0 */
148 } else if (method == LAGRANGE_RENO) {
151 x = dichotomy(0, a, 1e-13);
158 xbt_die( "Invalid method");
163 double max_deviation = 0.0;
164 max_deviation = std::max(max_deviation, fabs(R_1->get_value() - x));
165 max_deviation = std::max(max_deviation, fabs(R_3->get_value() - x));
166 max_deviation = std::max(max_deviation, fabs(R_2->get_value() - (b - a + x)));
167 max_deviation = std::max(max_deviation, fabs(R_1_2_3->get_value() - (a - x)));
169 if (max_deviation > 0.00001) { // Legacy value used in lagrange.c
170 XBT_WARN("Max Deviation from optimal solution : %g", max_deviation);
171 XBT_WARN("Found x = %1.20f", x);
172 XBT_WARN("Deviation from optimal solution (R_1 = %g): %1.20f", x, R_1->get_value() - x);
173 XBT_WARN("Deviation from optimal solution (R_2 = %g): %1.20f", b - a + x, R_2->get_value() - (b - a + x));
174 XBT_WARN("Deviation from optimal solution (R_3 = %g): %1.20f", x, R_3->get_value() - x);
175 XBT_WARN("Deviation from optimal solution (R_1_2_3 = %g): %1.20f", a - x, R_1_2_3->get_value() - (a - x));
184 Sys->variable_free(R_1_2_3);
185 Sys->variable_free(R_1);
186 Sys->variable_free(R_2);
187 Sys->variable_free(R_3);
191 static void test2(method_t method)
193 if (method == LAGRANGE_VEGAS)
194 lmm::Lagrange::set_default_protocol_function(lmm::func_vegas_f, lmm::func_vegas_fp, lmm::func_vegas_fpi);
195 if (method == LAGRANGE_RENO)
196 lmm::Lagrange::set_default_protocol_function(lmm::func_reno_f, lmm::func_reno_fp, lmm::func_reno_fpi);
198 lmm::System* Sys = new_system(method);
200 lmm::Constraint* CPU1 = Sys->constraint_new(nullptr, 200.0);
201 lmm::Constraint* CPU2 = Sys->constraint_new(nullptr, 100.0);
203 lmm::Variable* T1 = Sys->variable_new(nullptr, 1.0, -1.0, 1);
204 lmm::Variable* T2 = Sys->variable_new(nullptr, 1.0, -1.0, 1);
206 Sys->update_variable_weight(T1, 1.0);
207 Sys->update_variable_weight(T2, 1.0);
209 Sys->expand(CPU1, T1, 1.0);
210 Sys->expand(CPU2, T2, 1.0);
217 Sys->variable_free(T1);
218 Sys->variable_free(T2);
222 static void test3(method_t method)
227 double** A = new double*[links + 5];
228 /* array to add the constraints of fictitious variables */
229 double B[15] = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1, 1, 1, 1, 1 };
231 for (int i = 0; i < links + 5; i++) {
232 A[i] = new double[flows + 5];
233 for (int j = 0; j < flows + 5; j++) {
236 if (i >= links || j >= flows) {
242 /*matrix that store the constraints/topology */
243 A[0][1] = A[0][7] = 1.0;
244 A[1][1] = A[1][7] = A[1][8] = 1.0;
245 A[2][1] = A[2][8] = 1.0;
247 A[4][0] = A[4][3] = A[4][9] = 1.0;
248 A[5][0] = A[5][3] = A[5][4] = A[5][9] = 1.0;
249 A[6][0] = A[6][4] = A[6][9] = A[6][10] = 1.0;
250 A[7][2] = A[7][4] = A[7][6] = A[7][9] = A[7][10] = 1.0;
251 A[8][2] = A[8][10] = 1.0;
252 A[9][5] = A[9][6] = A[9][9] = 1.0;
259 if (method == LAGRANGE_VEGAS)
260 lmm::Lagrange::set_default_protocol_function(lmm::func_vegas_f, lmm::func_vegas_fp, lmm::func_vegas_fpi);
261 if (method == LAGRANGE_RENO)
262 lmm::Lagrange::set_default_protocol_function(lmm::func_reno_f, lmm::func_reno_fp, lmm::func_reno_fpi);
264 lmm::System* Sys = new_system(method);
266 /* Creates the constraints */
267 lmm::Constraint** tmp_cnst = new lmm::Constraint*[15];
268 for (int i = 0; i < 15; i++)
269 tmp_cnst[i] = Sys->constraint_new(nullptr, B[i]);
271 /* Creates the variables */
272 lmm::Variable** tmp_var = new lmm::Variable*[16];
273 for (int j = 0; j < 16; j++) {
274 tmp_var[j] = Sys->variable_new(nullptr, 1.0, -1.0, 15);
275 Sys->update_variable_weight(tmp_var[j], 1.0);
278 /* Link constraints and variables */
279 for (int i = 0; i < 15; i++)
280 for (int j = 0; j < 16; j++)
282 Sys->expand(tmp_cnst[i], tmp_var[j], 1.0);
286 for (int j = 0; j < 16; j++)
287 PRINT_VAR(tmp_var[j]);
289 for (int j = 0; j < 16; j++)
290 Sys->variable_free(tmp_var[j]);
294 for (int i = 0; i < links + 5; i++)
299 int main(int argc, char** argv)
301 MSG_init(&argc, argv);
302 XBT_INFO("***** Test 1 (Max-Min)");
304 XBT_INFO("***** Test 1 (Lagrange - Vegas)");
305 test1(LAGRANGE_VEGAS);
306 XBT_INFO("***** Test 1 (Lagrange - Reno)");
307 test1(LAGRANGE_RENO);
309 XBT_INFO("***** Test 2 (Max-Min)");
311 XBT_INFO("***** Test 2 (Lagrange - Vegas)");
312 test2(LAGRANGE_VEGAS);
313 XBT_INFO("***** Test 2 (Lagrange - Reno)");
314 test2(LAGRANGE_RENO);
316 XBT_INFO("***** Test 3 (Max-Min)");
318 XBT_INFO("***** Test 3 (Lagrange - Vegas)");
319 test3(LAGRANGE_VEGAS);
320 XBT_INFO("***** Test 3 (Lagrange - Reno)");
321 test3(LAGRANGE_RENO);