GNUnet  0.10.x
Data Structures | Macros | Enumerations | Functions
plugin_ats_mlp.c File Reference

ats mlp problem solver More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_ats_service.h"
#include "gnunet_ats_plugin.h"
#include "gnunet-service-ats_addresses.h"
#include "gnunet_statistics_service.h"
#include <float.h>
#include <glpk.h>
Include dependency graph for plugin_ats_mlp.c:

Go to the source code of this file.

Data Structures

struct  MLP_Solution
 
struct  ATS_Peer
 
struct  MLP_Problem
 
struct  MLP_Variables
 
struct  GAS_MLP_Handle
 MLP Handle. More...
 
struct  MLP_information
 Address specific MLP information. More...
 
struct  CountContext
 

Macros

#define BIG_M_VALUE   (UINT32_MAX) / 10
 
#define BIG_M_STRING   "unlimited"
 
#define MLP_AVERAGING_QUEUE_LENGTH   3
 
#define MLP_MAX_EXEC_DURATION
 
#define MLP_MAX_ITERATIONS   4096
 
#define MLP_DEFAULT_D   1.0
 
#define MLP_DEFAULT_R   1.0
 
#define MLP_DEFAULT_U   1.0
 
#define MLP_DEFAULT_QUALITY   1.0
 
#define MLP_DEFAULT_MIN_CONNECTIONS   4
 
#define MLP_DEFAULT_PEER_PREFERENCE   1.0
 
#define MLP_NaN   -1
 
#define MLP_UNDEFINED   0
 
#define GLP_YES   1.0
 
#define GLP_NO   0.0
 
#define LOG(kind, ...)   GNUNET_log_from (kind, "ats-mlp", __VA_ARGS__)
 NOTE: Do not modify this documentation. More...
 
#define DEBUG_MLP_PROBLEM_CREATION   GNUNET_NO
 Print debug output for mlp problem creation. More...
 

Enumerations

enum  MLP_Output_Format { MLP_MPS, MLP_CPLEX, MLP_GLPK }
 
enum  QualityMetrics { RQ_QUALITY_METRIC_DELAY = 0, RQ_QUALITY_METRIC_DISTANCE = 1, RQ_QUALITY_METRIC_COUNT = 2 }
 

Functions

static const char * print_quality_type (enum QualityMetrics qm)
 
static int mlp_term_hook (void *info, const char *s)
 Intercept GLPK terminal output. More...
 
