Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Remove useless parentheses.
[simgrid.git] / teshsuite / surf / lmm_usage / lmm_usage.cpp
1 /* A few tests for the maxmin library                                       */
2
3 /* Copyright (c) 2007-2018. The SimGrid Team. All rights reserved.          */
4
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. */
7
8 #include "simgrid/msg.h"
9 #include "src/kernel/lmm/maxmin.hpp"
10 #include "src/surf/surf_interface.hpp"
11 #include "xbt/log.h"
12 #include "xbt/module.h"
13 #include "xbt/sysdep.h"
14 #include <algorithm>
15 #include <cmath>
16
17 XBT_LOG_NEW_DEFAULT_CATEGORY(surf_test, "Messages specific for surf example");
18
19 namespace lmm = simgrid::kernel::lmm;
20
21 #define PRINT_VAR(var) XBT_DEBUG(#var " = %g", (var)->get_value())
22 #define SHOW_EXPR(expr) XBT_DEBUG(#expr " = %g",expr)
23
24 /*        ______                 */
25 /*  ==l1==  L2  ==L3==           */
26 /*        ------                 */
27
28 enum method_t { MAXMIN, LAGRANGE_RENO, LAGRANGE_VEGAS };
29
30 static lmm::System* new_system(method_t method)
31 {
32   /* selective update would need real actions instead of NULL as a first parameter to the variable constructor */
33   switch (method) {
34     case MAXMIN:
35       return lmm::make_new_maxmin_system(false);
36     case LAGRANGE_VEGAS:
37     case LAGRANGE_RENO:
38       return lmm::make_new_lagrange_system(false);
39     default:
40       xbt_die("Invalid method");
41   }
42 }
43
44 static double dichotomy(double func(double), double min, double max, double min_error)
45 {
46   double overall_error = 2 * min_error;
47
48   double min_func = func(min);
49   double max_func = func(max);
50
51   if (min_func > 0 && max_func > 0)
52     return min - 1.0;
53   if (min_func < 0 && max_func < 0)
54     return max + 1.0;
55   if (min_func > 0 && max_func < 0)
56     abort();
57
58   SHOW_EXPR(min_error);
59
60   while (overall_error > min_error) {
61     SHOW_EXPR(overall_error);
62     xbt_assert(min_func <= 0 || max_func <= 0);
63     xbt_assert(min_func >= 0 || max_func >= 0);
64     xbt_assert(min_func <= 0 || max_func >= 0);
65
66     SHOW_EXPR(min);
67     SHOW_EXPR(min_func);
68     SHOW_EXPR(max);
69     SHOW_EXPR(max_func);
70
71     double middle = (max + min) / 2.0;
72     if (fabs(min - middle) < 1e-12 || fabs(max - middle) < 1e-12) {
73       break;
74     }
75     double middle_func = func(middle);
76     SHOW_EXPR(middle);
77     SHOW_EXPR(middle_func);
78
79     if (middle_func < 0) {
80       min = middle;
81       min_func = middle_func;
82       overall_error = max_func - middle_func;
83     } else if (middle_func > 0) {
84       max = middle;
85       max_func = middle_func;
86       overall_error = middle_func - min_func;
87     } else {
88       overall_error = 0;
89     }
90   }
91   return ((min + max) / 2.0);
92 }
93
94 double a_test_1 = 0;
95 double b_test_1 = 0;
96 static double diff_lagrange_test_1(double x)
97 {
98   return -(3 / (1 + 3 * x * x / 2) - 3 / (2 * (3 * (a_test_1 - x) * (a_test_1 - x) / 2 + 1)) +
99            3 / (2 * (3 * (b_test_1 - a_test_1 + x) * (b_test_1 - a_test_1 + x) / 2 + 1)));
100 }
101
102 static void test1(method_t method)
103 {
104   double a = 1.0;
105   double b = 10.0;
106
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);
111
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);
116
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);
121
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);
126
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);
130
131   Sys->expand(L1, R_1, 1.0);
132   Sys->expand(L2, R_2, 1.0);
133   Sys->expand(L3, R_3, 1.0);
134
135   if (method == MAXMIN) {
136     Sys->solve();
137   } else {
138     double x;
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 */
142       if (x > a) {
143         x = a;
144       }
145       if (x < 0) {
146         x = 0;
147       }
148     } else if (method == LAGRANGE_RENO) {
149       a_test_1 = a;
150       b_test_1 = b;
151       x = dichotomy(diff_lagrange_test_1, 0, a, 1e-13);
152
153       if (x < 0)
154         x = 0;
155       if (x > a)
156         x = a;
157     } else {
158       xbt_die( "Invalid method");
159     }
160
161     Sys->solve();
162
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)));
168
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));
176     }
177   }
178
179   PRINT_VAR(R_1_2_3);
180   PRINT_VAR(R_1);
181   PRINT_VAR(R_2);
182   PRINT_VAR(R_3);
183
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);
188   delete Sys;
189 }
190
191 static void test2(method_t method)
192 {
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);
197
198   lmm::System* Sys = new_system(method);
199
200   lmm::Constraint* CPU1 = Sys->constraint_new(nullptr, 200.0);
201   lmm::Constraint* CPU2 = Sys->constraint_new(nullptr, 100.0);
202
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);
205
206   Sys->update_variable_weight(T1, 1.0);
207   Sys->update_variable_weight(T2, 1.0);
208
209   Sys->expand(CPU1, T1, 1.0);
210   Sys->expand(CPU2, T2, 1.0);
211
212   Sys->solve();
213
214   PRINT_VAR(T1);
215   PRINT_VAR(T2);
216
217   Sys->variable_free(T1);
218   Sys->variable_free(T2);
219   delete Sys;
220 }
221
222 static void test3(method_t method)
223 {
224   int flows = 11;
225   int links = 10;
226
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 };
230
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++) {
234       A[i][j] = 0.0;
235
236       if (i >= links || j >= flows) {
237         A[i][j] = 0.0;
238       }
239     }
240   }
241
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;
246   A[3][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;
253   A[10][11] =                                        1.0;
254   A[11][12] =                                        1.0;
255   A[12][13] =                                        1.0;
256   A[13][14] =                                        1.0;
257   A[14][15] =                                        1.0;
258
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);
263
264   lmm::System* Sys = new_system(method);
265
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]);
270
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);
276   }
277
278   /* Link constraints and variables */
279   for (int i = 0; i < 15; i++)
280     for (int j = 0; j < 16; j++)
281       if (A[i][j])
282         Sys->expand(tmp_cnst[i], tmp_var[j], 1.0);
283
284   Sys->solve();
285
286   for (int j = 0; j < 16; j++)
287     PRINT_VAR(tmp_var[j]);
288
289   for (int j = 0; j < 16; j++)
290     Sys->variable_free(tmp_var[j]);
291   delete[] tmp_var;
292   delete[] tmp_cnst;
293   delete Sys;
294   for (int i = 0; i < links + 5; i++)
295     delete[] A[i];
296   delete[] A;
297 }
298
299 int main(int argc, char** argv)
300 {
301   MSG_init(&argc, argv);
302   XBT_INFO("***** Test 1 (Max-Min)");
303   test1(MAXMIN);
304   XBT_INFO("***** Test 1 (Lagrange - Vegas)");
305   test1(LAGRANGE_VEGAS);
306   XBT_INFO("***** Test 1 (Lagrange - Reno)");
307   test1(LAGRANGE_RENO);
308
309   XBT_INFO("***** Test 2 (Max-Min)");
310   test2(MAXMIN);
311   XBT_INFO("***** Test 2 (Lagrange - Vegas)");
312   test2(LAGRANGE_VEGAS);
313   XBT_INFO("***** Test 2 (Lagrange - Reno)");
314   test2(LAGRANGE_RENO);
315
316   XBT_INFO("***** Test 3 (Max-Min)");
317   test3(MAXMIN);
318   XBT_INFO("***** Test 3 (Lagrange - Vegas)");
319   test3(LAGRANGE_VEGAS);
320   XBT_INFO("***** Test 3 (Lagrange - Reno)");
321   test3(LAGRANGE_RENO);
322
323   return 0;
324 }