aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Wachs <wachs@net.in.tum.de>2013-02-21 15:12:21 +0000
committerMatthias Wachs <wachs@net.in.tum.de>2013-02-21 15:12:21 +0000
commit2e7a719b552a1729684e90c6620553c42260576a (patch)
treeab756de7143a47e64fb156754cc7ac5cd7c58f7e /src
parentf3738485c15930fc8c1386ed8d2b9734087403fa (diff)
downloadgnunet-2e7a719b552a1729684e90c6620553c42260576a.tar.gz
gnunet-2e7a719b552a1729684e90c6620553c42260576a.zip
result propagation
Diffstat (limited to 'src')
-rw-r--r--src/ats/gnunet-service-ats_addresses_mlp.c232
-rw-r--r--src/ats/gnunet-service-ats_addresses_mlp.h2
2 files changed, 67 insertions, 167 deletions
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.c b/src/ats/gnunet-service-ats_addresses_mlp.c
index 6af971179..ac82a6a12 100644
--- a/src/ats/gnunet-service-ats_addresses_mlp.c
+++ b/src/ats/gnunet-service-ats_addresses_mlp.c
@@ -366,173 +366,6 @@ mlp_lookup_ats (struct ATS_Address *addr, int ats_index)
366} 366}
367#endif 367#endif
368 368
369/**
370 * Solves the LP problem
371 *
372 * @param mlp the MLP Handle
373 * @param s_ctx context to return results
374 * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
375 */
376static int
377mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *s_ctx)
378{
379 int res;
380 struct GNUNET_TIME_Relative duration;
381 struct GNUNET_TIME_Absolute end;
382 struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
383
384 /* LP presolver?
385 * Presolver is required if the problem was modified and an existing
386 * valid basis is now invalid */
387 if (mlp->presolver_required == GNUNET_YES)
388 mlp->control_param_lp.presolve = GLP_ON;
389 else
390 mlp->control_param_lp.presolve = GLP_OFF;
391
392 /* Solve LP problem to have initial valid solution */
393lp_solv:
394 res = glp_simplex(mlp->prob, &mlp->control_param_lp);
395 if (res == 0)
396 {
397 /* The LP problem instance has been successfully solved. */
398 }
399 else if (res == GLP_EITLIM)
400 {
401 /* simplex iteration limit has been exceeded. */
402 // TODO Increase iteration limit?
403 }
404 else if (res == GLP_ETMLIM)
405 {
406 /* Time limit has been exceeded. */
407 // TODO Increase time limit?
408 }
409 else
410 {
411 /* Problem was ill-defined, retry with presolver */
412 if (mlp->presolver_required == GNUNET_NO)
413 {
414 mlp->presolver_required = GNUNET_YES;
415 goto lp_solv;
416 }
417 else
418 {
419 /* Problem was ill-defined, no way to handle that */
420 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
421 "ats-mlp",
422 "Solving LP problem failed: %i %s\n", res, mlp_solve_to_string(res));
423 return GNUNET_SYSERR;
424 }
425 }
426
427 end = GNUNET_TIME_absolute_get ();
428 duration = GNUNET_TIME_absolute_get_difference (start, end);
429 mlp->lp_solved++;
430 mlp->lp_total_duration += duration.rel_value;
431 s_ctx->lp_duration = duration;
432
433 GNUNET_STATISTICS_update (mlp->stats,"# LP problem solved", 1, GNUNET_NO);
434 GNUNET_STATISTICS_set (mlp->stats,"# LP execution time (ms)", duration.rel_value, GNUNET_NO);
435 GNUNET_STATISTICS_set (mlp->stats,"# LP execution time average (ms)",
436 mlp->lp_total_duration / mlp->lp_solved, GNUNET_NO);
437
438 /* Analyze problem status */
439 res = glp_get_status (mlp->prob);
440 switch (res) {
441 /* solution is optimal */
442 case GLP_OPT:
443 /* solution is feasible */
444 case GLP_FEAS:
445 break;
446
447 /* Problem was ill-defined, no way to handle that */
448 default:
449 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
450 "ats-mlp",
451 "Solving LP problem failed, no solution: %s\n", mlp_status_to_string(res));
452 return GNUNET_SYSERR;
453 break;
454 }
455
456 /* solved sucessfully, no presolver required next time */
457 mlp->presolver_required = GNUNET_NO;
458
459 return GNUNET_OK;
460}
461
462
463/**
464 * Solves the MLP problem
465 *
466 * @param mlp the MLP Handle
467 * @param s_ctx context to return results
468 * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
469 */
470int
471mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp, struct GAS_MLP_SolutionContext *s_ctx)
472{
473 int res;
474 struct GNUNET_TIME_Relative duration;
475 struct GNUNET_TIME_Absolute end;
476 struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get();
477
478 /* solve MLP problem */
479 res = glp_intopt(mlp->prob, &mlp->control_param_mlp);
480
481 if (res == 0)
482 {
483 /* The MLP problem instance has been successfully solved. */
484 }
485 else if (res == GLP_EITLIM)
486 {
487 /* simplex iteration limit has been exceeded. */
488 // TODO Increase iteration limit?
489 }
490 else if (res == GLP_ETMLIM)
491 {
492 /* Time limit has been exceeded. */
493 // TODO Increase time limit?
494 }
495 else
496 {
497 /* Problem was ill-defined, no way to handle that */
498 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
499 "ats-mlp",
500 "Solving MLP problem failed: %s\n", mlp_solve_to_string(res));
501 return GNUNET_SYSERR;
502 }
503
504 end = GNUNET_TIME_absolute_get ();
505 duration = GNUNET_TIME_absolute_get_difference (start, end);
506 mlp->mlp_solved++;
507 mlp->mlp_total_duration += duration.rel_value;
508 s_ctx->mlp_duration = duration;
509
510 GNUNET_STATISTICS_update (mlp->stats,"# MLP problem solved", 1, GNUNET_NO);
511 GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time (ms)", duration.rel_value, GNUNET_NO);
512 GNUNET_STATISTICS_set (mlp->stats,"# MLP execution time average (ms)",
513 mlp->mlp_total_duration / mlp->mlp_solved, GNUNET_NO);
514
515 /* Analyze problem status */
516 res = glp_mip_status(mlp->prob);
517 switch (res) {
518 /* solution is optimal */
519 case GLP_OPT:
520 /* solution is feasible */
521 case GLP_FEAS:
522 break;
523
524 /* Problem was ill-defined, no way to handle that */
525 default:
526 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
527 "ats-mlp",
528 "Solving MLP problem failed, %s\n\n", mlp_status_to_string(res));
529 return GNUNET_SYSERR;
530 break;
531 }
532
533 return GNUNET_OK;
534}
535
536int GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx); 369int GAS_mlp_solve_problem (void *solver, struct GAS_MLP_SolutionContext *ctx);
537 370
538 371
@@ -1470,6 +1303,64 @@ mlp_solve_mlp_problem (struct GAS_MLP_Handle *mlp)
1470/** 1303/**
1471 * Solves the MLP problem 1304 * Solves the MLP problem
1472 * 1305 *
1306 * @param mlp the MLP Handle
1307 * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
1308 */
1309int
1310mlp_propagate_results (void *cls, const struct GNUNET_HashCode *key, void *value)
1311{
1312 struct GAS_MLP_Handle *mlp = cls;
1313 struct ATS_Address *address;
1314 struct MLP_information *mlpi;
1315 double mlp_bw;
1316 double mlp_use;
1317
1318 /* Check if we have to add this peer due to a pending request */
1319 if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(mlp->peers, key))
1320 return GNUNET_OK;
1321
1322 address = value;
1323 GNUNET_assert (address->solver_information != NULL);
1324 mlpi = address->solver_information;
1325
1326 mlp_bw = glp_mip_col_val(mlp->p.prob, mlpi->c_b);
1327 mlp_use = glp_mip_col_val(mlp->p.prob, mlpi->c_n);
1328
1329 if ((GLP_YES == mlp_use) && (GNUNET_NO == address->active))
1330 {
1331 /* Address switch: Activate address*/
1332 address->active = GNUNET_YES;
1333 address->assigned_bw_in.value__ = htonl (0);
1334 address->assigned_bw_out.value__ = htonl (0);
1335 mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
1336 }
1337 else if ((GLP_NO == mlp_use) && (GNUNET_YES == address->active))
1338 {
1339 /* Address switch: Disable address*/
1340 address->active = GNUNET_NO;
1341 /* Set bandwidth to 0 */
1342 address->assigned_bw_in.value__ = htonl (0);
1343 address->assigned_bw_out.value__ = htonl (0);
1344 mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
1345 }
1346 else if ((mlp_bw != ntohl(address->assigned_bw_out.value__)) ||
1347 (mlp_bw != ntohl(address->assigned_bw_in.value__)))
1348 {
1349 /* Bandwidth changed */
1350 address->assigned_bw_in.value__ = htonl (mlp_bw);
1351 address->assigned_bw_out.value__ = htonl (mlp_bw);
1352 mlp->bw_changed_cb (mlp->bw_changed_cb_cls, address);
1353 }
1354
1355 return GNUNET_OK;
1356}
1357
1358
1359
1360
1361/**
1362 * Solves the MLP problem
1363 *
1473 * @param solver the MLP Handle 1364 * @param solver the MLP Handle
1474 * @param addresses the address hashmap 1365 * @param addresses the address hashmap
1475 * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure 1366 * @return GNUNET_OK if could be solved, GNUNET_SYSERR on failure
@@ -1502,6 +1393,7 @@ GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addr
1502 LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n"); 1393 LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
1503 } 1394 }
1504 1395
1396
1505 /* Run LP solver */ 1397 /* Run LP solver */
1506 LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver \n"); 1398 LOG (GNUNET_ERROR_TYPE_DEBUG, "Running LP solver \n");
1507 start_lp = GNUNET_TIME_absolute_get(); 1399 start_lp = GNUNET_TIME_absolute_get();
@@ -1517,6 +1409,12 @@ GAS_mlp_solve_problem (void *solver, struct GNUNET_CONTAINER_MultiHashMap * addr
1517 (unsigned long long) duration_lp.rel_value, 1409 (unsigned long long) duration_lp.rel_value,
1518 (unsigned long long) duration_mlp.rel_value); 1410 (unsigned long long) duration_mlp.rel_value);
1519 1411
1412 /* Propagate result*/
1413 if (GNUNET_OK == res)
1414 {
1415 GNUNET_CONTAINER_multihashmap_iterate (addresses, &mlp_propagate_results, mlp);
1416 }
1417
1520 /* Reset change and update marker */ 1418 /* Reset change and update marker */
1521 mlp->mlp_prob_updated = GNUNET_NO; 1419 mlp->mlp_prob_updated = GNUNET_NO;
1522 mlp->mlp_prob_changed = GNUNET_NO; 1420 mlp->mlp_prob_changed = GNUNET_NO;
diff --git a/src/ats/gnunet-service-ats_addresses_mlp.h b/src/ats/gnunet-service-ats_addresses_mlp.h
index 920bea405..efb819c60 100644
--- a/src/ats/gnunet-service-ats_addresses_mlp.h
+++ b/src/ats/gnunet-service-ats_addresses_mlp.h
@@ -49,6 +49,8 @@
49#define DEFAULT_MIN_CONNECTIONS 4 49#define DEFAULT_MIN_CONNECTIONS 4
50 50
51#define NaN -1 51#define NaN -1
52#define GLP_YES 1.0
53#define GLP_NO 0.0
52 54
53struct ATS_Peer 55struct ATS_Peer
54{ 56{