static int reset_peers (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Reset peers for next problem creation. More...
 
static void mlp_delete_problem (struct GAS_MLP_Handle *mlp)
 Delete the MLP problem and free the constrain matrix. More...
 
static const char * mlp_status_to_string (int retcode)
 Translate glpk status error codes to text. More...
 
static const char * mlp_solve_to_string (int retcode)
 Translate glpk solver error codes to text. More...
 
static int mlp_create_problem_count_addresses_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 
static int mlp_create_problem_count_addresses (const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses)
 
static int mlp_create_problem_count_peers_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 
static int mlp_create_problem_count_peers (const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses)
 
static int mlp_create_problem_update_value (struct MLP_Problem *p, int row, int col, double val, int line)
 Updates an existing value in the matrix. More...
 
static void mlp_create_problem_set_value (struct MLP_Problem *p, int row, int col, double val, int line)
 Creates a new value in the matrix. More...
 
static int mlp_create_problem_create_column (struct MLP_Problem *p, char *name, unsigned int type, unsigned int bound, double lb, double ub, double coef)
 
static int mlp_create_problem_create_constraint (struct MLP_Problem *p, char *name, unsigned int bound, double lb, double ub)
 
static int mlp_create_problem_add_address_information (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Create the. More...
 
static void mlp_create_problem_add_invariant_rows (struct GAS_MLP_Handle *mlp, struct MLP_Problem *p)
 Create the invariant columns c4, c6, c10, c8, c7. More...
 
static void mlp_create_problem_add_invariant_columns (struct GAS_MLP_Handle *mlp, struct MLP_Problem *p)
 Create the invariant columns d, u, r, q0 ... More...
 
static int mlp_create_problem (struct GAS_MLP_Handle *mlp)
 Create the MLP problem. More...
 
static int mlp_solve_lp_problem (struct GAS_MLP_Handle *mlp)
 Solves the LP problem. More...
 
static int mlp_propagate_results (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Propagates the results when MLP problem was solved. More...
 
static void notify (struct GAS_MLP_Handle *mlp, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add)
 
static void mlp_branch_and_cut_cb (glp_tree *tree, void *info)
 
static int GAS_mlp_solve_problem (void *solver)
 Solves the MLP problem. More...
 
static void GAS_mlp_address_add (void *solver, struct ATS_Address *address, uint32_t network)
 Add a single address to the solve. More...
 
static void GAS_mlp_address_property_changed (void *solver, struct ATS_Address *address)
 Transport properties for this address have changed. More...
 
static int mlp_get_preferred_address_it (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Find the active address in the set of addresses of a peer. More...
 
static double get_peer_pref_value (struct GAS_MLP_Handle *mlp, const struct GNUNET_PeerIdentity *peer)
 
static void GAS_mlp_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer)
 Get the preferred address for a specific peer. More...
 
static void GAS_mlp_address_delete (void *solver, struct ATS_Address *address)
 Deletes a single address in the MLP problem. More...
 
static void GAS_mlp_bulk_start (void *solver)
 Start a bulk operation. More...
 
static void GAS_mlp_bulk_stop (void *solver)
 
static void GAS_mlp_stop_get_preferred_address (void *solver, const struct GNUNET_PeerIdentity *peer)
 Stop notifying about address and bandwidth changes for this peer. More...
 
static void GAS_mlp_address_change_preference (void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel)
 Changes the preferences for a peer in the MLP problem. More...
 
static void GAS_mlp_address_preference_feedback (void *solver, struct GNUNET_SERVICE_Client *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score)
 Get application feedback for a peer. More...
 
static int mlp_free_peers (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 
void * libgnunet_plugin_ats_mlp_done (void *cls)
 Shutdown the MLP problem solving component. More...
 
void * libgnunet_plugin_ats_mlp_init (void *cls)
 

Detailed Description

ats mlp problem solver

Author
Matthias Wachs
Christian Grothoff

Definition in file plugin_ats_mlp.c.

Macro Definition Documentation

◆ BIG_M_VALUE

#define BIG_M_VALUE   (UINT32_MAX) / 10

Definition at line 37 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ BIG_M_STRING

#define BIG_M_STRING   "unlimited"

Definition at line 38 of file plugin_ats_mlp.c.

◆ MLP_AVERAGING_QUEUE_LENGTH

#define MLP_AVERAGING_QUEUE_LENGTH   3

Definition at line 40 of file plugin_ats_mlp.c.

◆ MLP_MAX_EXEC_DURATION

#define MLP_MAX_EXEC_DURATION
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:440

Definition at line 42 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_MAX_ITERATIONS

#define MLP_MAX_ITERATIONS   4096

Definition at line 44 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_D

#define MLP_DEFAULT_D   1.0

Definition at line 46 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_R

#define MLP_DEFAULT_R   1.0

Definition at line 47 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_U

#define MLP_DEFAULT_U   1.0

Definition at line 48 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_QUALITY

#define MLP_DEFAULT_QUALITY   1.0

Definition at line 49 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_MIN_CONNECTIONS

#define MLP_DEFAULT_MIN_CONNECTIONS   4

Definition at line 50 of file plugin_ats_mlp.c.

Referenced by libgnunet_plugin_ats_mlp_init().

◆ MLP_DEFAULT_PEER_PREFERENCE

#define MLP_DEFAULT_PEER_PREFERENCE   1.0

Definition at line 51 of file plugin_ats_mlp.c.

◆ MLP_NaN

#define MLP_NaN   -1

Definition at line 53 of file plugin_ats_mlp.c.

Referenced by mlp_propagate_results().

◆ MLP_UNDEFINED

#define MLP_UNDEFINED   0

Definition at line 54 of file plugin_ats_mlp.c.

Referenced by mlp_delete_problem().

◆ GLP_YES

#define GLP_YES   1.0

Definition at line 55 of file plugin_ats_mlp.c.

Referenced by GAS_mlp_solve_problem(), and mlp_propagate_results().

◆ GLP_NO

#define GLP_NO   0.0

Definition at line 56 of file plugin_ats_mlp.c.

Referenced by GAS_mlp_solve_problem(), and mlp_propagate_results().

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "ats-mlp", __VA_ARGS__)

NOTE: Do not modify this documentation.

This documentation is based on gnunet.org:/vcs/fsnsg/ats-paper.git/tech-doku/ats-tech-guide.tex use build_txt.sh to generate plaintext output

The MLP solver (mlp) tries to finds an optimal bandwidth assignmentby optimizing an mixed integer programming problem. The MLP solver uses a number of constraints to find the best adddress for a peer and an optimal bandwidth assignment. mlp uses the GNU Linear Programming Kit to solve the MLP problem.

We defined a constraint system to find an optimal bandwidth assignment. This constraint system uses as an input data addresses, bandwidth quotas, preferences and quality values. This constraint system is stored in an matrix based equotation system.

5 Using GLPK

A (M)LP problem consists of a target function to optimizes, constraints and rows and columns. FIXME GLP uses three arrays to index the matrix: two integer arrays storing the row and column indices in the matrix and an float array to store the coeeficient.

To solve the problem we first find an initial solution for the LP problem using the LP solver and then find an MLP solution based on this solution using the MLP solver.

Solving (M)LP problems has the property that finding an initial solution for the LP problem is computationally expensive and finding the MLP solution is cheaper. This is especially interesting an existing LP solution can be reused if only coefficients in the matrix have changed (addresses updated). Only when the problem size changes (addresses added or deleted) a new LP solution has to be found.

Intended usage The mlp solver solves the bandwidth assignment problem only on demand when an address suggestion is requested. When an address is requested mlp the solves the mlp problem and if the active address or the bandwidth assigned changes it calls the callback to addresses. The mlp solver gets notified about new addresses (adding sessions), removed addresses (address deletions) and address updates. To benefit from the mlp properties mentioned in section 5 the solver rembers if since the last solution addresses were added or deleted (problem size changed, problem has to be rebuild and solved from sratch) or if addresses were updated and the existing solution can be reused.

5.1 Input data

The quotas for each network segment are passed by addresses. MLP can be adapted using configuration settings and uses the following parameters:

  • MLP_MAX_DURATION: Maximum duration for a MLP solution procees (default: 3 sec.)
  • MLP_MAX_ITERATIONS: Maximum number of iterations for a MLP solution process (default: 1024)
  • MLP_MIN_CONNECTIONS: Minimum number of desired connections (default: 4)
  • MLP_MIN_BANDWIDTH: Minimum amount of bandwidth assigned to an address (default: 1024)
  • MLP_COEFFICIENT_D: Diversity coefficient (default: 1.0)
  • MLP_COEFFICIENT_R: Relativity coefficient (default: 1.0)
  • MLP_COEFFICIENT_U: Utilization coefficient (default: 1.0)
  • MLP_COEFFICIENT_D: Diversity coefficient (default: 1.0)
  • MLP_COEFFICIENT_QUALITY_DELAY: Quality delay coefficient (default: 1.0)
  • MLP_COEFFICIENT_QUALITY_DISTANCE: Quality distance coefficient (default: 1.0)
  • MLP_COEFFICIENT_QUALITY_DISTANCE: Quality distance coefficient (default: 1.0)
  • MLP_COEFFICIENT_QUALITY_DISTANCE: Quality distance coefficient (default: 1.0)
  • MLP_COEFFICIENT_QUALITY_DISTANCE: Quality distance coefficient (default: 1.0)

5.2 Data structures used

mlp has for each known peer a struct ATS_Peer containing information about a specific peer. The address field solver_information contains information about the mlp properties of this address.

5.3 Initializing

During initialization mlp initializes the GLPK libray used to solve the MLP problem: it initializes the glpk environment and creates an initial LP problem. Next it loads the configuration values from the configuration or uses the default values configured in -addresses_mlp.h. The quotas used are given by addresses but may have to be adjusted. mlp uses a upper limit for the bandwidth assigned called BIG M and a minimum amount of bandwidth an address gets assigned as well as a minium desired number of connections. If the configured quota is bigger than BIG M, it is reduced to BIG M. If the configured quota is smaller than MLP_MIN_CONNECTIONS *MLP_MIN_BANDWIDTH it is increased to this value.

5.4 Shutdown

Definition at line 515 of file plugin_ats_mlp.c.

Referenced by GAS_mlp_address_add(), GAS_mlp_address_change_preference(), GAS_mlp_address_delete(), GAS_mlp_address_property_changed(), GAS_mlp_bulk_start(), GAS_mlp_bulk_stop(), GAS_mlp_get_preferred_address(), GAS_mlp_solve_problem(), get_peer_pref_value(), libgnunet_plugin_ats_mlp_done(), libgnunet_plugin_ats_mlp_init(), mlp_branch_and_cut_cb(), mlp_create_problem(), mlp_create_problem_create_column(), mlp_create_problem_create_constraint(), mlp_create_problem_set_value(), mlp_create_problem_update_value(), mlp_propagate_results(), mlp_solve_lp_problem(), and mlp_term_hook().

◆ DEBUG_MLP_PROBLEM_CREATION

#define DEBUG_MLP_PROBLEM_CREATION   GNUNET_NO

Print debug output for mlp problem creation.

Definition at line 520 of file plugin_ats_mlp.c.

Enumeration Type Documentation

◆ MLP_Output_Format

Enumerator
MLP_MPS 
MLP_CPLEX 
MLP_GLPK 

Definition at line 58 of file plugin_ats_mlp.c.

59 {
60  MLP_MPS,
61  MLP_CPLEX,
62  MLP_GLPK
63 };

◆ QualityMetrics

Enumerator
RQ_QUALITY_METRIC_DELAY 
RQ_QUALITY_METRIC_DISTANCE 
RQ_QUALITY_METRIC_COUNT 

Definition at line 66 of file plugin_ats_mlp.c.

Function Documentation

◆ print_quality_type()

static const char* print_quality_type ( enum QualityMetrics  qm)
static

Definition at line 75 of file plugin_ats_mlp.c.

References GNUNET_break, RQ_QUALITY_METRIC_DELAY, and RQ_QUALITY_METRIC_DISTANCE.

Referenced by mlp_create_problem_add_invariant_rows().

76 {
77  switch (qm)
78  {
80  return "delay";
81 
83  return "distance";
84 
85  default:
86  GNUNET_break (0);
87  return NULL;
88  }
89 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Here is the caller graph for this function:

◆ mlp_term_hook()

static int mlp_term_hook ( void *  info,
const char *  s 
)
static

Intercept GLPK terminal output.

Parameters
infothe mlp handle
sthe string to print
Returns
0: glpk prints output on terminal, 0 != surpress output

Definition at line 530 of file plugin_ats_mlp.c.

References GNUNET_ERROR_TYPE_ERROR, LOG, and GAS_MLP_Handle::opt_dbg_glpk_verbose.

Referenced by libgnunet_plugin_ats_mlp_init().

531 {
532  struct GAS_MLP_Handle *mlp = info;
533 
534  if (mlp->opt_dbg_glpk_verbose)
535  LOG (GNUNET_ERROR_TYPE_ERROR, "%s", s);
536  return 1;
537 }
int opt_dbg_glpk_verbose
Print GLPK output.
MLP Handle.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the caller graph for this function:

◆ reset_peers()

static int reset_peers ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Reset peers for next problem creation.

Parameters
clsnot used
keythe key
valueATS_Peer
Returns
GNUNET_OK

Definition at line 549 of file plugin_ats_mlp.c.

References GNUNET_NO, GNUNET_OK, peer, ATS_Peer::processed, and value.

Referenced by mlp_delete_problem().

552 {
553  struct ATS_Peer *peer = value;
554 
555  peer->processed = GNUNET_NO;
556  return GNUNET_OK;
557 }
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static char * value
Value of the record to add/remove.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
Here is the caller graph for this function:

◆ mlp_delete_problem()

static void mlp_delete_problem ( struct GAS_MLP_Handle mlp)
static

Delete the MLP problem and free the constrain matrix.

Parameters
mlpthe MLP handle

Definition at line 565 of file plugin_ats_mlp.c.

References MLP_Problem::ar, MLP_Problem::c_d, MLP_Problem::c_r, MLP_Problem::ci, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_free, GNUNET_NT_COUNT, MLP_Problem::ia, MLP_Problem::ja, MLP_UNDEFINED, GAS_MLP_Handle::p, MLP_Problem::prob, MLP_Problem::r_c2, MLP_Problem::r_c4, MLP_Problem::r_c6, MLP_Problem::r_c9, MLP_Problem::r_q, MLP_Problem::r_quota, GAS_MLP_Handle::requested_peers, reset_peers(), and RQ_QUALITY_METRIC_COUNT.

Referenced by GAS_mlp_solve_problem(), and libgnunet_plugin_ats_mlp_done().

566 {
567  int c;
568 
569  if (mlp == NULL)
570  return;
571  if (mlp->p.prob != NULL)
572  {
573  glp_delete_prob (mlp->p.prob);
574  mlp->p.prob = NULL;
575  }
576 
577  /* delete row index */
578  if (mlp->p.ia != NULL)
579  {
580  GNUNET_free (mlp->p.ia);
581  mlp->p.ia = NULL;
582  }
583 
584  /* delete column index */
585  if (mlp->p.ja != NULL)
586  {
587  GNUNET_free (mlp->p.ja);
588  mlp->p.ja = NULL;
589  }
590 
591  /* delete coefficients */
592  if (mlp->p.ar != NULL)
593  {
594  GNUNET_free (mlp->p.ar);
595  mlp->p.ar = NULL;
596  }
597  mlp->p.ci = 0;
598  mlp->p.prob = NULL;
599 
600  mlp->p.c_d = MLP_UNDEFINED;
601  mlp->p.c_r = MLP_UNDEFINED;
602  mlp->p.r_c2 = MLP_UNDEFINED;
603  mlp->p.r_c4 = MLP_UNDEFINED;
604  mlp->p.r_c6 = MLP_UNDEFINED;
605  mlp->p.r_c9 = MLP_UNDEFINED;
606  for (c = 0; c < RQ_QUALITY_METRIC_COUNT; c++)
607  mlp->p.r_q[c] = MLP_UNDEFINED;
608  for (c = 0; c < GNUNET_NT_COUNT; c++)
609  mlp->p.r_quota[c] = MLP_UNDEFINED;
610  mlp->p.ci = MLP_UNDEFINED;
611 
612 
614  &reset_peers, NULL);
615 }
int r_q[RQ_QUALITY_METRIC_COUNT]
glp_prob * prob
GLPK (MLP) problem object.
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
static int reset_peers(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Reset peers for next problem creation.
unsigned int r_c9
struct MLP_Problem p
Encapsulation for the MLP problem.
int r_quota[GNUNET_NT_COUNT]
#define MLP_UNDEFINED
unsigned int r_c6
unsigned int ci
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
unsigned int r_c2
unsigned int r_c4
#define GNUNET_NT_COUNT
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_status_to_string()

static const char* mlp_status_to_string ( int  retcode)
static

Translate glpk status error codes to text.

Parameters
retcodereturn code
Returns
string with result

Definition at line 624 of file plugin_ats_mlp.c.

References GNUNET_break.

Referenced by GAS_mlp_solve_problem(), and mlp_solve_lp_problem().

625 {
626  switch (retcode)
627  {
628  case GLP_UNDEF:
629  return "solution is undefined";
630 
631  case GLP_FEAS:
632  return "solution is feasible";
633 
634  case GLP_INFEAS:
635  return "solution is infeasible";
636 
637  case GLP_NOFEAS:
638  return "no feasible solution exists";
639 
640  case GLP_OPT:
641  return "solution is optimal";
642 
643  case GLP_UNBND:
644  return "solution is unbounded";
645 
646  default:
647  GNUNET_break (0);
648  return "unknown error";
649  }
650 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Here is the caller graph for this function:

◆ mlp_solve_to_string()

static const char* mlp_solve_to_string ( int  retcode)
static

Translate glpk solver error codes to text.

Parameters
retcodereturn code
Returns
string with result

Definition at line 659 of file plugin_ats_mlp.c.

References GNUNET_break.

Referenced by GAS_mlp_solve_problem(), and mlp_solve_lp_problem().

660 {
661  switch (retcode)
662  {
663  case 0:
664  return "ok";
665 
666  case GLP_EBADB:
667  return "invalid basis";
668 
669  case GLP_ESING:
670  return "singular matrix";
671 
672  case GLP_ECOND:
673  return "ill-conditioned matrix";
674 
675  case GLP_EBOUND:
676  return "invalid bounds";
677 
678  case GLP_EFAIL:
679  return "solver failed";
680 
681  case GLP_EOBJLL:
682  return "objective lower limit reached";
683 
684  case GLP_EOBJUL:
685  return "objective upper limit reached";
686 
687  case GLP_EITLIM:
688  return "iteration limit exceeded";
689 
690  case GLP_ETMLIM:
691  return "time limit exceeded";
692 
693  case GLP_ENOPFS:
694  return "no primal feasible solution";
695 
696  case GLP_ENODFS:
697  return "no dual feasible solution";
698 
699  case GLP_EROOT:
700  return "root LP optimum not provided";
701 
702  case GLP_ESTOP:
703  return "search terminated by application";
704 
705  case GLP_EMIPGAP:
706  return "relative mip gap tolerance reached";
707 
708  case GLP_ENOFEAS:
709  return "no dual feasible solution";
710 
711  case GLP_ENOCVG:
712  return "no convergence";
713 
714  case GLP_EINSTAB:
715  return "numerical instability";
716 
717  case GLP_EDATA:
718  return "invalid data";
719 
720  case GLP_ERANGE:
721  return "result out of range";
722 
723  default:
724  GNUNET_break (0);
725  return "unknown error";
726  }
727 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Here is the caller graph for this function:

◆ mlp_create_problem_count_addresses_it()

static int mlp_create_problem_count_addresses_it ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Definition at line 737 of file plugin_ats_mlp.c.

References GNUNET_CONTAINER_multipeermap_contains(), GNUNET_OK, GNUNET_YES, CountContext::map, and CountContext::result.

Referenced by mlp_create_problem_count_addresses().

740 {
741  struct CountContext *cctx = cls;
742 
743  /* Check if we have to add this peer due to a pending request */
745  cctx->result++;
746  return GNUNET_OK;
747 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_count_addresses()

static int mlp_create_problem_count_addresses ( const struct GNUNET_CONTAINER_MultiPeerMap requested_peers,
const struct GNUNET_CONTAINER_MultiPeerMap addresses 
)
static

Definition at line 751 of file plugin_ats_mlp.c.

References GNUNET_CONTAINER_multipeermap_iterate(), CountContext::map, mlp_create_problem_count_addresses_it(), and CountContext::result.

Referenced by mlp_create_problem().

756 {
757  struct CountContext cctx;
758 
759  cctx.map = requested_peers;
760  cctx.result = 0;
763  &cctx);
764  return cctx.result;
765 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
static int mlp_create_problem_count_addresses_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_count_peers_it()

static int mlp_create_problem_count_peers_it ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Definition at line 769 of file plugin_ats_mlp.c.

References GNUNET_CONTAINER_multipeermap_contains(), GNUNET_OK, GNUNET_YES, CountContext::map, and CountContext::result.

Referenced by mlp_create_problem_count_peers().

772 {
773  struct CountContext *cctx = cls;
774 
775  /* Check if we have to addresses for the requested peer */
777  cctx->result++;
778  return GNUNET_OK;
779 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_count_peers()

static int mlp_create_problem_count_peers ( const struct GNUNET_CONTAINER_MultiPeerMap requested_peers,
const struct GNUNET_CONTAINER_MultiPeerMap addresses 
)
static

Definition at line 783 of file plugin_ats_mlp.c.

References addresses, GNUNET_CONTAINER_multipeermap_iterate(), CountContext::map, mlp_create_problem_count_peers_it(), and CountContext::result.

Referenced by mlp_create_problem().

787 {
788  struct CountContext cctx;
789 
790  cctx.map = addresses;
791  cctx.result = 0;
792  GNUNET_CONTAINER_multipeermap_iterate (requested_peers,
794  &cctx);
795  return cctx.result;
796 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
static struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap to store addresses.
Definition: gnunet-ats.c:146
static int mlp_create_problem_count_peers_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_update_value()

static int mlp_create_problem_update_value ( struct MLP_Problem p,
int  row,
int  col,
double  val,
int  line 
)
static

Updates an existing value in the matrix.

Extract the row, updates the value and updates the row in the problem

Parameters
pthe mlp problem
rowthe row to create the value in
colthe column to create the value in
valthe value to set
linecalling line for debbuging
Returns
GNUNET_YES value changed, GNUNET_NO value did not change, GNUNET_SYSERR on error

Definition at line 813 of file plugin_ats_mlp.c.

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_malloc, GNUNET_NO, GNUNET_SYSERR, GNUNET_YES, LOG, MLP_Problem::prob, and res.

Referenced by GAS_mlp_address_change_preference(), and GAS_mlp_address_property_changed().

816 {
817  int c_cols;
818  int c_elems;
819  int c1;
820  int res;
821  int found;
822  double *val_array;
823  int *ind_array;
824 
825  GNUNET_assert (NULL != p->prob);
826 
827  /* Get number of columns and prepare data structure */
828  c_cols = glp_get_num_cols (p->prob);
829  if (0 >= c_cols)
830  return GNUNET_SYSERR;
831 
832  val_array = GNUNET_malloc ((c_cols + 1) * sizeof(double));
833  GNUNET_assert (NULL != val_array);
834  ind_array = GNUNET_malloc ((c_cols + 1) * sizeof(int));
835  GNUNET_assert (NULL != ind_array);
836  /* Extract the row */
837 
838  /* Update the value */
839  c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array);
840  found = GNUNET_NO;
841  for (c1 = 1; c1 < (c_elems + 1); c1++)
842  {
843  if (ind_array[c1] == col)
844  {
845  found = GNUNET_YES;
846  break;
847  }
848  }
849  if (GNUNET_NO == found)
850  {
851  ind_array[c_elems + 1] = col;
852  val_array[c_elems + 1] = val;
853  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n",
854  glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
855  val);
856  glp_set_mat_row (p->prob, row, c_elems + 1, ind_array, val_array);
857  GNUNET_free (ind_array);
858  GNUNET_free (val_array);
859  return GNUNET_YES;
860  }
861  else
862  {
863  /* Update value */
865  "[P] Updating value in [%s : %s] from `%.2f' to `%.2f'\n",
866  glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
867  val_array[c1], val);
868  if (val != val_array[c1])
869  res = GNUNET_YES;
870  else
871  res = GNUNET_NO;
872  val_array[c1] = val;
873  /* Update the row in the matrix */
874  glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array);
875  }
876 
877  GNUNET_free (ind_array);
878  GNUNET_free (val_array);
879  return res;
880 }
glp_prob * prob
GLPK (MLP) problem object.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
static int res
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_YES
Definition: gnunet_common.h:77
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the caller graph for this function:

◆ mlp_create_problem_set_value()

static void mlp_create_problem_set_value ( struct MLP_Problem p,
int  row,
int  col,
double  val,
int  line 
)
static

Creates a new value in the matrix.

Sets the row and column index in the problem array and increments the position field

Parameters
pthe mlp problem
rowthe row to create the value in
colthe column to create the value in
valthe value to set
linecalling line for debbuging

Definition at line 895 of file plugin_ats_mlp.c.

References MLP_Problem::ar, MLP_Problem::ci, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, MLP_Problem::ia, MLP_Problem::ja, LOG, and MLP_Problem::num_elements.

Referenced by mlp_create_problem_add_address_information(), and mlp_create_problem_add_invariant_rows().

898 {
899  if ((p->ci) >= p->num_elements)
900  {
902  "[P]: line %u: Request for index %u bigger than array size of %u\n",
903  line, p->ci + 1, p->num_elements);
904  GNUNET_break (0);
905  return;
906  }
907  if ((0 == row) || (0 == col))
908  {
909  GNUNET_break (0);
911  "[P]: Invalid call from line %u: row = %u, col = %u\n",
912  line, row, col);
913  }
914  p->ia[p->ci] = row;
915  p->ja[p->ci] = col;
916  p->ar[p->ci] = val;
917 #if DEBUG_MLP_PROBLEM_CREATION
919  "[P]: line %u: Set value [%u,%u] in index %u == %.2f\n",
920  line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]);
921 #endif
922  p->ci++;
923 }
unsigned int num_elements
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static char * line
Desired phone line (string to be converted to a hash).
unsigned int ci
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the caller graph for this function:

◆ mlp_create_problem_create_column()

static int mlp_create_problem_create_column ( struct MLP_Problem p,
char *  name,
unsigned int  type,
unsigned int  bound,
double  lb,
double  ub,
double  coef 
)
static

Definition at line 926 of file plugin_ats_mlp.c.

References GNUNET_ERROR_TYPE_DEBUG, LOG, and MLP_Problem::prob.

Referenced by mlp_create_problem_add_address_information(), and mlp_create_problem_add_invariant_columns().

930 {
931  int col = glp_add_cols (p->prob, 1);
932 
933  glp_set_col_name (p->prob, col, name);
934  glp_set_col_bnds (p->prob, col, bound, lb, ub);
935  glp_set_col_kind (p->prob, col, type);
936  glp_set_obj_coef (p->prob, col, coef);
937 #if DEBUG_MLP_PROBLEM_CREATION
938  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n",
939  col, name, coef);
940 #endif
941  return col;
942 }
glp_prob * prob
GLPK (MLP) problem object.
const char * name
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the caller graph for this function:

◆ mlp_create_problem_create_constraint()

static int mlp_create_problem_create_constraint ( struct MLP_Problem p,
char *  name,
unsigned int  bound,
double  lb,
double  ub 
)
static

Definition at line 945 of file plugin_ats_mlp.c.

References GNUNET_asprintf(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, LOG, op, and MLP_Problem::prob.

Referenced by mlp_create_problem_add_address_information(), and mlp_create_problem_add_invariant_rows().

947 {
948  char *op;
949  int row = glp_add_rows (p->prob, 1);
950 
951  /* set row name */
952  glp_set_row_name (p->prob, row, name);
953  /* set row bounds: <= 0 */
954  glp_set_row_bnds (p->prob, row, bound, lb, ub);
955  switch (bound)
956  {
957  case GLP_UP:
958  GNUNET_asprintf (&op, "-inf <= x <= %.2f", ub);
959  break;
960 
961  case GLP_DB:
962  GNUNET_asprintf (&op, "%.2f <= x <= %.2f", lb, ub);
963  break;
964 
965  case GLP_FX:
966  GNUNET_asprintf (&op, "%.2f == x == %.2f", lb, ub);
967  break;
968 
969  case GLP_LO:
970  GNUNET_asprintf (&op, "%.2f <= x <= inf", lb);
971  break;
972 
973  default:
974  GNUNET_asprintf (&op, "ERROR");
975  break;
976  }
977 #if DEBUG_MLP_PROBLEM_CREATION
978  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n",
979  row, name, op);
980 #endif
981  GNUNET_free (op);
982  return row;
983 }
glp_prob * prob
GLPK (MLP) problem object.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
const char * name
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_add_address_information()

static int mlp_create_problem_add_address_information ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Create the.

  • address columns b and n
  • address dependent constraint rows c1, c3
  • peer dependent rows c2 and c9
  • Set address dependent entries in problem matrix as well

Definition at line 993 of file plugin_ats_mlp.c.

References address, MLP_Variables::b_min, MLP_Variables::BIG_M, MLP_information::c_b, MLP_information::c_n, MLP_Problem::c_r, ATS_Peer::f, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_get(), GNUNET_free, GNUNET_i2s(), GNUNET_NO, GNUNET_NT_COUNT, GNUNET_OK, GNUNET_YES, mlp_create_problem_create_column(), mlp_create_problem_create_constraint(), mlp_create_problem_set_value(), MLP_information::n, name, GAS_NormalizationInfo::norm, ATS_Address::norm_delay, ATS_Address::norm_distance, GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_dbg_optimize_quality, GAS_MLP_Handle::opt_dbg_optimize_relativity, GAS_MLP_Handle::opt_dbg_optimize_utility, p, GAS_MLP_Handle::p, peer, ATS_Address::peer, ATS_Address::plugin, ATS_Peer::processed, ATS_Address::properties, GAS_MLP_Handle::pv, MLP_Variables::quota_in, MLP_Variables::quota_index, MLP_Variables::quota_out, MLP_information::r_c1, ATS_Peer::r_c2, MLP_information::r_c3, MLP_Problem::r_c4, MLP_Problem::r_c6, MLP_Problem::r_c8, ATS_Peer::r_c9, MLP_Problem::r_q, MLP_Problem::r_quota, GAS_MLP_Handle::requested_peers, RQ_QUALITY_METRIC_DELAY, RQ_QUALITY_METRIC_DISTANCE, GNUNET_ATS_Properties::scope, ATS_Address::solver_information, and value.

Referenced by mlp_create_problem().

997 {
998  struct GAS_MLP_Handle *mlp = cls;
999  struct MLP_Problem *p = &mlp->p;
1000  struct ATS_Address *address = value;
1001  struct ATS_Peer *peer;
1002  struct MLP_information *mlpi;
1003  char *name;
1004  double cur_bigm;
1005  uint32_t addr_net;
1006  uint32_t addr_net_index;
1007  unsigned long long max_quota;
1008  int c;
1009 
1010  /* Check if we have to add this peer due to a pending request */
1012  key))
1013  return GNUNET_OK;
1014 
1015  mlpi = address->solver_information;
1016  if (NULL == mlpi)
1017  {
1018  fprintf (stderr, "%s %p\n", GNUNET_i2s (&address->peer), address);
1019  GNUNET_break (0);
1020  return GNUNET_OK;
1021  }
1022 
1023  addr_net = address->properties.scope;
1024  for (addr_net_index = 0; addr_net_index < GNUNET_NT_COUNT; addr_net_index++)
1025  {
1026  if (mlp->pv.quota_index[addr_net_index] == addr_net)
1027  break;
1028  }
1029 
1030  if (addr_net_index >= GNUNET_NT_COUNT)
1031  {
1032  GNUNET_break (0);
1033  return GNUNET_OK;
1034  }
1035 
1036  max_quota = 0;
1037  for (c = 0; c < GNUNET_NT_COUNT; c++)
1038  {
1039  if (mlp->pv.quota_out[c] > max_quota)
1040  max_quota = mlp->pv.quota_out[c];
1041  if (mlp->pv.quota_in[c] > max_quota)
1042  max_quota = mlp->pv.quota_in[c];
1043  }
1044  if (max_quota > mlp->pv.BIG_M)
1045  cur_bigm = (double) mlp->pv.BIG_M;
1046  else
1047  cur_bigm = max_quota;
1048 
1049 
1050  /* Get peer */
1052  GNUNET_assert (NULL != peer);
1053  if (peer->processed == GNUNET_NO)
1054  {
1055  /* Add peer dependent constraints */
1056  /* Add c2) One address active per peer */
1057  GNUNET_asprintf (&name, "c2_%s", GNUNET_i2s (&address->peer));
1058  peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0,
1059  1.0);
1060  GNUNET_free (name);
1061  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1062  {
1064  {
1065  /* Add c9) Relativity */
1066  GNUNET_asprintf (&name, "c9_%s", GNUNET_i2s (&address->peer));
1067  peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0,
1068  0.0);
1069  GNUNET_free (name);
1070  /* c9) set coefficient */
1071  mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f,
1072  __LINE__);
1073  }
1074  }
1075  peer->processed = GNUNET_YES;
1076  }
1077 
1078  /* Reset addresses' solver information */
1079  mlpi->c_b = 0;
1080  mlpi->c_n = 0;
1081  mlpi->n = 0;
1082  mlpi->r_c1 = 0;
1083  mlpi->r_c3 = 0;
1084 
1085  /* Add bandwidth column */
1086  GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer),
1087  address->plugin, address);
1088  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1089  {
1090  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0,
1091  0.0, 0.0);
1092  }
1093  else
1094  {
1095  /* Maximize for bandwidth assignment in feasibility testing */
1096  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0,
1097  0.0, 1.0);
1098  }
1099  GNUNET_free (name);
1100 
1101  /* Add address active column */
1102  GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer),
1103  address->plugin, address);
1104  mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0,
1105  1.0, 0.0);
1106  GNUNET_free (name);
1107 
1108  /* Add address dependent constraints */
1109  /* Add c1) bandwidth capping: b_t + (-M) * n_t <= 0 */
1110  GNUNET_asprintf (&name, "c1_%s_%s_%p", GNUNET_i2s (&address->peer),
1111  address->plugin, address);
1112  mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 0.0);
1113  GNUNET_free (name);
1114  /* c1) set b = 1 coefficient */
1115  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__);
1116  /* c1) set n = - min (M, quota) coefficient */
1117  cur_bigm = (double) mlp->pv.quota_out[addr_net_index];
1118  if (cur_bigm > mlp->pv.BIG_M)
1119  cur_bigm = (double) mlp->pv.BIG_M;
1120  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -cur_bigm, __LINE__);
1121 
1122  /* Add constraint c 3) minimum bandwidth
1123  * b_t + (-n_t * b_min) >= 0
1124  * */
1125  GNUNET_asprintf (&name, "c3_%s_%s_%p", GNUNET_i2s (&address->peer),
1126  address->plugin, address);
1127  mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0);
1128  GNUNET_free (name);
1129 
1130  /* c3) set b = 1 coefficient */
1131  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__);
1132  /* c3) set n = -b_min coefficient */
1133  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n,
1134  -((double ) mlp->pv.b_min), __LINE__);
1135 
1136 
1137  /* Set coefficient entries in invariant rows */
1138 
1139  /* Feasbility */
1140 
1141  /* c 4) minimum connections */
1142  mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__);
1143  /* c 2) 1 address peer peer */
1144  mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__);
1145  /* c 10) obey network specific quotas
1146  * (1)*b_1 + ... + (1)*b_m <= quota_n
1147  */
1148  mlp_create_problem_set_value (p, p->r_quota[addr_net_index], mlpi->c_b, 1,
1149  __LINE__);
1150 
1151  /* Optimality */
1152  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1153  {
1154  /* c 6) maximize diversity */
1155  mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__);
1156  /* c 9) relativity */
1158  mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__);
1159  /* c 8) utility */
1161  mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__);
1162  /* c 7) Optimize quality */
1163  /* For all quality metrics, set quality of this address */
1165  {
1168  mlpi->c_b,
1169  address->norm_delay.norm,
1170  __LINE__);
1173  mlpi->c_b,
1174  address->norm_distance.norm,
1175  __LINE__);
1176  }
1177  }
1178 
1179  return GNUNET_OK;
1180 }
unsigned int b_min
int r_q[RQ_QUALITY_METRIC_COUNT]
signed int c_n
address usage column
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
int opt_dbg_feasibility_only
solve feasibility only
struct GNUNET_ATS_Properties properties
ATS performance information for this address.
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
int opt_dbg_optimize_relativity
solve autoscale the problem
struct GNUNET_PeerIdentity peer
Peer ID this address is for.
static int mlp_create_problem_create_constraint(struct MLP_Problem *p, char *name, unsigned int bound, double lb, double ub)
int quota_index[GNUNET_NT_COUNT]
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void mlp_create_problem_set_value(struct MLP_Problem *p, int row, int col, double val, int line)
Creates a new value in the matrix.
unsigned int r_c2
int opt_dbg_optimize_utility
solve autoscale the problem
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
char * plugin
Plugin name.
int opt_dbg_optimize_quality
solve autoscale the problem
struct MLP_Problem p
Encapsulation for the MLP problem.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Address specific MLP information.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
unsigned int r_c9
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * value
Value of the record to add/remove.
unsigned int r_c8
unsigned int r_c3
constraint 3: minimum bandwidth
int r_quota[GNUNET_NT_COUNT]
int n
Address selected.
unsigned long long quota_out[GNUNET_NT_COUNT]
Address with additional information.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
unsigned int r_c6
void * solver_information
Solver-specific information for this address.
const char * name
unsigned long long quota_in[GNUNET_NT_COUNT]
enum GNUNET_NetworkType scope
Which network scope does the respective address belong to? This property does not change...
MLP Handle.
unsigned int r_c1
constraint 1: bandwidth capping
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
signed int c_b
bandwidth column index
struct GAS_NormalizationInfo norm_delay
Normalized delay information for this address.
unsigned int r_c4
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
static char * address
GNS address for this phone.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_NT_COUNT
double norm
Normalized values from queue to a range of values [1.0...2.0].
static int mlp_create_problem_create_column(struct MLP_Problem *p, char *name, unsigned int type, unsigned int bound, double lb, double ub, double coef)
struct GAS_NormalizationInfo norm_distance
Normalized distance information for this address.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_add_invariant_rows()

static void mlp_create_problem_add_invariant_rows ( struct GAS_MLP_Handle mlp,
struct MLP_Problem p 
)
static

Create the invariant columns c4, c6, c10, c8, c7.

Definition at line 1187 of file plugin_ats_mlp.c.

References MLP_Problem::c_d, MLP_Problem::c_q, MLP_Problem::c_u, GNUNET_asprintf(), GNUNET_free, GNUNET_NO, GNUNET_NT_COUNT, GNUNET_NT_to_string(), GNUNET_YES, MLP_Variables::m_q, mlp_create_problem_create_constraint(), mlp_create_problem_set_value(), MLP_Variables::n_min, name, MLP_Problem::num_peers, GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_dbg_optimize_diversity, GAS_MLP_Handle::opt_dbg_optimize_quality, GAS_MLP_Handle::opt_dbg_optimize_utility, print_quality_type(), GAS_MLP_Handle::pv, MLP_Variables::quota_index, MLP_Variables::quota_out, MLP_Problem::r_c4, MLP_Problem::r_c6, MLP_Problem::r_c8, MLP_Problem::r_q, and MLP_Problem::r_quota.

Referenced by mlp_create_problem().

1189 {
1190  int c;
1191 
1192  /* Feasibility */
1193 
1194  /* Row for c4) minimum connection */
1195  /* Number of minimum connections is min(|Peers|, n_min) */
1196  p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO,
1197  (mlp->pv.n_min >
1198  p->num_peers) ?
1199  p->num_peers : mlp->pv.n_min,
1200  0.0);
1201 
1202  /* Rows for c 10) Enforce network quotas */
1203  for (c = 0; c < GNUNET_NT_COUNT; c++)
1204  {
1205  char *text;
1206  GNUNET_asprintf (&text, "c10_quota_ats_%s",
1207  GNUNET_NT_to_string (mlp->pv.quota_index[c]));
1208  p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 0.0,
1209  mlp->pv.quota_out[c]);
1210  GNUNET_free (text);
1211  }
1212 
1213  /* Optimality */
1214  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1215  {
1216  char *name;
1217  /* Add row for c6) Maximize for diversity */
1219  {
1220  p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0,
1221  0.0);
1222  /* Set c6 ) Setting -D */
1223  mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__);
1224  }
1225 
1226  /* Adding rows for c 8) Maximize utility */
1228  {
1229  p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0,
1230  0.0);
1231  /* -u */
1232  mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__);
1233  }
1234 
1235  /* For all quality metrics:
1236  * c 7) Maximize quality, austerity */
1238  {
1239  for (c = 0; c < mlp->pv.m_q; c++)
1240  {
1241  GNUNET_asprintf (&name,
1242  "c7_q%i_%s", c,
1243  print_quality_type (c));
1244  p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0,
1245  0.0);
1246  GNUNET_free (name);
1248  p->r_q[c],
1249  p->c_q[c], -1, __LINE__);
1250  }
1251  }
1252  }
1253 }
int r_q[RQ_QUALITY_METRIC_COUNT]
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:44
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
int opt_dbg_feasibility_only
solve feasibility only
static const char * print_quality_type(enum QualityMetrics qm)
static int mlp_create_problem_create_constraint(struct MLP_Problem *p, char *name, unsigned int bound, double lb, double ub)
int quota_index[GNUNET_NT_COUNT]
static void mlp_create_problem_set_value(struct MLP_Problem *p, int row, int col, double val, int line)
Creates a new value in the matrix.
int opt_dbg_optimize_utility
solve autoscale the problem
#define GNUNET_NO
Definition: gnunet_common.h:78
unsigned int num_peers
int opt_dbg_optimize_quality
solve autoscale the problem
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
unsigned int n_min
unsigned int r_c8
int r_quota[GNUNET_NT_COUNT]
unsigned long long quota_out[GNUNET_NT_COUNT]
unsigned int r_c6
int opt_dbg_optimize_diversity
solve autoscale the problem
const char * name
int c_q[RQ_QUALITY_METRIC_COUNT]
unsigned int r_c4
#define GNUNET_YES
Definition: gnunet_common.h:77
#define GNUNET_NT_COUNT
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem_add_invariant_columns()

static void mlp_create_problem_add_invariant_columns ( struct GAS_MLP_Handle mlp,
struct MLP_Problem p 
)
static

Create the invariant columns d, u, r, q0 ...

qm

Definition at line 1260 of file plugin_ats_mlp.c.

References MLP_Problem::c_d, MLP_Problem::c_q, MLP_Problem::c_r, MLP_Problem::c_u, MLP_Variables::co_D, MLP_Variables::co_Q, MLP_Variables::co_R, MLP_Variables::co_U, GNUNET_asprintf(), GNUNET_free, GNUNET_NO, GNUNET_YES, MLP_Variables::m_q, mlp_create_problem_create_column(), name, GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_dbg_optimize_diversity, GAS_MLP_Handle::opt_dbg_optimize_quality, GAS_MLP_Handle::opt_dbg_optimize_relativity, GAS_MLP_Handle::opt_dbg_optimize_utility, and GAS_MLP_Handle::pv.

Referenced by mlp_create_problem().

1262 {
1263  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1264  {
1265  char *name;
1266  int c;
1267 
1268  /* Diversity d column */
1270  p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0,
1271  0.0, mlp->pv.co_D);
1272 
1273  /* Utilization u column */
1275  p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0,
1276  0.0, mlp->pv.co_U);
1277 
1278  /* Relativity r column */
1280  p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0,
1281  0.0, mlp->pv.co_R);
1282 
1283  /* Quality metric columns */
1285  {
1286  for (c = 0; c < mlp->pv.m_q; c++)
1287  {
1288  GNUNET_asprintf (&name, "q_%u", c);
1289  p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO,
1290  0.0, 0.0,
1291  mlp->pv.co_Q[c]);
1292  GNUNET_free (name);
1293  }
1294  }
1295  }
1296 }
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
int opt_dbg_feasibility_only
solve feasibility only
int opt_dbg_optimize_relativity
solve autoscale the problem
int opt_dbg_optimize_utility
solve autoscale the problem
#define GNUNET_NO
Definition: gnunet_common.h:78
int opt_dbg_optimize_quality
solve autoscale the problem
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int opt_dbg_optimize_diversity
solve autoscale the problem
double co_Q[RQ_QUALITY_METRIC_COUNT]
const char * name
int c_q[RQ_QUALITY_METRIC_COUNT]
#define GNUNET_YES
Definition: gnunet_common.h:77
static int mlp_create_problem_create_column(struct MLP_Problem *p, char *name, unsigned int type, unsigned int bound, double lb, double ub, double coef)
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_create_problem()

static int mlp_create_problem ( struct GAS_MLP_Handle mlp)
static

Create the MLP problem.

Parameters
mlpthe MLP handle
Returns
GNUNET_OK or GNUNET_SYSERR

Definition at line 1306 of file plugin_ats_mlp.c.

References _, GNUNET_ATS_PluginEnvironment::addresses, MLP_Problem::ar, MLP_Problem::ci, GAS_MLP_Handle::env, GNUNET_assert, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_malloc, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, MLP_Problem::ia, MLP_Problem::ja, LOG, MLP_Variables::m_q, mlp_create_problem_add_address_information(), mlp_create_problem_add_invariant_columns(), mlp_create_problem_add_invariant_rows(), mlp_create_problem_count_addresses(), mlp_create_problem_count_peers(), MLP_Problem::num_addresses, MLP_Problem::num_elements, MLP_Problem::num_peers, GAS_MLP_Handle::opt_dbg_autoscale_problem, p, GAS_MLP_Handle::p, MLP_Problem::prob, GAS_MLP_Handle::pv, GAS_MLP_Handle::requested_peers, and res.

Referenced by GAS_mlp_solve_problem().

1307 {
1308  struct MLP_Problem *p = &mlp->p;
1309  int res = GNUNET_OK;
1310 
1311  GNUNET_assert (p->prob == NULL);
1312  GNUNET_assert (p->ia == NULL);
1313  GNUNET_assert (p->ja == NULL);
1314  GNUNET_assert (p->ar == NULL);
1315  /* Reset MLP problem struct */
1316 
1317  /* create the glpk problem */
1318  p->prob = glp_create_prob ();
1319  GNUNET_assert (NULL != p->prob);
1321  mlp->env->addresses);
1323  mlp->env->addresses);
1324 
1325  /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 2 + 1 */
1326  p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses
1327  + mlp->pv.m_q + p->num_peers + 2 + 1);
1329  "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality metrics == %u elements\n",
1330  p->num_peers,
1331  p->num_addresses,
1332  mlp->pv.m_q,
1333  p->num_elements);
1334 
1335  /* Set a problem name */
1336  glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution");
1337  /* Set optimization direction to maximize */
1338  glp_set_obj_dir (p->prob, GLP_MAX);
1339 
1340  /* Create problem matrix */
1341  /* last +1 caused by glpk index starting with one: [1..elements]*/
1342  p->ci = 1;
1343  /* row index */
1344  p->ia = GNUNET_malloc (p->num_elements * sizeof(int));
1345  /* column index */
1346  p->ja = GNUNET_malloc (p->num_elements * sizeof(int));
1347  /* coefficient */
1348  p->ar = GNUNET_malloc (p->num_elements * sizeof(double));
1349 
1350  if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar))
1351  {
1353  "Problem size too large, cannot allocate memory!\n"));
1354  return GNUNET_SYSERR;
1355  }
1356 
1357  /* Adding invariant columns */
1359 
1360  /* Adding address independent constraint rows */
1362 
1363  /* Adding address dependent columns constraint rows */
1365  &
1367  mlp);
1368 
1369  /* Load the matrix */
1370  LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n");
1371  glp_load_matrix (p->prob, (p->ci) - 1, p->ia, p->ja, p->ar);
1373  {
1374  glp_scale_prob (p->prob, GLP_SF_AUTO);
1375  }
1376 
1377  return res;
1378 }
glp_prob * prob
GLPK (MLP) problem object.
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void mlp_create_problem_add_invariant_columns(struct GAS_MLP_Handle *mlp, struct MLP_Problem *p)
Create the invariant columns d, u, r, q0 ...
unsigned int num_elements
static int mlp_create_problem_add_address_information(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Create the.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
unsigned int num_peers
static int mlp_create_problem_count_addresses(const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses)
struct MLP_Problem p
Encapsulation for the MLP problem.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static int mlp_create_problem_count_peers(const struct GNUNET_CONTAINER_MultiPeerMap *requested_peers, const struct GNUNET_CONTAINER_MultiPeerMap *addresses)
struct GNUNET_ATS_PluginEnvironment * env
static int res
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int opt_dbg_autoscale_problem
solve autoscale the problem
unsigned int ci
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
#define GNUNET_YES
Definition: gnunet_common.h:77
unsigned int num_addresses
struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap containing all addresses available.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_malloc(size)
Wrapper around malloc.
static void mlp_create_problem_add_invariant_rows(struct GAS_MLP_Handle *mlp, struct MLP_Problem *p)
Create the invariant columns c4, c6, c10, c8, c7.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_solve_lp_problem()

static int mlp_solve_lp_problem ( struct GAS_MLP_Handle mlp)
static

Solves the LP problem.

Parameters
mlpthe MLP Handle
Returns
GNUNET_OK if could be solved, GNUNET_SYSERR on failure

Definition at line 1388 of file plugin_ats_mlp.c.

References GAS_MLP_Handle::control_param_lp, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_OK, GNUNET_SYSERR, LOG, mlp_solve_to_string(), mlp_status_to_string(), GAS_MLP_Handle::p, MLP_Problem::prob, and res.

Referenced by GAS_mlp_solve_problem().

1389 {
1390  int res = 0;
1391  int res_status = 0;
1392 
1393  res = glp_simplex (mlp->p.prob, &mlp->control_param_lp);
1394  if (0 == res)
1395  LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: %s\n",
1396  mlp_solve_to_string (res));
1397  else
1398  LOG (GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem failed: %s\n",
1399  mlp_solve_to_string (res));
1400 
1401  /* Analyze problem status */
1402  res_status = glp_get_status (mlp->p.prob);
1403  switch (res_status)
1404  {
1405  case GLP_OPT: /* solution is optimal */
1407  "Solving LP problem: %s, %s\n",
1408  mlp_solve_to_string (res),
1409  mlp_status_to_string (res_status));
1410  return GNUNET_OK;
1411 
1412  default:
1414  "Solving LP problem failed: %s %s\n",
1415  mlp_solve_to_string (res),
1416  mlp_status_to_string (res_status));
1417  return GNUNET_SYSERR;
1418  }
1419 }
glp_prob * prob
GLPK (MLP) problem object.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static const char * mlp_solve_to_string(int retcode)
Translate glpk solver error codes to text.
struct MLP_Problem p
Encapsulation for the MLP problem.
static const char * mlp_status_to_string(int retcode)
Translate glpk status error codes to text.
static int res
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
glp_smcp control_param_lp
GLPK LP control parameter.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_propagate_results()

static int mlp_propagate_results ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Propagates the results when MLP problem was solved.

Parameters
clsthe MLP handle
keythe peer identity
valuethe address
Returns
GNUNET_OK to continue

Definition at line 1431 of file plugin_ats_mlp.c.

References ATS_Address::active, address, ATS_Address::assigned_bw_in, ATS_Address::assigned_bw_out, MLP_information::b_in, MLP_information::b_out, GNUNET_ATS_PluginEnvironment::bandwidth_changed_cb, MLP_information::c_b, MLP_information::c_n, GNUNET_ATS_PluginEnvironment::cls, GAS_MLP_Handle::env, GAS_MLP_Handle::exclude_peer, GLP_NO, GLP_YES, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_memcmp, GNUNET_NO, GNUNET_OK, GNUNET_YES, LOG, MLP_NaN, MLP_information::n, GAS_MLP_Handle::p, ATS_Address::peer, MLP_Problem::prob, GAS_MLP_Handle::requested_peers, ATS_Address::solver_information, and value.

Referenced by GAS_mlp_solve_problem().

1434 {
1435  struct GAS_MLP_Handle *mlp = cls;
1436  struct ATS_Address *address;
1437  struct MLP_information *mlpi;
1438  double mlp_bw_in = MLP_NaN;
1439  double mlp_bw_out = MLP_NaN;
1440  double mlp_use = MLP_NaN;
1441 
1442  /* Check if we have to add this peer due to a pending request */
1444  key))
1445  {
1446  return GNUNET_OK;
1447  }
1448  address = value;
1449  GNUNET_assert (address->solver_information != NULL);
1450  mlpi = address->solver_information;
1451 
1452  mlp_bw_in = glp_mip_col_val (mlp->p.prob, mlpi->c_b);/* FIXME */
1453  if (mlp_bw_in > (double) UINT32_MAX)
1454  {
1456  "Overflow in assigned bandwidth, reducing ...\n");
1457  mlp_bw_in = (double) UINT32_MAX;
1458  }
1459  mlp_bw_out = glp_mip_col_val (mlp->p.prob, mlpi->c_b);
1460  if (mlp_bw_out > (double) UINT32_MAX)
1461  {
1463  "Overflow in assigned bandwidth, reducing ...\n");
1464  mlp_bw_out = (double) UINT32_MAX;
1465  }
1466  mlp_use = glp_mip_col_val (mlp->p.prob, mlpi->c_n);
1467 
1468  /*
1469  * Debug: solution
1470  * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u session %u, mlp use %.3f\n",
1471  * GNUNET_i2s(&address->peer), address->plugin,
1472  * address->addr_len, address->session_id);
1473  */
1474 
1475  if (GLP_YES == mlp_use)
1476  {
1477  /* This address was selected by the solver to be used */
1478  mlpi->n = GNUNET_YES;
1479  if (GNUNET_NO == address->active)
1480  {
1481  /* Address was not used before, enabling address */
1482  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n",
1483  (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out);
1484  address->active = GNUNET_YES;
1485  address->assigned_bw_in = mlp_bw_in;
1486  mlpi->b_in = mlp_bw_in;
1487  address->assigned_bw_out = mlp_bw_out;
1488  mlpi->b_out = mlp_bw_out;
1489  if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer,
1490  mlp->exclude_peer)))
1491  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
1492  return GNUNET_OK;
1493  }
1494  else if (GNUNET_YES == address->active)
1495  {
1496  /* Address was used before, check for bandwidth change */
1497  if ((mlp_bw_out != address->assigned_bw_out) ||
1498  (mlp_bw_in != address->assigned_bw_in))
1499  {
1500  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n",
1501  (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out);
1502  address->assigned_bw_in = mlp_bw_in;
1503  mlpi->b_in = mlp_bw_in;
1504  address->assigned_bw_out = mlp_bw_out;
1505  mlpi->b_out = mlp_bw_out;
1506  if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer,
1507  mlp->
1508  exclude_peer)))
1509  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
1510  return GNUNET_OK;
1511  }
1512  }
1513  else
1514  GNUNET_break (0);
1515  }
1516  else if (GLP_NO == mlp_use)
1517  {
1518  /* This address was selected by the solver to be not used */
1519  mlpi->n = GNUNET_NO;
1520  if (GNUNET_NO == address->active)
1521  {
1522  /* Address was not used before, nothing to do */
1523  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n",
1524  (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out);
1525  return GNUNET_OK;
1526  }
1527  else if (GNUNET_YES == address->active)
1528  {
1529  /* Address was used before, disabling address */
1530  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n",
1531  (1 == mlp_use) ? "[x]" : "[ ]", mlp_bw_out);
1532  address->active = GNUNET_NO;
1533  /* Set bandwidth to 0 */
1534  address->assigned_bw_in = 0;
1535  mlpi->b_in = 0;
1536  address->assigned_bw_out = 0;
1537  mlpi->b_out = 0;
1538  return GNUNET_OK;
1539  }
1540  else
1541  GNUNET_break (0);
1542  }
1543  else
1544  GNUNET_break (0);
1545 
1546  return GNUNET_OK;
1547 }
uint32_t b_in
Bandwidth assigned inbound.
glp_prob * prob
GLPK (MLP) problem object.
signed int c_n
address usage column
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
int active
Is this the active address for this peer?
struct GNUNET_PeerIdentity peer
Peer ID this address is for.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint32_t b_out
Bandwidth assigned outbound.
struct MLP_Problem p
Encapsulation for the MLP problem.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
Address specific MLP information.
uint32_t assigned_bw_in
Inbound bandwidth assigned by solver.
static char * value
Value of the record to add/remove.
#define MLP_NaN
struct GNUNET_ATS_PluginEnvironment * env
int n
Address selected.
Address with additional information.
void * solver_information
Solver-specific information for this address.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
MLP Handle.
#define GLP_NO
uint32_t assigned_bw_out
Outbound bandwidth assigned by solver.
#define GLP_YES
signed int c_b
bandwidth column index
void * cls
Closure to pass to all callbacks in this struct.
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
static char * address
GNS address for this phone.
const struct GNUNET_PeerIdentity * exclude_peer
Exclude peer from next result propagation.
GAS_bandwidth_changed_cb bandwidth_changed_cb
ATS addresses callback to be notified about bandwidth assignment changes.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify()

static void notify ( struct GAS_MLP_Handle mlp,
enum GAS_Solver_Operation  op,
enum GAS_Solver_Status  stat,
enum GAS_Solver_Additional_Information  add 
)
static

Definition at line 1551 of file plugin_ats_mlp.c.

References GNUNET_ATS_PluginEnvironment::cls, GAS_MLP_Handle::env, and GNUNET_ATS_PluginEnvironment::info_cb.

Referenced by GAS_mlp_solve_problem().

1555 {
1556  mlp->env->info_cb (mlp->env->cls,
1557  op,
1558  stat,
1559  add);
1560 }
struct GNUNET_ATS_PluginEnvironment * env
static int add
Desired action is to add a record.
GAS_solver_information_callback info_cb
Callback for solver to call with status information, can be NULL.
void * cls
Closure to pass to all callbacks in this struct.
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
Here is the caller graph for this function:

◆ mlp_branch_and_cut_cb()

static void mlp_branch_and_cut_cb ( glp_tree *  tree,
void *  info 
)
static

Definition at line 1564 of file plugin_ats_mlp.c.

References GNUNET_ERROR_TYPE_INFO, LOG, MLP_Variables::lp_mip_gap, MLP_Solution::lp_mlp_gap, MLP_Solution::lp_objective_value, MLP_Variables::mip_gap, MLP_Solution::mlp_gap, GAS_MLP_Handle::p, MLP_Problem::prob, GAS_MLP_Handle::ps, and GAS_MLP_Handle::pv.

Referenced by libgnunet_plugin_ats_mlp_init().

1565 {
1566  struct GAS_MLP_Handle *mlp = info;
1567  double mlp_obj = 0;
1568 
1569  switch (glp_ios_reason (tree))
1570  {
1571  case GLP_ISELECT:
1572  /* Do nothing here */
1573  break;
1574 
1575  case GLP_IPREPRO:
1576  /* Do nothing here */
1577  break;
1578 
1579  case GLP_IROWGEN:
1580  /* Do nothing here */
1581  break;
1582 
1583  case GLP_IHEUR:
1584  /* Do nothing here */
1585  break;
1586 
1587  case GLP_ICUTGEN:
1588  /* Do nothing here */
1589  break;
1590 
1591  case GLP_IBRANCH:
1592  /* Do nothing here */
1593  break;
1594 
1595  case GLP_IBINGO:
1596  /* A better solution was found */
1597  mlp->ps.mlp_gap = glp_ios_mip_gap (tree);
1598  mlp_obj = glp_mip_obj_val (mlp->p.prob);
1599  mlp->ps.lp_mlp_gap = (abs (mlp_obj - mlp->ps.lp_objective_value)) / (abs (
1600  mlp_obj)
1601  +
1602  DBL_EPSILON);
1603 
1605  "Found better integer solution, current gaps: %.3f <= %.3f, %.3f <= %.3f\n",
1606  mlp->ps.mlp_gap, mlp->pv.mip_gap,
1607  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1608 
1609  if (mlp->ps.mlp_gap <= mlp->pv.mip_gap)
1610  {
1612  "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n",
1613  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1614  glp_ios_terminate (tree);
1615  }
1616 
1617  if (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap)
1618  {
1620  "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n",
1621  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1622  glp_ios_terminate (tree);
1623  }
1624 
1625  break;
1626 
1627  default:
1628  break;
1629  }
1630  // GNUNET_break (0);
1631 }
glp_prob * prob
GLPK (MLP) problem object.
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
struct MLP_Problem p
Encapsulation for the MLP problem.
struct MLP_Solution ps
Encapsulation for the MLP solution.
double lp_objective_value
MLP Handle.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the caller graph for this function:

◆ GAS_mlp_solve_problem()

static int GAS_mlp_solve_problem ( void *  solver)
static

Solves the MLP problem.

Parameters
solverthe MLP Handle
Returns
GNUNET_OK if could be solved, GNUNET_SYSERR on failure

Definition at line 1641 of file plugin_ats_mlp.c.

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_ATS_PluginEnvironment::addresses, GAS_MLP_Handle::control_param_lp, GAS_MLP_Handle::control_param_mlp, GAS_MLP_Handle::env, filename, GAS_INFO_FULL, GAS_INFO_NONE, GAS_INFO_UPDATED, GAS_OP_SOLVE_MLP_LP_START, GAS_OP_SOLVE_MLP_LP_STOP, GAS_OP_SOLVE_MLP_MLP_START, GAS_OP_SOLVE_MLP_MLP_STOP, GAS_OP_SOLVE_SETUP_START, GAS_OP_SOLVE_SETUP_STOP, GAS_OP_SOLVE_START, GAS_OP_SOLVE_STOP, GAS_OP_SOLVE_UPDATE_NOTIFICATION_START, GAS_OP_SOLVE_UPDATE_NOTIFICATION_STOP, GAS_STAT_FAIL, GAS_STAT_SUCCESS, GLP_NO, GLP_YES, GNUNET_asprintf(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_CONTAINER_multipeermap_size(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_UNIT_ZERO, GNUNET_YES, LOG, MLP_Variables::lp_mip_gap, MLP_Solution::lp_mlp_gap, MLP_Solution::lp_objective_value, MLP_Solution::lp_presolv, MLP_Solution::lp_res, MLP_Variables::mip_gap, MLP_Solution::mip_presolv, MLP_Solution::mip_res, MLP_CPLEX, mlp_create_problem(), mlp_delete_problem(), MLP_Solution::mlp_gap, MLP_GLPK, MLP_MPS, MLP_Solution::mlp_objective_value, mlp_propagate_results(), mlp_solve_lp_problem(), mlp_solve_to_string(), mlp_status_to_string(), notify(), MLP_Problem::num_addresses, MLP_Problem::num_elements, MLP_Problem::num_peers, GAS_MLP_Handle::opt_dbg_intopt_presolver, GAS_MLP_Handle::opt_dump_problem_all, GAS_MLP_Handle::opt_dump_problem_on_fail, GAS_MLP_Handle::opt_dump_solution_all, GAS_MLP_Handle::opt_dump_solution_on_fail, GAS_MLP_Handle::opt_log_format, GAS_MLP_Handle::p, MLP_Solution::p_cols, MLP_Solution::p_elements, MLP_Solution::p_rows, MLP_Problem::prob, GAS_MLP_Handle::ps, GAS_MLP_Handle::pv, GNUNET_TIME_Relative::rel_value_us, GAS_MLP_Handle::requested_peers, GAS_MLP_Handle::stat_bulk_lock, GAS_MLP_Handle::stat_bulk_requests, GAS_MLP_Handle::stat_mlp_prob_changed, and GAS_MLP_Handle::stat_mlp_prob_updated.

Referenced by GAS_mlp_address_add(), GAS_mlp_address_change_preference(), GAS_mlp_address_delete(), GAS_mlp_address_property_changed(), GAS_mlp_bulk_stop(), GAS_mlp_get_preferred_address(), and GAS_mlp_stop_get_preferred_address().

1642 {
1643  struct GAS_MLP_Handle *mlp = solver;
1644  char *filename;
1645  int res_lp = 0;
1646  int mip_res = 0;
1647  int mip_status = 0;
1648 
1649  struct GNUNET_TIME_Absolute start_total;
1650  struct GNUNET_TIME_Absolute start_cur_op;
1651  struct GNUNET_TIME_Relative dur_total;
1652  struct GNUNET_TIME_Relative dur_setup;
1653  struct GNUNET_TIME_Relative dur_lp;
1654  struct GNUNET_TIME_Relative dur_mlp;
1655 
1656  GNUNET_assert (NULL != solver);
1657  dur_lp = GNUNET_TIME_UNIT_ZERO;
1658 
1659  if (GNUNET_YES == mlp->stat_bulk_lock)
1660  {
1661  mlp->stat_bulk_requests++;
1662  return GNUNET_NO;
1663  }
1667  start_total = GNUNET_TIME_absolute_get ();
1668 
1670  {
1672  return GNUNET_OK; /* No pending requests */
1673  }
1675  {
1677  return GNUNET_OK; /* No addresses available */
1678  }
1679 
1680  if ((GNUNET_NO == mlp->stat_mlp_prob_changed)
1681  && (GNUNET_NO == mlp->stat_mlp_prob_updated))
1682  {
1683  LOG (GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
1685  return GNUNET_OK;
1686  }
1687  if (GNUNET_YES == mlp->stat_mlp_prob_changed)
1688  {
1689  LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
1691  mlp_delete_problem (mlp);
1692  if (GNUNET_SYSERR == mlp_create_problem (mlp))
1693  {
1695  return GNUNET_SYSERR;
1696  }
1698  if (GNUNET_NO == mlp->opt_dbg_intopt_presolver)
1699  {
1700  mlp->control_param_lp.presolve = GLP_YES; /* LP presolver, we need lp solution */
1701  mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP solution */
1702  }
1703  else
1704  {
1705  mlp->control_param_lp.presolve = GNUNET_NO; /* LP presolver, we need lp solution */
1706  mlp->control_param_mlp.presolve = GLP_YES; /* No presolver, we have LP solution */
1707  dur_lp = GNUNET_TIME_UNIT_ZERO;
1708  }
1709  }
1710  else
1711  {
1712  LOG (GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
1713  }
1714 
1715  /* Reset solution info */
1716  mlp->ps.lp_objective_value = 0.0;
1717  mlp->ps.mlp_gap = 1.0;
1718  mlp->ps.mlp_objective_value = 0.0;
1719  mlp->ps.lp_mlp_gap = 0.0;
1720 
1721  dur_setup = GNUNET_TIME_absolute_get_duration (start_total);
1722 
1723  /* Run LP solver */
1724  if (GNUNET_NO == mlp->opt_dbg_intopt_presolver)
1725  {
1730  "Running LP solver %s\n",
1731  (GLP_YES == mlp->control_param_lp.presolve) ? "with presolver" :
1732  "without presolver");
1733  start_cur_op = GNUNET_TIME_absolute_get ();
1734 
1735  /* Solve LP */
1736  /* Only for debugging:
1737  * Always use LP presolver:
1738  * mlp->control_param_lp.presolve = GLP_YES; */
1739  res_lp = mlp_solve_lp_problem (mlp);
1740  if (GNUNET_OK == res_lp)
1741  {
1742  mlp->ps.lp_objective_value = glp_get_obj_val (mlp->p.prob);
1744  "LP solution was: %.3f\n",
1745  mlp->ps.lp_objective_value);
1746  }
1747 
1748  dur_lp = GNUNET_TIME_absolute_get_duration (start_cur_op);
1750  (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1753  }
1754 
1756  res_lp = GNUNET_OK;
1757 
1758  /* Run MLP solver */
1759  if ((GNUNET_OK == res_lp) || (GNUNET_YES == mlp->opt_dbg_intopt_presolver))
1760  {
1761  LOG (GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
1765  start_cur_op = GNUNET_TIME_absolute_get ();
1766 
1767  /* Solve MIP */
1768 
1769  /* Only for debugging, always use LP presolver */
1771  mlp->control_param_mlp.presolve = GNUNET_YES;
1772 
1773  mip_res = glp_intopt (mlp->p.prob, &mlp->control_param_mlp);
1774  switch (mip_res)
1775  {
1776  case 0:
1777  /* Successful */
1779  "Solving MLP problem: %s\n",
1780  mlp_solve_to_string (mip_res));
1781  break;
1782 
1783  case GLP_ETMLIM: /* Time limit reached */
1784  case GLP_EMIPGAP: /* MIP gap tolerance limit reached */
1785  case GLP_ESTOP: /* Solver was instructed to stop*/
1786  /* Semi-successful */
1788  "Solving MLP problem solution was interupted: %s\n",
1789  mlp_solve_to_string (mip_res));
1790  break;
1791 
1792  case GLP_EBOUND:
1793  case GLP_EROOT:
1794  case GLP_ENOPFS:
1795  case GLP_ENODFS:
1796  case GLP_EFAIL:
1797  default:
1798  /* Fail */
1800  "Solving MLP problem failed: %s\n",
1801  mlp_solve_to_string (mip_res));
1802  break;
1803  }
1804 
1805  /* Analyze problem status */
1806  mip_status = glp_mip_status (mlp->p.prob);
1807  switch (mip_status)
1808  {
1809  case GLP_OPT: /* solution is optimal */
1811  "Solution of MLP problem is optimal: %s, %s\n",
1812  mlp_solve_to_string (mip_res),
1813  mlp_status_to_string (mip_status));
1814  mip_res = GNUNET_OK;
1815  break;
1816 
1817  case GLP_FEAS: /* solution is feasible but not proven optimal */
1818 
1819  if ((mlp->ps.mlp_gap <= mlp->pv.mip_gap) ||
1820  (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap))
1821  {
1823  "Solution of MLP problem is feasible and solution within gap constraints: %s, %s\n",
1824  mlp_solve_to_string (mip_res),
1825  mlp_status_to_string (mip_status));
1826  mip_res = GNUNET_OK;
1827  }
1828  else
1829  {
1831  "Solution of MLP problem is feasible but solution not within gap constraints: %s, %s\n",
1832  mlp_solve_to_string (mip_res),
1833  mlp_status_to_string (mip_status));
1834  mip_res = GNUNET_SYSERR;
1835  }
1836  break;
1837 
1838  case GLP_UNDEF: /* Solution undefined */
1839  case GLP_NOFEAS: /* No feasible solution */
1840  default:
1842  "Solving MLP problem failed: %s %s\n",
1843  mlp_solve_to_string (mip_res),
1844  mlp_status_to_string (mip_status));
1845  mip_res = GNUNET_SYSERR;
1846  break;
1847  }
1848 
1849  dur_mlp = GNUNET_TIME_absolute_get_duration (start_cur_op);
1850  dur_total = GNUNET_TIME_absolute_get_duration (start_total);
1851 
1853  (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1856  }
1857  else
1858  {
1859  /* Do not execute mip solver since lp solution is invalid */
1860  dur_mlp = GNUNET_TIME_UNIT_ZERO;
1861  dur_total = GNUNET_TIME_absolute_get_duration (start_total);
1862 
1866  mip_res = GNUNET_SYSERR;
1867  }
1868 
1869  /* Notify about end */
1870  notify (mlp, GAS_OP_SOLVE_STOP,
1871  ((GNUNET_OK == mip_res) && (GNUNET_OK == mip_res)) ?
1875 
1877  "Execution time for %s solve: (total/setup/lp/mlp) : %llu %llu %llu %llu\n",
1878  (GNUNET_YES == mlp->stat_mlp_prob_changed) ? "full" : "updated",
1879  (unsigned long long) dur_total.rel_value_us,
1880  (unsigned long long) dur_setup.rel_value_us,
1881  (unsigned long long) dur_lp.rel_value_us,
1882  (unsigned long long) dur_mlp.rel_value_us);
1883 
1884  /* Save stats */
1885  mlp->ps.lp_res = res_lp;
1886  mlp->ps.mip_res = mip_res;
1887  mlp->ps.lp_presolv = mlp->control_param_lp.presolve;
1888  mlp->ps.mip_presolv = mlp->control_param_mlp.presolve;
1889  mlp->ps.p_cols = glp_get_num_cols (mlp->p.prob);
1890  mlp->ps.p_rows = glp_get_num_rows (mlp->p.prob);
1891  mlp->ps.p_elements = mlp->p.num_elements;
1892 
1893  /* Propagate result*/
1895  (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS :
1896  GAS_STAT_FAIL,
1897  GAS_INFO_NONE);
1898  if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res))
1899  {
1901  &mlp_propagate_results, mlp);
1902  }
1904  (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS :
1905  GAS_STAT_FAIL,
1906  GAS_INFO_NONE);
1907 
1909  if ((GNUNET_YES == mlp->opt_dump_problem_all) ||
1910  (mlp->opt_dump_problem_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK !=
1911  mip_res))))
1912  {
1913  /* Write problem to disk */
1914  switch (mlp->opt_log_format)
1915  {
1916  case MLP_CPLEX:
1917  GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.cplex",
1918  mlp->p.num_peers,
1919  mlp->p.num_addresses, time.abs_value_us);
1920  glp_write_lp (mlp->p.prob, NULL, filename);
1921  break;
1922 
1923  case MLP_GLPK:
1924  GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.glpk",
1925  mlp->p.num_peers,
1926  mlp->p.num_addresses, time.abs_value_us);
1927  glp_write_prob (mlp->p.prob, 0, filename);
1928  break;
1929 
1930  case MLP_MPS:
1931  GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers,
1932  mlp->p.num_addresses, time.abs_value_us);
1933  glp_write_mps (mlp->p.prob, GLP_MPS_FILE, NULL, filename);
1934  break;
1935 
1936  default:
1937  break;
1938  }
1939  LOG (GNUNET_ERROR_TYPE_ERROR, "Dumped problem to file: `%s' \n", filename);
1940  GNUNET_free (filename);
1941  }
1942  if ((mlp->opt_dump_solution_all) ||
1943  (mlp->opt_dump_solution_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK !=
1944  mip_res))))
1945  {
1946  /* Write solution to disk */
1947  GNUNET_asprintf (&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers,
1948  mlp->p.num_addresses, time.abs_value_us);
1949  glp_print_mip (mlp->p.prob, filename);
1950  LOG (GNUNET_ERROR_TYPE_ERROR, "Dumped solution to file: `%s' \n", filename);
1951  GNUNET_free (filename);
1952  }
1953 
1954  /* Reset change and update marker */
1955  mlp->control_param_lp.presolve = GLP_NO;
1958 
1959  if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res))
1960  return GNUNET_OK;
1961  else
1962  return GNUNET_SYSERR;
1963 }
int opt_dump_solution_on_fail
Write MILP problem solutions to a file when solver fails.
Solving of the LP problem was started MLP solver only.
After the problem was finished, start notifications about changes to addresses.
glp_prob * prob
GLPK (MLP) problem object.
enum MLP_Output_Format opt_log_format
Output format.
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
The setup of the problem as a preparation to solve it was started.
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
static int mlp_create_problem(struct GAS_MLP_Handle *mlp)
Create the MLP problem.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
No more specific information.
unsigned int num_elements
int stat_bulk_requests
Number of changes while solver was locked.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
A full solution process is performed Quite specific to the MLP solver.
unsigned int num_peers
Solving of the LP problem is done MLP solver only.
static const char * mlp_solve_to_string(int retcode)
Translate glpk solver error codes to text.
struct MLP_Problem p
Encapsulation for the MLP problem.
int stat_mlp_prob_changed
Has the problem size changed since last solution.
uint64_t abs_value_us
The actual value.
static const char * mlp_status_to_string(int retcode)
Translate glpk status error codes to text.
struct MLP_Solution ps
Encapsulation for the MLP solution.
int opt_dump_problem_on_fail
Write MILP problems to a MPS file when solver fails.
Solving of the MLP problem is done MLP solver only.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
int stat_bulk_lock
Bulk lock.
A solution iteration has been started.
double lp_objective_value
int opt_dump_problem_all
Write all MILP problems to a MPS file.
int opt_dbg_intopt_presolver
use the intopt presolver instead of simplex
Solving of the MLP problem was started MLP solver only.
static char * filename
struct GNUNET_ATS_PluginEnvironment * env
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
double mlp_objective_value
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
A solution iteration has been finished.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
MLP Handle.
#define GLP_NO
#define GLP_YES
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:373
static void mlp_delete_problem(struct GAS_MLP_Handle *mlp)
Delete the MLP problem and free the constrain matrix.
The setup of the problem as a preparation to solve is finished.
static int mlp_solve_lp_problem(struct GAS_MLP_Handle *mlp)
Solves the LP problem.
An existing solution was reused Quite specific to the MLP solver.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
unsigned int num_addresses
int stat_mlp_prob_updated
Was the problem updated since last solution.
int opt_dump_solution_all
Write all MILP problem solutions to a file.
static void notify(struct GAS_MLP_Handle *mlp, enum GAS_Solver_Operation op, enum GAS_Solver_Status stat, enum GAS_Solver_Additional_Information add)
struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap containing all addresses available.
static int mlp_propagate_results(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Propagates the results when MLP problem was solved.
glp_iocp control_param_mlp
GLPK LP control parameter.
glp_smcp control_param_lp
GLPK LP control parameter.
After the problem was finished, notifications about changes to addresses are done.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_address_add()

static void GAS_mlp_address_add ( void *  solver,
struct ATS_Address address,
uint32_t  network 
)
static

Add a single address to the solve.

Parameters
solverthe solver Handle
addressthe address to add
networknetwork type of this address

Definition at line 1973 of file plugin_ats_mlp.c.

References _, GAS_mlp_solve_problem(), GNUNET_break, GNUNET_CONTAINER_multipeermap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_i2s(), GNUNET_new, GNUNET_NT_COUNT, GNUNET_YES, LOG, GAS_MLP_Handle::opt_mlp_auto_solve, ATS_Address::peer, GAS_MLP_Handle::requested_peers, ATS_Address::solver_information, and GAS_MLP_Handle::stat_mlp_prob_changed.

Referenced by libgnunet_plugin_ats_mlp_init().

1976 {
1977  struct GAS_MLP_Handle *mlp = solver;
1978 
1979  if (GNUNET_NT_COUNT <= network)
1980  {
1981  GNUNET_break (0);
1982  return;
1983  }
1984 
1985  if (NULL == address->solver_information)
1986  {
1987  address->solver_information = GNUNET_new (struct MLP_information);
1988  }
1989  else
1991  _ ("Adding address for peer `%s' multiple times\n"),
1992  GNUNET_i2s (&address->peer));
1993 
1994  /* Is this peer included in the problem? */
1995  if (NULL ==
1997  &address->peer))
1998  {
1999  /* FIXME: should this be an error? */
2001  "Adding address for peer `%s' without address request\n",
2002  GNUNET_i2s (&address->peer));
2003  return;
2004  }
2005 
2007  "Adding address for peer `%s' with address request \n",
2008  GNUNET_i2s (&address->peer));
2009  /* Problem size changed: new address for peer with pending request */
2011  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2012  GAS_mlp_solve_problem (solver);
2013 }
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
struct GNUNET_PeerIdentity peer
Peer ID this address is for.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int stat_mlp_prob_changed
Has the problem size changed since last solution.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Address specific MLP information.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
void * solver_information
Solver-specific information for this address.
MLP Handle.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
#define GNUNET_YES
Definition: gnunet_common.h:77
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_NT_COUNT
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_address_property_changed()

static void GAS_mlp_address_property_changed ( void *  solver,
struct ATS_Address address 
)
static

Transport properties for this address have changed.

Parameters
solversolver handle
addressthe address

Definition at line 2023 of file plugin_ats_mlp.c.

References _, MLP_information::c_b, GAS_mlp_solve_problem(), GNUNET_break, GNUNET_CONTAINER_multipeermap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_YES, LOG, mlp_create_problem_update_value(), GAS_NormalizationInfo::norm, ATS_Address::norm_delay, ATS_Address::norm_distance, GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_mlp_auto_solve, GAS_MLP_Handle::p, ATS_Address::peer, MLP_Problem::prob, MLP_Problem::r_q, GAS_MLP_Handle::requested_peers, RQ_QUALITY_METRIC_DELAY, RQ_QUALITY_METRIC_DISTANCE, ATS_Address::solver_information, and GAS_MLP_Handle::stat_mlp_prob_updated.

Referenced by libgnunet_plugin_ats_mlp_init().

2025 {
2026  struct MLP_information *mlpi = address->solver_information;
2027  struct GAS_MLP_Handle *mlp = solver;
2028 
2029  if (NULL == mlp->p.prob)
2030  return; /* There is no MLP problem to update yet */
2031 
2032  if (NULL == mlpi)
2033  {
2035  _ ("Updating address property for peer `%s' %p not added before\n"),
2036  GNUNET_i2s (&address->peer),
2037  address);
2038  GNUNET_break (0);
2039  return;
2040  }
2041  if (NULL ==
2043  &address->peer))
2044  {
2045  /* Peer is not requested, so no need to update problem */
2046  return;
2047  }
2049  "Updating properties for peer `%s'\n",
2050  GNUNET_i2s (&address->peer));
2051 
2053  return;
2054 
2055  /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */
2056  if ((GNUNET_YES ==
2059  mlpi->c_b,
2060  address->norm_delay.norm,
2061  __LINE__)) ||
2062  (GNUNET_YES ==
2065  mlpi->c_b,
2066  address->norm_distance.norm,
2067  __LINE__)))
2068  {
2070  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2071  GAS_mlp_solve_problem (solver);
2072  }
2073 }
int r_q[RQ_QUALITY_METRIC_COUNT]
glp_prob * prob
GLPK (MLP) problem object.
int opt_dbg_feasibility_only
solve feasibility only
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
static int mlp_create_problem_update_value(struct MLP_Problem *p, int row, int col, double val, int line)
Updates an existing value in the matrix.
struct GNUNET_PeerIdentity peer
Peer ID this address is for.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
struct MLP_Problem p
Encapsulation for the MLP problem.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Address specific MLP information.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
void * solver_information
Solver-specific information for this address.
MLP Handle.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
signed int c_b
bandwidth column index
struct GAS_NormalizationInfo norm_delay
Normalized delay information for this address.
#define GNUNET_YES
Definition: gnunet_common.h:77
int stat_mlp_prob_updated
Was the problem updated since last solution.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
double norm
Normalized values from queue to a range of values [1.0...2.0].
struct GAS_NormalizationInfo norm_distance
Normalized distance information for this address.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mlp_get_preferred_address_it()

static int mlp_get_preferred_address_it ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Find the active address in the set of addresses of a peer.

Parameters
clsdestination
keypeer id
valueaddress
Returns
GNUNET_OK

Definition at line 2084 of file plugin_ats_mlp.c.

References ATS_Address::addr, ATS_Address::assigned_bw_in, MLP_information::b_in, MLP_information::b_out, GNUNET_NO, GNUNET_YES, MLP_information::n, ATS_Address::solver_information, and value.

Referenced by GAS_mlp_address_delete(), and GAS_mlp_get_preferred_address().

2087 {
2088  static int counter = 0;
2089  struct ATS_Address **aa = cls;
2090  struct ATS_Address *addr = value;
2091  struct MLP_information *mlpi = addr->solver_information;
2092 
2093  if (mlpi == NULL)
2094  return GNUNET_YES;
2095 
2096  /*
2097  * Debug output
2098  * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2099  * "MLP [%u] Peer `%s' %s length %u session %u active %s mlp active %s\n",
2100  * counter, GNUNET_i2s (&addr->peer), addr->plugin, addr->addr_len, addr->session_id,
2101  * (GNUNET_YES == addr->active) ? "active" : "inactive",
2102  * (GNUNET_YES == mlpi->n) ? "active" : "inactive");
2103  */
2104 
2105  if (GNUNET_YES == mlpi->n)
2106  {
2107  (*aa) = addr;
2108  (*aa)->assigned_bw_in = mlpi->b_in;
2109  (*aa)->assigned_bw_out = mlpi->b_out;
2110  return GNUNET_NO;
2111  }
2112  counter++;
2113  return GNUNET_YES;
2114 }
uint32_t b_in
Bandwidth assigned inbound.
const void * addr
Address (in plugin-specific binary format).
#define GNUNET_NO
Definition: gnunet_common.h:78
uint32_t b_out
Bandwidth assigned outbound.
Address specific MLP information.
uint32_t assigned_bw_in
Inbound bandwidth assigned by solver.
static char * value
Value of the record to add/remove.
int n
Address selected.
Address with additional information.
void * solver_information
Solver-specific information for this address.
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ get_peer_pref_value()

static double get_peer_pref_value ( struct GAS_MLP_Handle mlp,
const struct GNUNET_PeerIdentity peer 
)
static

Definition at line 2118 of file plugin_ats_mlp.c.

References GNUNET_ATS_PluginEnvironment::cls, GAS_MLP_Handle::env, GNUNET_ATS_PluginEnvironment::get_preferences, GNUNET_ATS_PREFERENCE_END, GNUNET_ERROR_TYPE_DEBUG, GNUNET_i2s(), LOG, and res.

Referenced by GAS_mlp_address_change_preference(), and GAS_mlp_get_preferred_address().

2120 {
2121  double res;
2122  const double *preferences;
2123  int c;
2124 
2125  preferences = mlp->env->get_preferences (mlp->env->cls, peer);
2126  res = 0.0;
2127  for (c = 0; c < GNUNET_ATS_PREFERENCE_END; c++)
2128  {
2129  /* fprintf (stderr, "VALUE[%u] %s %.3f \n",
2130  * c, GNUNET_i2s (&cur->addr->peer), t[c]); */
2131  res += preferences[c];
2132  }
2133 
2135  res += 1.0;
2136 
2138  "Peer preference for peer `%s' == %.2f\n",
2139  GNUNET_i2s (peer), res);
2140 
2141  return res;
2142 }
GAS_get_preferences get_preferences
ATS addresses function to obtain preference values.
End of preference list.
struct GNUNET_ATS_PluginEnvironment * env
static int res
void * cls
Closure to pass to all callbacks in this struct.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_get_preferred_address()

static void GAS_mlp_get_preferred_address ( void *  solver,
const struct GNUNET_PeerIdentity peer 
)
static

Get the preferred address for a specific peer.

Parameters
solverthe MLP Handle
peerthe peer

Definition at line 2152 of file plugin_ats_mlp.c.

References GNUNET_ATS_PluginEnvironment::addresses, GNUNET_ATS_PluginEnvironment::bandwidth_changed_cb, GNUNET_ATS_PluginEnvironment::cls, GAS_MLP_Handle::env, GAS_MLP_Handle::exclude_peer, ATS_Peer::f, GAS_mlp_solve_problem(), get_peer_pref_value(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST, GNUNET_CONTAINER_multipeermap_contains(), GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_new, GNUNET_YES, ATS_Peer::id, LOG, mlp_get_preferred_address_it(), GAS_MLP_Handle::opt_mlp_auto_solve, p, peer, GAS_MLP_Handle::requested_peers, res, and GAS_MLP_Handle::stat_mlp_prob_changed.

Referenced by GAS_mlp_address_delete(), and libgnunet_plugin_ats_mlp_init().

2154 {
2155  struct GAS_MLP_Handle *mlp = solver;
2156  struct ATS_Peer *p;
2157  struct ATS_Address *res;
2158 
2160  "Getting preferred address for `%s'\n",
2161  GNUNET_i2s (peer));
2162 
2163  /* Is this peer included in the problem? */
2164  if (NULL ==
2166  peer))
2167  {
2169  "Adding peer `%s' to list of requested_peers with requests\n",
2170  GNUNET_i2s (peer));
2171 
2172  p = GNUNET_new (struct ATS_Peer);
2173  p->id = (*peer);
2174  p->f = get_peer_pref_value (mlp, peer);
2176  peer, p,
2178 
2179  /* Added new peer, we have to rebuild problem before solving */
2181 
2182  if ((GNUNET_YES == mlp->opt_mlp_auto_solve) &&
2184  mlp->env->addresses,
2185  peer)))
2186  {
2187  mlp->exclude_peer = peer;
2188  GAS_mlp_solve_problem (mlp);
2189  mlp->exclude_peer = NULL;
2190  }
2191  }
2192  /* Get prefered address */
2193  res = NULL;
2196  &res);
2197  if (NULL != res)
2198  mlp->env->bandwidth_changed_cb (mlp->env->cls,
2199  res);
2200 }
static double get_peer_pref_value(struct GAS_MLP_Handle *mlp, const struct GNUNET_PeerIdentity *peer)
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int stat_mlp_prob_changed
Has the problem size changed since last solution.
struct GNUNET_PeerIdentity id
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
, &#39; bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_...
static int mlp_get_preferred_address_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find the active address in the set of addresses of a peer.
struct GNUNET_ATS_PluginEnvironment * env
static int res
Address with additional information.
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
MLP Handle.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
void * cls
Closure to pass to all callbacks in this struct.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap containing all addresses available.
int GNUNET_CONTAINER_multipeermap_contains(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Check if the map contains any value under the given key (including values that are NULL)...
const struct GNUNET_PeerIdentity * exclude_peer
Exclude peer from next result propagation.
GAS_bandwidth_changed_cb bandwidth_changed_cb
ATS addresses callback to be notified about bandwidth assignment changes.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_address_delete()

static void GAS_mlp_address_delete ( void *  solver,
struct ATS_Address address 
)
static

Deletes a single address in the MLP problem.

The MLP problem has to be recreated and the problem has to be resolved

Parameters
solverthe MLP Handle
addressthe address to delete

Definition at line 2212 of file plugin_ats_mlp.c.

References ATS_Address::active, GNUNET_ATS_PluginEnvironment::addresses, ATS_Address::assigned_bw_in, ATS_Address::assigned_bw_out, GNUNET_ATS_PluginEnvironment::bandwidth_changed_cb, GNUNET_ATS_PluginEnvironment::cls, GAS_MLP_Handle::env, GAS_mlp_get_preferred_address(), GAS_mlp_solve_problem(), GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_i2s(), GNUNET_NO, GNUNET_YES, LOG, mlp_get_preferred_address_it(), GAS_MLP_Handle::opt_mlp_auto_solve, ATS_Address::peer, GAS_MLP_Handle::requested_peers, res, ATS_Address::solver_information, and GAS_MLP_Handle::stat_mlp_prob_changed.

Referenced by libgnunet_plugin_ats_mlp_init().

2214 {
2215  struct GAS_MLP_Handle *mlp = solver;
2216  struct MLP_information *mlpi;
2217  struct ATS_Address *res;
2218  int was_active;
2219 
2220  mlpi = address->solver_information;
2221  if (NULL != mlpi)
2222  {
2223  /* Remove full address */
2224  GNUNET_free (mlpi);
2225  address->solver_information = NULL;
2226  }
2227  was_active = address->active;
2228  address->active = GNUNET_NO;
2229  address->assigned_bw_in = 0;
2230  address->assigned_bw_out = 0;
2231 
2232  /* Is this peer included in the problem? */
2233  if (NULL ==
2235  &address->peer))
2236  {
2238  "Deleting address for peer `%s' without address request \n",
2239  GNUNET_i2s (&address->peer));
2240  return;
2241  }
2243  "Deleting address for peer `%s' with address request \n",
2244  GNUNET_i2s (&address->peer));
2245 
2246  /* Problem size changed: new address for peer with pending request */
2248  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2249  {
2250  GAS_mlp_solve_problem (solver);
2251  }
2252  if (GNUNET_YES == was_active)
2253  {
2254  GAS_mlp_get_preferred_address (solver, &address->peer);
2255  res = NULL;
2257  &address->peer,
2259  &res);
2260  if (NULL == res)
2261  {
2262  /* No alternative address, disconnecting peer */
2263  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
2264  }
2265  }
2266 }
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
int active
Is this the active address for this peer?
struct GNUNET_PeerIdentity peer
Peer ID this address is for.
static void GAS_mlp_get_preferred_address(void *solver, const struct GNUNET_PeerIdentity *peer)
Get the preferred address for a specific peer.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
#define GNUNET_NO
Definition: gnunet_common.h:78
int stat_mlp_prob_changed
Has the problem size changed since last solution.
Address specific MLP information.
uint32_t assigned_bw_in
Inbound bandwidth assigned by solver.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
static int mlp_get_preferred_address_it(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Find the active address in the set of addresses of a peer.
struct GNUNET_ATS_PluginEnvironment * env
static int res
Address with additional information.
void * solver_information
Solver-specific information for this address.
MLP Handle.
uint32_t assigned_bw_out
Outbound bandwidth assigned by solver.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
void * cls
Closure to pass to all callbacks in this struct.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_CONTAINER_MultiPeerMap * addresses
Hashmap containing all addresses available.
GAS_bandwidth_changed_cb bandwidth_changed_cb
ATS addresses callback to be notified about bandwidth assignment changes.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_bulk_start()

static void GAS_mlp_bulk_start ( void *  solver)
static

Start a bulk operation.

Parameters
solverthe solver

Definition at line 2275 of file plugin_ats_mlp.c.

References GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, LOG, and GAS_MLP_Handle::stat_bulk_lock.

Referenced by libgnunet_plugin_ats_mlp_init().

2276 {
2277  struct GAS_MLP_Handle *s = solver;
2278 
2280  "Locking solver for bulk operation ...\n");
2281  GNUNET_assert (NULL != solver);
2282  s->stat_bulk_lock++;
2283 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int stat_bulk_lock
Bulk lock.
MLP Handle.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the caller graph for this function:

◆ GAS_mlp_bulk_stop()

static void GAS_mlp_bulk_stop ( void *  solver)
static

Definition at line 2287 of file plugin_ats_mlp.c.

References GAS_mlp_solve_problem(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, LOG, GAS_MLP_Handle::stat_bulk_lock, and GAS_MLP_Handle::stat_bulk_requests.

Referenced by libgnunet_plugin_ats_mlp_init().

2288 {
2289  struct GAS_MLP_Handle *s = solver;
2290 
2292  "Unlocking solver from bulk operation ...\n");
2293  GNUNET_assert (NULL != solver);
2294 
2295  if (s->stat_bulk_lock < 1)
2296  {
2297  GNUNET_break (0);
2298  return;
2299  }
2300  s->stat_bulk_lock--;
2301 
2302  if (0 < s->stat_bulk_requests)
2303  {
2304  GAS_mlp_solve_problem (solver);
2305  s->stat_bulk_requests = 0;
2306  }
2307 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int stat_bulk_requests
Number of changes while solver was locked.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
int stat_bulk_lock
Bulk lock.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
MLP Handle.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_stop_get_preferred_address()

static void GAS_mlp_stop_get_preferred_address ( void *  solver,
const struct GNUNET_PeerIdentity peer 
)
static

Stop notifying about address and bandwidth changes for this peer.

Parameters
solverthe MLP handle
peerthe peer

Definition at line 2318 of file plugin_ats_mlp.c.

References GAS_mlp_solve_problem(), GNUNET_assert, GNUNET_CONTAINER_multipeermap_get(), GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_YES, GAS_MLP_Handle::opt_mlp_auto_solve, p, GAS_MLP_Handle::requested_peers, and GAS_MLP_Handle::stat_mlp_prob_changed.

Referenced by libgnunet_plugin_ats_mlp_init().

2320 {
2321  struct GAS_MLP_Handle *mlp = solver;
2322  struct ATS_Peer *p = NULL;
2323 
2324  GNUNET_assert (NULL != solver);
2325  GNUNET_assert (NULL != peer);
2326  if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
2327  peer)))
2328  {
2331  peer, p));
2332  GNUNET_free (p);
2333 
2335  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2336  {
2337  GAS_mlp_solve_problem (solver);
2338  }
2339  }
2340 }
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
int stat_mlp_prob_changed
Has the problem size changed since last solution.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
MLP Handle.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
#define GNUNET_YES
Definition: gnunet_common.h:77
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_address_change_preference()

static void GAS_mlp_address_change_preference ( void *  solver,
const struct GNUNET_PeerIdentity peer,
enum GNUNET_ATS_PreferenceKind  kind,
double  pref_rel 
)
static

Changes the preferences for a peer in the MLP problem.

Parameters
solverthe MLP Handle
peerthe peer
kindthe kind to change the preference
pref_relthe relative score

Definition at line 2352 of file plugin_ats_mlp.c.

References MLP_Problem::c_r, GAS_MLP_Handle::env, ATS_Peer::f, GAS_mlp_solve_problem(), get_peer_pref_value(), GNUNET_CONTAINER_multipeermap_get(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_NO, GNUNET_STATISTICS_update(), GNUNET_YES, LOG, mlp_create_problem_update_value(), GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_mlp_auto_solve, p, GAS_MLP_Handle::p, ATS_Peer::r_c9, GAS_MLP_Handle::requested_peers, GAS_MLP_Handle::stat_mlp_prob_updated, and GNUNET_ATS_PluginEnvironment::stats.

Referenced by libgnunet_plugin_ats_mlp_init().

2356 {
2357  struct GAS_MLP_Handle *mlp = solver;
2358  struct ATS_Peer *p;
2359 
2361  "Changing preference for address for peer `%s' to %.2f\n",
2362  GNUNET_i2s (peer),
2363  pref_rel);
2364 
2366  "# LP address preference changes", 1, GNUNET_NO);
2367  /* Update the constraints with changed preferences */
2368 
2369 
2370 
2371  /* Update relativity constraint c9 */
2372  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers,
2373  peer)))
2374  {
2376  "Updating preference for unknown peer `%s'\n",
2377  GNUNET_i2s (peer));
2378  return;
2379  }
2380 
2381  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
2382  {
2383  p->f = get_peer_pref_value (mlp, peer);
2385  p->r_c9,
2386  mlp->p.c_r,
2387  -p->f,
2388  __LINE__);
2389 
2390  /* Problem size changed: new address for peer with pending request */
2392  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2393  GAS_mlp_solve_problem (solver);
2394  }
2395 }
static double get_peer_pref_value(struct GAS_MLP_Handle *mlp, const struct GNUNET_PeerIdentity *peer)
int opt_dbg_feasibility_only
solve feasibility only
struct GNUNET_STATISTICS_Handle * stats
Statistics handle to be used by the solver.
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
static int mlp_create_problem_update_value(struct MLP_Problem *p, int row, int col, double val, int line)
Updates an existing value in the matrix.
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
#define GNUNET_NO
Definition: gnunet_common.h:78
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct MLP_Problem p
Encapsulation for the MLP problem.
static int GAS_mlp_solve_problem(void *solver)
Solves the MLP problem.
unsigned int r_c9
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
struct GNUNET_ATS_PluginEnvironment * env
MLP Handle.
void * GNUNET_CONTAINER_multipeermap_get(const struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key)
Given a key find a value in the map matching the key.
#define GNUNET_YES
Definition: gnunet_common.h:77
int stat_mlp_prob_updated
Was the problem updated since last solution.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GAS_mlp_address_preference_feedback()

static void GAS_mlp_address_preference_feedback ( void *  solver,
struct GNUNET_SERVICE_Client application,
const struct GNUNET_PeerIdentity peer,
const struct GNUNET_TIME_Relative  scope,
enum GNUNET_ATS_PreferenceKind  kind,
double  score 
)
static

Get application feedback for a peer.

Parameters
solverthe solver handle
applicationthe application
peerthe peer to change the preference for
scopethe time interval for this feedback: [now - scope .. now]
kindthe kind to change the preference
scorethe score

Definition at line 2409 of file plugin_ats_mlp.c.

References GNUNET_assert.

Referenced by libgnunet_plugin_ats_mlp_init().

2415 {
2416  struct GAS_PROPORTIONAL_Handle *s = solver;
2417 
2418  GNUNET_assert (NULL != solver);
2419  GNUNET_assert (NULL != peer);
2420  GNUNET_assert (NULL != s);
2421 }
A handle for the proportional solver.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
Here is the caller graph for this function:

◆ mlp_free_peers()

static int mlp_free_peers ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Definition at line 2425 of file plugin_ats_mlp.c.

References GNUNET_assert, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_OK, GNUNET_YES, map, p, and value.

Referenced by libgnunet_plugin_ats_mlp_done().

2427 {
2428  struct GNUNET_CONTAINER_MultiPeerMap *map = cls;
2429  struct ATS_Peer *p = value;
2430 
2433  GNUNET_free (p);
2434 
2435  return GNUNET_OK;
2436 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static struct GNUNET_CONTAINER_MultiPeerMap * map
Handle to the map used to store old latency values for peers.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * value
Value of the record to add/remove.
Internal representation of the hash map.
#define GNUNET_YES
Definition: gnunet_common.h:77
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ libgnunet_plugin_ats_mlp_done()

void* libgnunet_plugin_ats_mlp_done ( void *  cls)

Shutdown the MLP problem solving component.

Parameters
clsthe solver handle
Returns
NULL

Definition at line 2446 of file plugin_ats_mlp.c.

References GNUNET_ATS_SolverFunctions::cls, GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, LOG, mlp_delete_problem(), mlp_free_peers(), GAS_MLP_Handle::requested_peers, and sf.

2447 {
2448  struct GNUNET_ATS_SolverFunctions *sf = cls;
2449  struct GAS_MLP_Handle *mlp = sf->cls;
2450 
2452  "Shutting down mlp solver\n");
2453  mlp_delete_problem (mlp);
2455  &mlp_free_peers,
2456  mlp->requested_peers);
2458  mlp->requested_peers = NULL;
2459 
2460  /* Clean up GLPK environment */
2461  glp_free_env ();
2462  GNUNET_free (mlp);
2463 
2465  "Shutdown down of mlp solver complete\n");
2466  return NULL;
2467 }
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
static int mlp_free_peers(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
void * cls
Closure to pass to all solver functions in this struct.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
MLP Handle.
static void mlp_delete_problem(struct GAS_MLP_Handle *mlp)
Delete the MLP problem and free the constrain matrix.
static struct GNUNET_ATS_SolverFunctions * sf
Solver handle.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:

◆ libgnunet_plugin_ats_mlp_init()

void* libgnunet_plugin_ats_mlp_init ( void *  cls)

Definition at line 2471 of file plugin_ats_mlp.c.

References _, MLP_Variables::b_min, MLP_Variables::BIG_M, BIG_M_VALUE, GNUNET_ATS_PluginEnvironment::cfg, GNUNET_ATS_SolverFunctions::cls, GNUNET_ATS_PluginEnvironment::cls, MLP_Variables::co_D, MLP_Variables::co_Q, MLP_Variables::co_R, MLP_Variables::co_U, env, GAS_MLP_Handle::env, GAS_mlp_address_add(), GAS_mlp_address_change_preference(), GAS_mlp_address_delete(), GAS_mlp_address_preference_feedback(), GAS_mlp_address_property_changed(), GAS_mlp_bulk_start(), GAS_mlp_bulk_stop(), GAS_mlp_get_preferred_address(), GAS_mlp_stop_get_preferred_address(), GNUNET_CONFIGURATION_get_value_float(), GNUNET_CONFIGURATION_get_value_size(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT, GNUNET_CONTAINER_multipeermap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_new, GNUNET_NO, GNUNET_NT_COUNT, GNUNET_NT_to_string(), GNUNET_OK, GNUNET_STRINGS_utf8_toupper(), GNUNET_SYSERR, GNUNET_YES, GNUNET_ATS_PluginEnvironment::in_quota, LOG, MLP_Variables::lp_mip_gap, MLP_Variables::m_q, MLP_Variables::mip_gap, mlp_branch_and_cut_cb(), MLP_CPLEX, MLP_DEFAULT_D, MLP_DEFAULT_MIN_CONNECTIONS, MLP_DEFAULT_QUALITY, MLP_DEFAULT_R, MLP_DEFAULT_U, MLP_GLPK, MLP_MAX_EXEC_DURATION, MLP_MAX_ITERATIONS, MLP_MPS, mlp_term_hook(), MLP_Variables::n_min, GAS_MLP_Handle::opt_dbg_autoscale_problem, GAS_MLP_Handle::opt_dbg_feasibility_only, GAS_MLP_Handle::opt_dbg_glpk_verbose, GAS_MLP_Handle::opt_dbg_intopt_presolver, GAS_MLP_Handle::opt_dbg_optimize_diversity, GAS_MLP_Handle::opt_dbg_optimize_quality, GAS_MLP_Handle::opt_dbg_optimize_relativity, GAS_MLP_Handle::opt_dbg_optimize_utility, GAS_MLP_Handle::opt_dump_problem_all, GAS_MLP_Handle::opt_dump_problem_on_fail, GAS_MLP_Handle::opt_dump_solution_all, GAS_MLP_Handle::opt_dump_solution_on_fail, GAS_MLP_Handle::opt_log_format, GAS_MLP_Handle::opt_mlp_auto_solve, GNUNET_ATS_PluginEnvironment::out_quota, GAS_MLP_Handle::pv, MLP_Variables::quota_in, MLP_Variables::quota_index, MLP_Variables::quota_out, GNUNET_TIME_Relative::rel_value_us, GAS_MLP_Handle::requested_peers, res, RQ_QUALITY_METRIC_COUNT, RQ_QUALITY_METRIC_DELAY, RQ_QUALITY_METRIC_DISTANCE, GNUNET_ATS_SolverFunctions::s_add, GNUNET_ATS_SolverFunctions::s_address_update_property, GNUNET_ATS_SolverFunctions::s_bulk_start, GNUNET_ATS_SolverFunctions::s_bulk_stop, GNUNET_ATS_SolverFunctions::s_del, GNUNET_ATS_SolverFunctions::s_feedback, GNUNET_ATS_SolverFunctions::s_get, GNUNET_ATS_SolverFunctions::s_get_stop, GNUNET_ATS_SolverFunctions::s_pref, sf, GAS_MLP_Handle::stat_bulk_lock, GAS_MLP_Handle::stat_bulk_requests, GAS_MLP_Handle::stat_mlp_prob_changed, and GAS_MLP_Handle::stat_mlp_prob_updated.

2472 {
2473  static struct GNUNET_ATS_SolverFunctions sf;
2475  struct GAS_MLP_Handle *mlp = GNUNET_new (struct GAS_MLP_Handle);
2476  float f_tmp;
2477  unsigned long long tmp;
2478  unsigned int b_min;
2479  unsigned int n_min;
2480  int c;
2481  char *outputformat;
2482 
2483  struct GNUNET_TIME_Relative max_duration;
2484  long long unsigned int max_iterations;
2485 
2486  /* Init GLPK environment */
2487  int res = glp_init_env ();
2488 
2489  switch (res)
2490  {
2491  case 0:
2492  LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
2493  "initialization successful");
2494  break;
2495 
2496  case 1:
2497  LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
2498  "environment is already initialized");
2499  break;
2500 
2501  case 2:
2502  LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
2503  "initialization failed (insufficient memory)");
2504  GNUNET_free (mlp);
2505  return NULL;
2506  break;
2507 
2508  case 3:
2509  LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
2510  "initialization failed (unsupported programming model)");
2511  GNUNET_free (mlp);
2512  return NULL;
2513  break;
2514 
2515  default:
2516  break;
2517  }
2518 
2520  "ats",
2521  "MLP_DUMP_PROBLEM_ALL");
2522  if (GNUNET_SYSERR == mlp->opt_dump_problem_all)
2524 
2526  "ats",
2527  "MLP_DUMP_SOLUTION_ALL");
2530 
2532  env->cfg,
2533  "ats",
2534  "MLP_DUMP_PROBLEM_ON_FAIL");
2537 
2539  env->cfg,
2540  "ats",
2541  "MLP_DUMP_SOLUTION_ON_FAIL");
2544 
2546  "ats",
2547  "MLP_DBG_GLPK_VERBOSE");
2548  if (GNUNET_SYSERR == mlp->opt_dbg_glpk_verbose)
2550 
2552  env->cfg,
2553  "ats",
2554  "MLP_DBG_FEASIBILITY_ONLY");
2559  "MLP solver is configured to check feasibility only!\n");
2560 
2562  env->cfg,
2563  "ats",
2564  "MLP_DBG_AUTOSCALE_PROBLEM");
2569  "MLP solver is configured automatically scale the problem!\n");
2570 
2572  env->cfg,
2573  "ats",
2574  "MLP_DBG_INTOPT_PRESOLVE");
2579  "MLP solver is configured use the mlp presolver\n");
2580 
2582  env->cfg,
2583  "ats",
2584  "MLP_DBG_OPTIMIZE_DIVERSITY");
2589  "MLP solver is not optimizing for diversity\n");
2590 
2592  env->cfg,
2593  "ats",
2594  "MLP_DBG_OPTIMIZE_RELATIVITY");
2599  "MLP solver is not optimizing for relativity\n");
2600 
2602  env->cfg,
2603  "ats",
2604  "MLP_DBG_OPTIMIZE_QUALITY");
2607  if (GNUNET_NO == mlp->opt_dbg_optimize_quality)
2609  "MLP solver is not optimizing for quality\n");
2610 
2612  env->cfg,
2613  "ats",
2614  "MLP_DBG_OPTIMIZE_UTILITY");
2617  if (GNUNET_NO == mlp->opt_dbg_optimize_utility)
2619  "MLP solver is not optimizing for utility\n");
2620 
2621  if ((GNUNET_NO == mlp->opt_dbg_optimize_utility) &&
2622  (GNUNET_NO == mlp->opt_dbg_optimize_quality) &&
2624  (GNUNET_NO == mlp->opt_dbg_optimize_utility) &&
2626  {
2628  _ (
2629  "MLP solver is not optimizing for anything, changing to feasibility check\n"));
2631  }
2632 
2634  "ats",
2635  "MLP_LOG_FORMAT",
2636  &outputformat))
2637  mlp->opt_log_format = MLP_CPLEX;
2638  else
2639  {
2640  GNUNET_STRINGS_utf8_toupper (outputformat, outputformat);
2641  if (0 == strcmp (outputformat, "MPS"))
2642  {
2643  mlp->opt_log_format = MLP_MPS;
2644  }
2645  else if (0 == strcmp (outputformat, "CPLEX"))
2646  {
2647  mlp->opt_log_format = MLP_CPLEX;
2648  }
2649  else if (0 == strcmp (outputformat, "GLPK"))
2650  {
2651  mlp->opt_log_format = MLP_GLPK;
2652  }
2653  else
2654  {
2656  "Invalid log format `%s' in configuration, using CPLEX!\n",
2657  outputformat);
2658  mlp->opt_log_format = MLP_CPLEX;
2659  }
2660  GNUNET_free (outputformat);
2661  }
2662 
2663  mlp->pv.BIG_M = (double) BIG_M_VALUE;
2664 
2665  mlp->pv.mip_gap = (double) 0.0;
2667  "MLP_MAX_MIP_GAP",
2668  &f_tmp))
2669  {
2670  if ((f_tmp < 0.0) || (f_tmp > 1.0))
2671  {
2672  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"),
2673  "MIP gap", f_tmp);
2674  }
2675  else
2676  {
2677  mlp->pv.mip_gap = f_tmp;
2678  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n",
2679  "MIP gap", f_tmp);
2680  }
2681  }
2682 
2683  mlp->pv.lp_mip_gap = (double) 0.0;
2685  "MLP_MAX_LP_MIP_GAP",
2686  &f_tmp))
2687  {
2688  if ((f_tmp < 0.0) || (f_tmp > 1.0))
2689  {
2690  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"),
2691  "LP/MIP", f_tmp);
2692  }
2693  else
2694  {
2695  mlp->pv.lp_mip_gap = f_tmp;
2696  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2697  "LP/MIP", f_tmp);
2698  }
2699  }
2700 
2701  /* Get timeout for iterations */
2703  "MLP_MAX_DURATION",
2704  &max_duration))
2705  {
2706  max_duration = MLP_MAX_EXEC_DURATION;
2707  }
2708 
2709  /* Get maximum number of iterations */
2711  "MLP_MAX_ITERATIONS",
2712  &max_iterations))
2713  {
2714  max_iterations = MLP_MAX_ITERATIONS;
2715  }
2716 
2717  /* Get diversity coefficient from configuration */
2718  mlp->pv.co_D = MLP_DEFAULT_D;
2720  "MLP_COEFFICIENT_D",
2721  &f_tmp))
2722  {
2723  if ((f_tmp < 0.0))
2724  {
2725  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"),
2726  "MLP_COEFFICIENT_D", f_tmp);
2727  }
2728  else
2729  {
2730  mlp->pv.co_D = f_tmp;
2731  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2732  "MLP_COEFFICIENT_D", f_tmp);
2733  }
2734  }
2735 
2736  /* Get relativity coefficient from configuration */
2737  mlp->pv.co_R = MLP_DEFAULT_R;
2739  "MLP_COEFFICIENT_R",
2740  &f_tmp))
2741  {
2742  if ((f_tmp < 0.0))
2743  {
2744  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"),
2745  "MLP_COEFFICIENT_R", f_tmp);
2746  }
2747  else
2748  {
2749  mlp->pv.co_R = f_tmp;
2750  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2751  "MLP_COEFFICIENT_R", f_tmp);
2752  }
2753  }
2754 
2755 
2756  /* Get utilization coefficient from configuration */
2757  mlp->pv.co_U = MLP_DEFAULT_U;
2759  "MLP_COEFFICIENT_U",
2760  &f_tmp))
2761  {
2762  if ((f_tmp < 0.0))
2763  {
2764  LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Invalid %s configuration %f \n"),
2765  "MLP_COEFFICIENT_U", f_tmp);
2766  }
2767  else
2768  {
2769  mlp->pv.co_U = f_tmp;
2770  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2771  "MLP_COEFFICIENT_U", f_tmp);
2772  }
2773  }
2774 
2775  /* Get quality metric coefficients from configuration */
2776  for (c = 0; c < RQ_QUALITY_METRIC_COUNT; c++)
2777  {
2778  /* initialize quality coefficients with default value 1.0 */
2779  mlp->pv.co_Q[c] = MLP_DEFAULT_QUALITY;
2780  }
2781 
2782 
2783  if (GNUNET_OK ==
2785  "MLP_COEFFICIENT_QUALITY_DELAY",
2786  &tmp))
2787  mlp->pv.co_Q[RQ_QUALITY_METRIC_DELAY] = (double) tmp / 100;
2788  else
2790 
2791  if (GNUNET_OK ==
2793  "MLP_COEFFICIENT_QUALITY_DISTANCE",
2794  &tmp))
2795  mlp->pv.co_Q[RQ_QUALITY_METRIC_DISTANCE] = (double) tmp / 100;
2796  else
2798 
2799  /* Get minimum bandwidth per used address from configuration */
2801  "MLP_MIN_BANDWIDTH",
2802  &tmp))
2803  b_min = tmp;
2804  else
2805  {
2806  b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
2807  }
2808 
2809  /* Get minimum number of connections from configuration */
2811  "MLP_MIN_CONNECTIONS",
2812  &tmp))
2813  n_min = tmp;
2814  else
2816 
2817  /* Init network quotas */
2818  for (c = 0; c < GNUNET_NT_COUNT; c++)
2819  {
2820  mlp->pv.quota_index[c] = c;
2821  mlp->pv.quota_out[c] = env->out_quota[c];
2822  mlp->pv.quota_in[c] = env->in_quota[c];
2823 
2825  "Quota for network `%s' (in/out) %llu/%llu\n",
2826  GNUNET_NT_to_string (c),
2827  mlp->pv.quota_out[c],
2828  mlp->pv.quota_in[c]);
2829  /* Check if defined quota could make problem unsolvable */
2830  if ((n_min * b_min) > mlp->pv.quota_out[c])
2831  {
2833  _ (
2834  "Adjusting inconsistent outbound quota configuration for network `%s', is %llu must be at least %llu\n"),
2836  mlp->pv.quota_out[c],
2837  (n_min * b_min));
2838  mlp->pv.quota_out[c] = (n_min * b_min);
2839  }
2840  if ((n_min * b_min) > mlp->pv.quota_in[c])
2841  {
2843  _ (
2844  "Adjusting inconsistent inbound quota configuration for network `%s', is %llu must be at least %llu\n"),
2846  mlp->pv.quota_in[c],
2847  (n_min * b_min));
2848  mlp->pv.quota_in[c] = (n_min * b_min);
2849  }
2850  /* Check if bandwidth is too big to make problem solvable */
2851  if (mlp->pv.BIG_M < mlp->pv.quota_out[c])
2852  {
2854  _ (
2855  "Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n"),
2857  mlp->pv.quota_out[c],
2858  mlp->pv.BIG_M);
2859  mlp->pv.quota_out[c] = mlp->pv.BIG_M;
2860  }
2861  if (mlp->pv.BIG_M < mlp->pv.quota_in[c])
2862  {
2864  _ (
2865  "Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n"),
2867  mlp->pv.quota_in[c],
2868  mlp->pv.BIG_M);
2869  mlp->pv.quota_in[c] = mlp->pv.BIG_M;
2870  }
2871  }
2872  mlp->env = env;
2873  sf.cls = mlp;
2883 
2884  /* Setting MLP Input variables */
2885  mlp->pv.b_min = b_min;
2886  mlp->pv.n_min = n_min;
2892  mlp->stat_bulk_requests = 0;
2893  mlp->stat_bulk_lock = 0;
2894 
2895  /* Setup GLPK */
2896  /* Redirect GLPK output to GNUnet logging */
2897  glp_term_hook (&mlp_term_hook, (void *) mlp);
2898 
2899  /* Init LP solving parameters */
2900  glp_init_smcp (&mlp->control_param_lp);
2901  mlp->control_param_lp.msg_lev = GLP_MSG_OFF;
2902  if (GNUNET_YES == mlp->opt_dbg_glpk_verbose)
2903  mlp->control_param_lp.msg_lev = GLP_MSG_ALL;
2904 
2905  mlp->control_param_lp.it_lim = max_iterations;
2906  mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL;
2907 
2908  /* Init MLP solving parameters */
2909  glp_init_iocp (&mlp->control_param_mlp);
2910  /* Setting callback function */
2911  mlp->control_param_mlp.cb_func = &mlp_branch_and_cut_cb;
2912  mlp->control_param_mlp.cb_info = mlp;
2913  mlp->control_param_mlp.msg_lev = GLP_MSG_OFF;
2914  mlp->control_param_mlp.mip_gap = mlp->pv.mip_gap;
2915  if (GNUNET_YES == mlp->opt_dbg_glpk_verbose)
2916  mlp->control_param_mlp.msg_lev = GLP_MSG_ALL;
2917  mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL;
2918 
2919  LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n");
2920 
2921  return &sf;
2922 }
unsigned int b_min
GAS_solver_stop_get_preferred_address s_get_stop
Tell solver stop notifying ATS about changes for this peers.
int opt_dump_solution_on_fail
Write MILP problem solutions to a file when solver fails.
#define MLP_DEFAULT_MIN_CONNECTIONS
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
static void GAS_mlp_address_delete(void *solver, struct ATS_Address *address)
Deletes a single address in the MLP problem.
GAS_solver_address_add s_add
Add a new address for a peer to the solver.
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:44
enum MLP_Output_Format opt_log_format
Output format.
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
int opt_dbg_feasibility_only
solve feasibility only
struct GNUNET_CONTAINER_MultiPeerMap * requested_peers
Peers with pending address requests.
static void GAS_mlp_address_add(void *solver, struct ATS_Address *address, uint32_t network)
Add a single address to the solve.
int opt_dbg_optimize_relativity
solve autoscale the problem
static void mlp_branch_and_cut_cb(glp_tree *tree, void *info)
int quota_index[GNUNET_NT_COUNT]
static void GAS_mlp_get_preferred_address(void *solver, const struct GNUNET_PeerIdentity *peer)
Get the preferred address for a specific peer.
GAS_solver_address_feedback_preference s_feedback
Give feedback about the current assignment.
static void GAS_mlp_bulk_stop(void *solver)
int GNUNET_CONFIGURATION_get_value_float(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, float *number)
Get a configuration value that should be a floating point number.
int stat_bulk_requests
Number of changes while solver was locked.
GAS_solver_address_property_changed s_address_update_property
Update the properties of an address in the solver.
int opt_dbg_optimize_utility
solve autoscale the problem
int opt_mlp_auto_solve
Solve the problem automatically when updates occur? Default: GNUNET_YES Can be disabled for test and ...
#define GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT
Bandwidth (in/out) to assume initially (before either peer has communicated any particular preference...
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int opt_dbg_glpk_verbose
Print GLPK output.
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
int opt_dbg_optimize_quality
solve autoscale the problem
int stat_mlp_prob_changed
Has the problem size changed since last solution.
#define MLP_DEFAULT_QUALITY
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static void GAS_mlp_address_property_changed(void *solver, struct ATS_Address *address)
Transport properties for this address have changed.
int opt_dump_problem_on_fail
Write MILP problems to a MPS file when solver fails.
int stat_bulk_lock
Bulk lock.
void GNUNET_STRINGS_utf8_toupper(const char *input, char *output)
Convert the utf-8 input string to upper case.
Definition: strings.c:578
unsigned int n_min
static void GAS_mlp_address_preference_feedback(void *solver, struct GNUNET_SERVICE_Client *application, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_TIME_Relative scope, enum GNUNET_ATS_PreferenceKind kind, double score)
Get application feedback for a peer.
int opt_dump_problem_all
Write all MILP problems to a MPS file.
#define MLP_MAX_EXEC_DURATION
GAS_solver_address_delete s_del
Delete an address in the solver.
int opt_dbg_intopt_presolver
use the intopt presolver instead of simplex
struct GNUNET_ATS_PluginEnvironment * env
#define MLP_MAX_ITERATIONS
unsigned long long quota_out[GNUNET_NT_COUNT]
GAS_solver_address_change_preference s_pref
Change relative preference for quality in solver.
int GNUNET_CONFIGURATION_get_value_size(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *size)
Get a configuration value that should be a size in bytes.
#define BIG_M_VALUE
static int res
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define MLP_DEFAULT_U
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
int opt_dbg_optimize_diversity
solve autoscale the problem
double co_Q[RQ_QUALITY_METRIC_COUNT]
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
void * cls
Closure to pass to all solver functions in this struct.
#define MLP_DEFAULT_D
static void GAS_mlp_address_change_preference(void *solver, const struct GNUNET_PeerIdentity *peer, enum GNUNET_ATS_PreferenceKind kind, double pref_rel)
Changes the preferences for a peer in the MLP problem.
int opt_dbg_autoscale_problem
solve autoscale the problem
GAS_solver_get_preferred_address s_get
Tell solver to notify ATS if the address to use changes for a specific peer using the bandwidth chang...
unsigned long long in_quota[6]
Array of configured inbound quotas Order according to networks in network array.
unsigned long long quota_in[GNUNET_NT_COUNT]
MLP Handle.
GAS_solver_bulk_start s_bulk_start
Start a bulk operation.
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration handle to be used by the solver.
unsigned long long out_quota[6]
Array of configured outbound quotas Order according to networks in network array. ...
static void GAS_mlp_stop_get_preferred_address(void *solver, const struct GNUNET_PeerIdentity *peer)
Stop notifying about address and bandwidth changes for this peer.
void * cls
Closure to pass to all callbacks in this struct.
#define GNUNET_YES
Definition: gnunet_common.h:77
#define MLP_DEFAULT_R
static struct GNUNET_ATS_SolverFunctions * sf
Solver handle.
int stat_mlp_prob_updated
Was the problem updated since last solution.
int opt_dump_solution_all
Write all MILP problem solutions to a file.
The ATS plugin will pass a pointer to a struct of this type as to the initialization function of the ...
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
glp_iocp control_param_mlp
GLPK LP control parameter.
glp_smcp control_param_lp
GLPK LP control parameter.
GAS_solver_bulk_stop s_bulk_stop
Bulk operation done.
#define LOG(kind,...)
NOTE: Do not modify this documentation.
#define GNUNET_NT_COUNT
static void GAS_mlp_bulk_start(void *solver)
Start a bulk operation.
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static int mlp_term_hook(void *info, const char *s)
Intercept GLPK terminal output.
Here is the call graph for this function: