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   GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10)
 
#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   GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10)

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 43 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 45 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 46 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 47 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 48 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 49 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 50 of file plugin_ats_mlp.c.

◆ MLP_NaN

#define MLP_NaN   -1

Definition at line 52 of file plugin_ats_mlp.c.

Referenced by mlp_propagate_results().

◆ MLP_UNDEFINED

#define MLP_UNDEFINED   0

Definition at line 53 of file plugin_ats_mlp.c.

Referenced by mlp_delete_problem().

◆ GLP_YES

#define GLP_YES   1.0

Definition at line 54 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 55 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 57 of file plugin_ats_mlp.c.

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

◆ QualityMetrics

Enumerator
RQ_QUALITY_METRIC_DELAY 
RQ_QUALITY_METRIC_DISTANCE 
RQ_QUALITY_METRIC_COUNT 

Definition at line 65 of file plugin_ats_mlp.c.

Function Documentation

◆ print_quality_type()

static const char* print_quality_type ( enum QualityMetrics  qm)
static

Definition at line 74 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().

75 {
76  switch (qm){
78  return "delay";
80  return "distance";
81  default:
82  GNUNET_break (0);
83  return NULL;
84  }
85 }
#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  peer->processed = GNUNET_NO;
555  return GNUNET_OK;
556  }
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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 564 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().

565 {
566  int c;
567  if (mlp == NULL)
568  return;
569  if (mlp->p.prob != NULL)
570  {
571  glp_delete_prob(mlp->p.prob);
572  mlp->p.prob = NULL;
573  }
574 
575  /* delete row index */
576  if (mlp->p.ia != NULL)
577  {
578  GNUNET_free (mlp->p.ia);
579  mlp->p.ia = NULL;
580  }
581 
582  /* delete column index */
583  if (mlp->p.ja != NULL)
584  {
585  GNUNET_free (mlp->p.ja);
586  mlp->p.ja = NULL;
587  }
588 
589  /* delete coefficients */
590  if (mlp->p.ar != NULL)
591  {
592  GNUNET_free (mlp->p.ar);
593  mlp->p.ar = NULL;
594  }
595  mlp->p.ci = 0;
596  mlp->p.prob = NULL;
597 
598  mlp->p.c_d = MLP_UNDEFINED;
599  mlp->p.c_r = MLP_UNDEFINED;
600  mlp->p.r_c2 = MLP_UNDEFINED;
601  mlp->p.r_c4 = MLP_UNDEFINED;
602  mlp->p.r_c6 = MLP_UNDEFINED;
603  mlp->p.r_c9 = MLP_UNDEFINED;
604  for (c = 0; c < RQ_QUALITY_METRIC_COUNT ; c ++)
605  mlp->p.r_q[c] = MLP_UNDEFINED;
606  for (c = 0; c < GNUNET_NT_COUNT; c ++)
607  mlp->p.r_quota[c] = MLP_UNDEFINED;
608  mlp->p.ci = MLP_UNDEFINED;
609 
610 
612  &reset_peers, NULL);
613 }
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 622 of file plugin_ats_mlp.c.

References GNUNET_break.

Referenced by GAS_mlp_solve_problem(), and mlp_solve_lp_problem().

623 {
624  switch (retcode) {
625  case GLP_UNDEF:
626  return "solution is undefined";
627  case GLP_FEAS:
628  return "solution is feasible";
629  case GLP_INFEAS:
630  return "solution is infeasible";
631  case GLP_NOFEAS:
632  return "no feasible solution exists";
633  case GLP_OPT:
634  return "solution is optimal";
635  case GLP_UNBND:
636  return "solution is unbounded";
637  default:
638  GNUNET_break (0);
639  return "unknown error";
640  }
641 }
#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 650 of file plugin_ats_mlp.c.

References GNUNET_break.

Referenced by GAS_mlp_solve_problem(), and mlp_solve_lp_problem().

651 {
652  switch (retcode) {
653  case 0:
654  return "ok";
655  case GLP_EBADB:
656  return "invalid basis";
657  case GLP_ESING:
658  return "singular matrix";
659  case GLP_ECOND:
660  return "ill-conditioned matrix";
661  case GLP_EBOUND:
662  return "invalid bounds";
663  case GLP_EFAIL:
664  return "solver failed";
665  case GLP_EOBJLL:
666  return "objective lower limit reached";
667  case GLP_EOBJUL:
668  return "objective upper limit reached";
669  case GLP_EITLIM:
670  return "iteration limit exceeded";
671  case GLP_ETMLIM:
672  return "time limit exceeded";
673  case GLP_ENOPFS:
674  return "no primal feasible solution";
675  case GLP_ENODFS:
676  return "no dual feasible solution";
677  case GLP_EROOT:
678  return "root LP optimum not provided";
679  case GLP_ESTOP:
680  return "search terminated by application";
681  case GLP_EMIPGAP:
682  return "relative mip gap tolerance reached";
683  case GLP_ENOFEAS:
684  return "no dual feasible solution";
685  case GLP_ENOCVG:
686  return "no convergence";
687  case GLP_EINSTAB:
688  return "numerical instability";
689  case GLP_EDATA:
690  return "invalid data";
691  case GLP_ERANGE:
692  return "result out of range";
693  default:
694  GNUNET_break (0);
695  return "unknown error";
696  }
697 }
#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 707 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().

710 {
711  struct CountContext *cctx = cls;
712 
713  /* Check if we have to add this peer due to a pending request */
715  cctx->result++;
716  return GNUNET_OK;
717 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_YES
Definition: gnunet_common.h:80
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 721 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().

723 {
724  struct CountContext cctx;
725 
726  cctx.map = requested_peers;
727  cctx.result = 0;
730  return cctx.result;
731 }
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 735 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().

738 {
739  struct CountContext *cctx = cls;
740 
741  /* Check if we have to addresses for the requested peer */
743  cctx->result++;
744  return GNUNET_OK;
745 }
const struct GNUNET_CONTAINER_MultiPeerMap * map
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_YES
Definition: gnunet_common.h:80
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 749 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().

751 {
752  struct CountContext cctx;
753 
754  cctx.map = addresses;
755  cctx.result = 0;
756  GNUNET_CONTAINER_multipeermap_iterate (requested_peers,
758  return cctx.result;
759 }
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 776 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().

779 {
780  int c_cols;
781  int c_elems;
782  int c1;
783  int res;
784  int found;
785  double *val_array;
786  int *ind_array;
787 
788  GNUNET_assert (NULL != p->prob);
789 
790  /* Get number of columns and prepare data structure */
791  c_cols = glp_get_num_cols(p->prob);
792  if (0 >= c_cols)
793  return GNUNET_SYSERR;
794 
795  val_array = GNUNET_malloc ((c_cols +1)* sizeof (double));
796  GNUNET_assert (NULL != val_array);
797  ind_array = GNUNET_malloc ((c_cols+1) * sizeof (int));
798  GNUNET_assert (NULL != ind_array);
799  /* Extract the row */
800 
801  /* Update the value */
802  c_elems = glp_get_mat_row (p->prob, row, ind_array, val_array);
803  found = GNUNET_NO;
804  for (c1 = 1; c1 < (c_elems+1); c1++)
805  {
806  if (ind_array[c1] == col)
807  {
808  found = GNUNET_YES;
809  break;
810  }
811  }
812  if (GNUNET_NO == found)
813  {
814  ind_array[c_elems+1] = col;
815  val_array[c_elems+1] = val;
816  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Setting value in [%s : %s] to `%.2f'\n",
817  glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
818  val);
819  glp_set_mat_row (p->prob, row, c_elems+1, ind_array, val_array);
820  GNUNET_free (ind_array);
821  GNUNET_free (val_array);
822  return GNUNET_YES;
823  }
824  else
825  {
826  /* Update value */
827  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P] Updating value in [%s : %s] from `%.2f' to `%.2f'\n",
828  glp_get_row_name (p->prob, row), glp_get_col_name (p->prob, col),
829  val_array[c1], val);
830  if (val != val_array[c1])
831  res = GNUNET_YES;
832  else
833  res = GNUNET_NO;
834  val_array[c1] = val;
835  /* Update the row in the matrix */
836  glp_set_mat_row (p->prob, row, c_elems, ind_array, val_array);
837  }
838 
839  GNUNET_free (ind_array);
840  GNUNET_free (val_array);
841  return res;
842 }
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:81
static int res
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
#define GNUNET_YES
Definition: gnunet_common.h:80
#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 857 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().

860 {
861  if ((p->ci) >= p->num_elements)
862  {
863  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Request for index %u bigger than array size of %u\n",
864  line, p->ci + 1, p->num_elements);
865  GNUNET_break (0);
866  return;
867  }
868  if ((0 == row) || (0 == col))
869  {
870  GNUNET_break (0);
871  LOG (GNUNET_ERROR_TYPE_ERROR, "[P]: Invalid call from line %u: row = %u, col = %u\n",
872  line, row, col);
873  }
874  p->ia[p->ci] = row ;
875  p->ja[p->ci] = col;
876  p->ar[p->ci] = val;
877 #if DEBUG_MLP_PROBLEM_CREATION
878  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: line %u: Set value [%u,%u] in index %u == %.2f\n",
879  line, p->ia[p->ci], p->ja[p->ci], p->ci, p->ar[p->ci]);
880 #endif
881  p->ci++;
882 }
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 885 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().

888 {
889  int col = glp_add_cols (p->prob, 1);
890  glp_set_col_name (p->prob, col, name);
891  glp_set_col_bnds (p->prob, col, bound, lb, ub);
892  glp_set_col_kind (p->prob, col, type);
893  glp_set_obj_coef (p->prob, col, coef);
894 #if DEBUG_MLP_PROBLEM_CREATION
895  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added column [%u] `%s': %.2f\n",
896  col, name, coef);
897 #endif
898  return col;
899 }
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 902 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().

904 {
905  char * op;
906  int row = glp_add_rows (p->prob, 1);
907  /* set row name */
908  glp_set_row_name (p->prob, row, name);
909  /* set row bounds: <= 0 */
910  glp_set_row_bnds (p->prob, row, bound, lb, ub);
911  switch (bound)
912  {
913  case GLP_UP:
914  GNUNET_asprintf(&op, "-inf <= x <= %.2f", ub);
915  break;
916  case GLP_DB:
917  GNUNET_asprintf(&op, "%.2f <= x <= %.2f", lb, ub);
918  break;
919  case GLP_FX:
920  GNUNET_asprintf(&op, "%.2f == x == %.2f", lb, ub);
921  break;
922  case GLP_LO:
923  GNUNET_asprintf(&op, "%.2f <= x <= inf", lb);
924  break;
925  default:
926  GNUNET_asprintf(&op, "ERROR");
927  break;
928  }
929 #if DEBUG_MLP_PROBLEM_CREATION
930  LOG (GNUNET_ERROR_TYPE_DEBUG, "[P]: Added row [%u] `%s': %s\n",
931  row, name, op);
932 #endif
933  GNUNET_free (op);
934  return row;
935 }
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:139
#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 945 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().

948 {
949  struct GAS_MLP_Handle *mlp = cls;
950  struct MLP_Problem *p = &mlp->p;
951  struct ATS_Address *address = value;
952  struct ATS_Peer *peer;
953  struct MLP_information *mlpi;
954  char *name;
955  double cur_bigm;
956  uint32_t addr_net;
957  uint32_t addr_net_index;
958  unsigned long long max_quota;
959  int c;
960 
961  /* Check if we have to add this peer due to a pending request */
963  return GNUNET_OK;
964 
965  mlpi = address->solver_information;
966  if (NULL == mlpi)
967  {
968  fprintf (stderr, "%s %p\n",GNUNET_i2s (&address->peer), address);
969  GNUNET_break (0);
970  return GNUNET_OK;
971  }
972 
973  addr_net = address->properties.scope;
974  for (addr_net_index = 0; addr_net_index < GNUNET_NT_COUNT; addr_net_index++)
975  {
976  if (mlp->pv.quota_index[addr_net_index] == addr_net)
977  break;
978  }
979 
980  if (addr_net_index >= GNUNET_NT_COUNT)
981  {
982  GNUNET_break (0);
983  return GNUNET_OK;
984  }
985 
986  max_quota = 0;
987  for (c = 0; c < GNUNET_NT_COUNT; c++)
988  {
989  if (mlp->pv.quota_out[c] > max_quota)
990  max_quota = mlp->pv.quota_out[c];
991  if (mlp->pv.quota_in[c] > max_quota)
992  max_quota = mlp->pv.quota_in[c];
993  }
994  if (max_quota > mlp->pv.BIG_M)
995  cur_bigm = (double) mlp->pv.BIG_M;
996  else
997  cur_bigm = max_quota;
998 
999 
1000  /* Get peer */
1002  GNUNET_assert (NULL != peer);
1003  if (peer->processed == GNUNET_NO)
1004  {
1005  /* Add peer dependent constraints */
1006  /* Add c2) One address active per peer */
1007  GNUNET_asprintf(&name, "c2_%s", GNUNET_i2s(&address->peer));
1008  peer->r_c2 = mlp_create_problem_create_constraint (p, name, GLP_FX, 1.0, 1.0);
1009  GNUNET_free (name);
1010  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1011  {
1013  {
1014  /* Add c9) Relativity */
1015  GNUNET_asprintf(&name, "c9_%s", GNUNET_i2s(&address->peer));
1016  peer->r_c9 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0);
1017  GNUNET_free (name);
1018  /* c9) set coefficient */
1019  mlp_create_problem_set_value (p, peer->r_c9, p->c_r, -peer->f , __LINE__);
1020  }
1021  }
1022  peer->processed = GNUNET_YES;
1023  }
1024 
1025  /* Reset addresses' solver information */
1026  mlpi->c_b = 0;
1027  mlpi->c_n = 0;
1028  mlpi->n = 0;
1029  mlpi->r_c1 = 0;
1030  mlpi->r_c3 = 0;
1031 
1032  /* Add bandwidth column */
1033  GNUNET_asprintf (&name, "b_%s_%s_%p", GNUNET_i2s (&address->peer), address->plugin, address);
1034  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1035  {
1036  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, 0.0);
1037  }
1038  else
1039  {
1040  /* Maximize for bandwidth assignment in feasibility testing */
1041  mlpi->c_b = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, 1.0);
1042  }
1043  GNUNET_free (name);
1044 
1045  /* Add address active column */
1046  GNUNET_asprintf (&name, "n_%s_%s_%p", GNUNET_i2s (&address->peer), address->plugin, address);
1047  mlpi->c_n = mlp_create_problem_create_column (p, name, GLP_IV, GLP_DB, 0.0, 1.0, 0.0);
1048  GNUNET_free (name);
1049 
1050  /* Add address dependent constraints */
1051  /* Add c1) bandwidth capping: b_t + (-M) * n_t <= 0 */
1052  GNUNET_asprintf(&name, "c1_%s_%s_%p", GNUNET_i2s(&address->peer), address->plugin, address);
1053  mlpi->r_c1 = mlp_create_problem_create_constraint (p, name, GLP_UP, 0.0, 0.0);
1054  GNUNET_free (name);
1055  /* c1) set b = 1 coefficient */
1056  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_b, 1, __LINE__);
1057  /* c1) set n = - min (M, quota) coefficient */
1058  cur_bigm = (double) mlp->pv.quota_out[addr_net_index];
1059  if (cur_bigm > mlp->pv.BIG_M)
1060  cur_bigm = (double) mlp->pv.BIG_M;
1061  mlp_create_problem_set_value (p, mlpi->r_c1, mlpi->c_n, -cur_bigm, __LINE__);
1062 
1063  /* Add constraint c 3) minimum bandwidth
1064  * b_t + (-n_t * b_min) >= 0
1065  * */
1066  GNUNET_asprintf(&name, "c3_%s_%s_%p", GNUNET_i2s(&address->peer), address->plugin, address);
1067  mlpi->r_c3 = mlp_create_problem_create_constraint (p, name, GLP_LO, 0.0, 0.0);
1068  GNUNET_free (name);
1069 
1070  /* c3) set b = 1 coefficient */
1071  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_b, 1, __LINE__);
1072  /* c3) set n = -b_min coefficient */
1073  mlp_create_problem_set_value (p, mlpi->r_c3, mlpi->c_n, - ((double )mlp->pv.b_min), __LINE__);
1074 
1075 
1076  /* Set coefficient entries in invariant rows */
1077 
1078  /* Feasbility */
1079 
1080  /* c 4) minimum connections */
1081  mlp_create_problem_set_value (p, p->r_c4, mlpi->c_n, 1, __LINE__);
1082  /* c 2) 1 address peer peer */
1083  mlp_create_problem_set_value (p, peer->r_c2, mlpi->c_n, 1, __LINE__);
1084  /* c 10) obey network specific quotas
1085  * (1)*b_1 + ... + (1)*b_m <= quota_n
1086  */
1087  mlp_create_problem_set_value (p, p->r_quota[addr_net_index], mlpi->c_b, 1, __LINE__);
1088 
1089  /* Optimality */
1090  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1091  {
1092  /* c 6) maximize diversity */
1093  mlp_create_problem_set_value (p, p->r_c6, mlpi->c_n, 1, __LINE__);
1094  /* c 9) relativity */
1096  mlp_create_problem_set_value (p, peer->r_c9, mlpi->c_b, 1, __LINE__);
1097  /* c 8) utility */
1099  mlp_create_problem_set_value (p, p->r_c8, mlpi->c_b, 1, __LINE__);
1100  /* c 7) Optimize quality */
1101  /* For all quality metrics, set quality of this address */
1103  {
1106  mlpi->c_b,
1107  address->norm_delay.norm,
1108  __LINE__);
1111  mlpi->c_b,
1112  address->norm_distance.norm,
1113  __LINE__);
1114  }
1115  }
1116 
1117  return GNUNET_OK;
1118 }
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:80
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 1125 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().

1126 {
1127  int c;
1128 
1129  /* Feasibility */
1130 
1131  /* Row for c4) minimum connection */
1132  /* Number of minimum connections is min(|Peers|, n_min) */
1133  p->r_c4 = mlp_create_problem_create_constraint (p, "c4", GLP_LO, (mlp->pv.n_min > p->num_peers) ? p->num_peers : mlp->pv.n_min, 0.0);
1134 
1135  /* Rows for c 10) Enforce network quotas */
1136  for (c = 0; c < GNUNET_NT_COUNT; c++)
1137  {
1138  char * text;
1139  GNUNET_asprintf(&text, "c10_quota_ats_%s",
1141  p->r_quota[c] = mlp_create_problem_create_constraint (p, text, GLP_DB, 0.0, mlp->pv.quota_out[c]);
1142  GNUNET_free (text);
1143  }
1144 
1145  /* Optimality */
1146  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1147  {
1148  char *name;
1149  /* Add row for c6) Maximize for diversity */
1151  {
1152  p->r_c6 = mlp_create_problem_create_constraint (p, "c6", GLP_FX, 0.0, 0.0);
1153  /* Set c6 ) Setting -D */
1154  mlp_create_problem_set_value (p, p->r_c6, p->c_d, -1, __LINE__);
1155  }
1156 
1157  /* Adding rows for c 8) Maximize utility */
1159  {
1160  p->r_c8 = mlp_create_problem_create_constraint (p, "c8", GLP_FX, 0.0, 0.0);
1161  /* -u */
1162  mlp_create_problem_set_value (p, p->r_c8, p->c_u, -1, __LINE__);
1163  }
1164 
1165  /* For all quality metrics:
1166  * c 7) Maximize quality, austerity */
1168  {
1169  for (c = 0; c < mlp->pv.m_q; c++)
1170  {
1171  GNUNET_asprintf (&name,
1172  "c7_q%i_%s", c,
1173  print_quality_type (c));
1174  p->r_q[c] = mlp_create_problem_create_constraint (p, name, GLP_FX, 0.0, 0.0);
1175  GNUNET_free (name);
1177  p->r_q[c],
1178  p->c_q[c], -1, __LINE__);
1179  }
1180  }
1181  }
1182 }
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:43
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:81
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:80
#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 1189 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().

1190 {
1191  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
1192  {
1193  char *name;
1194  int c;
1195 
1196  /* Diversity d column */
1198  p->c_d = mlp_create_problem_create_column (p, "d", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_D);
1199 
1200  /* Utilization u column */
1202  p->c_u = mlp_create_problem_create_column (p, "u", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_U);
1203 
1204  /* Relativity r column */
1206  p->c_r = mlp_create_problem_create_column (p, "r", GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_R);
1207 
1208  /* Quality metric columns */
1210  {
1211  for (c = 0; c < mlp->pv.m_q; c++)
1212  {
1213  GNUNET_asprintf (&name, "q_%u", c);
1214  p->c_q[c] = mlp_create_problem_create_column (p, name, GLP_CV, GLP_LO, 0.0, 0.0, mlp->pv.co_Q[c]);
1215  GNUNET_free (name);
1216  }
1217  }
1218  }
1219 }
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:81
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:80
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 1229 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().

1230 {
1231  struct MLP_Problem *p = &mlp->p;
1232  int res = GNUNET_OK;
1233 
1234  GNUNET_assert (p->prob == NULL);
1235  GNUNET_assert (p->ia == NULL);
1236  GNUNET_assert (p->ja == NULL);
1237  GNUNET_assert (p->ar == NULL);
1238  /* Reset MLP problem struct */
1239 
1240  /* create the glpk problem */
1241  p->prob = glp_create_prob ();
1242  GNUNET_assert (NULL != p->prob);
1245  mlp->env->addresses);
1246 
1247  /* Create problem matrix: 10 * #addresses + #q * #addresses + #q, + #peer + 2 + 1 */
1248  p->num_elements = (10 * p->num_addresses + mlp->pv.m_q * p->num_addresses +
1249  mlp->pv.m_q + p->num_peers + 2 + 1);
1251  "Rebuilding problem for %u peer(s) and %u addresse(s) and %u quality metrics == %u elements\n",
1252  p->num_peers,
1253  p->num_addresses,
1254  mlp->pv.m_q,
1255  p->num_elements);
1256 
1257  /* Set a problem name */
1258  glp_set_prob_name (p->prob, "GNUnet ATS bandwidth distribution");
1259  /* Set optimization direction to maximize */
1260  glp_set_obj_dir (p->prob, GLP_MAX);
1261 
1262  /* Create problem matrix */
1263  /* last +1 caused by glpk index starting with one: [1..elements]*/
1264  p->ci = 1;
1265  /* row index */
1266  p->ia = GNUNET_malloc (p->num_elements * sizeof (int));
1267  /* column index */
1268  p->ja = GNUNET_malloc (p->num_elements * sizeof (int));
1269  /* coefficient */
1270  p->ar = GNUNET_malloc (p->num_elements * sizeof (double));
1271 
1272  if ((NULL == p->ia) || (NULL == p->ja) || (NULL == p->ar))
1273  {
1274  LOG (GNUNET_ERROR_TYPE_ERROR, _("Problem size too large, cannot allocate memory!\n"));
1275  return GNUNET_SYSERR;
1276  }
1277 
1278  /* Adding invariant columns */
1280 
1281  /* Adding address independent constraint rows */
1283 
1284  /* Adding address dependent columns constraint rows */
1287  mlp);
1288 
1289  /* Load the matrix */
1290  LOG (GNUNET_ERROR_TYPE_DEBUG, "Loading matrix\n");
1291  glp_load_matrix(p->prob, (p->ci)-1, p->ia, p->ja, p->ar);
1293  {
1294  glp_scale_prob (p->prob, GLP_SF_AUTO);
1295  }
1296 
1297  return res;
1298 }
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:78
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:208
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:79
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:80
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 1308 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().

1309 {
1310  int res = 0;
1311  int res_status = 0;
1312  res = glp_simplex(mlp->p.prob, &mlp->control_param_lp);
1313  if (0 == res)
1314  LOG(GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem: %s\n",
1315  mlp_solve_to_string (res));
1316  else
1317  LOG(GNUNET_ERROR_TYPE_DEBUG, "Solving LP problem failed: %s\n",
1318  mlp_solve_to_string (res));
1319 
1320  /* Analyze problem status */
1321  res_status = glp_get_status (mlp->p.prob);
1322  switch (res_status) {
1323  case GLP_OPT: /* solution is optimal */
1325  "Solving LP problem: %s, %s\n",
1326  mlp_solve_to_string(res),
1327  mlp_status_to_string(res_status));
1328  return GNUNET_OK;
1329  default:
1331  "Solving LP problem failed: %s %s\n",
1332  mlp_solve_to_string(res),
1333  mlp_status_to_string(res_status));
1334  return GNUNET_SYSERR;
1335  }
1336 }
glp_prob * prob
GLPK (MLP) problem object.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:79
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 1348 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().

1351 {
1352  struct GAS_MLP_Handle *mlp = cls;
1353  struct ATS_Address *address;
1354  struct MLP_information *mlpi;
1355  double mlp_bw_in = MLP_NaN;
1356  double mlp_bw_out = MLP_NaN;
1357  double mlp_use = MLP_NaN;
1358 
1359  /* Check if we have to add this peer due to a pending request */
1361  key))
1362  {
1363  return GNUNET_OK;
1364  }
1365  address = value;
1366  GNUNET_assert (address->solver_information != NULL);
1367  mlpi = address->solver_information;
1368 
1369  mlp_bw_in = glp_mip_col_val(mlp->p.prob, mlpi->c_b);/* FIXME */
1370  if (mlp_bw_in > (double) UINT32_MAX)
1371  {
1372  LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing ...\n" );
1373  mlp_bw_in = (double) UINT32_MAX;
1374  }
1375  mlp_bw_out = glp_mip_col_val(mlp->p.prob, mlpi->c_b);
1376  if (mlp_bw_out > (double) UINT32_MAX)
1377  {
1378  LOG (GNUNET_ERROR_TYPE_DEBUG, "Overflow in assigned bandwidth, reducing ...\n" );
1379  mlp_bw_out = (double) UINT32_MAX;
1380  }
1381  mlp_use = glp_mip_col_val(mlp->p.prob, mlpi->c_n);
1382 
1383  /*
1384  * Debug: solution
1385  * LOG (GNUNET_ERROR_TYPE_INFO, "MLP result address: `%s' `%s' length %u session %u, mlp use %.3f\n",
1386  * GNUNET_i2s(&address->peer), address->plugin,
1387  * address->addr_len, address->session_id);
1388  */
1389 
1390  if (GLP_YES == mlp_use)
1391  {
1392  /* This address was selected by the solver to be used */
1393  mlpi->n = GNUNET_YES;
1394  if (GNUNET_NO == address->active)
1395  {
1396  /* Address was not used before, enabling address */
1397  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : enabling address\n",
1398  (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
1399  address->active = GNUNET_YES;
1400  address->assigned_bw_in = mlp_bw_in;
1401  mlpi->b_in = mlp_bw_in;
1402  address->assigned_bw_out = mlp_bw_out;
1403  mlpi->b_out = mlp_bw_out;
1404  if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer, mlp->exclude_peer)))
1405  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
1406  return GNUNET_OK;
1407  }
1408  else if (GNUNET_YES == address->active)
1409  {
1410  /* Address was used before, check for bandwidth change */
1411  if ((mlp_bw_out != address->assigned_bw_out) ||
1412  (mlp_bw_in != address->assigned_bw_in))
1413  {
1414  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : bandwidth changed\n",
1415  (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
1416  address->assigned_bw_in = mlp_bw_in;
1417  mlpi->b_in = mlp_bw_in;
1418  address->assigned_bw_out = mlp_bw_out;
1419  mlpi->b_out = mlp_bw_out;
1420  if ((NULL == mlp->exclude_peer) || (0 != GNUNET_memcmp (&address->peer, mlp->exclude_peer)))
1421  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
1422  return GNUNET_OK;
1423  }
1424  }
1425  else
1426  GNUNET_break (0);
1427  }
1428  else if (GLP_NO == mlp_use)
1429  {
1430  /* This address was selected by the solver to be not used */
1431  mlpi->n = GNUNET_NO;
1432  if (GNUNET_NO == address->active)
1433  {
1434  /* Address was not used before, nothing to do */
1435  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : no change\n",
1436  (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
1437  return GNUNET_OK;
1438  }
1439  else if (GNUNET_YES == address->active)
1440  {
1441  /* Address was used before, disabling address */
1442  LOG (GNUNET_ERROR_TYPE_DEBUG, "%s %.2f : disabling address\n",
1443  (1 == mlp_use) ? "[x]": "[ ]", mlp_bw_out);
1444  address->active = GNUNET_NO;
1445  /* Set bandwidth to 0 */
1446  address->assigned_bw_in = 0;
1447  mlpi->b_in = 0;
1448  address->assigned_bw_out = 0;
1449  mlpi->b_out = 0;
1450  return GNUNET_OK;
1451  }
1452  else
1453  GNUNET_break (0);
1454  }
1455  else
1456  GNUNET_break (0);
1457 
1458  return GNUNET_OK;
1459 }
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:80
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 1463 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().

1467 {
1468  mlp->env->info_cb (mlp->env->cls,
1469  op,
1470  stat,
1471  add);
1472 }
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:139
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 1476 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().

1477 {
1478  struct GAS_MLP_Handle *mlp = info;
1479  double mlp_obj = 0;
1480 
1481  switch (glp_ios_reason (tree))
1482  {
1483  case GLP_ISELECT:
1484  /* Do nothing here */
1485  break;
1486  case GLP_IPREPRO:
1487  /* Do nothing here */
1488  break;
1489  case GLP_IROWGEN:
1490  /* Do nothing here */
1491  break;
1492  case GLP_IHEUR:
1493  /* Do nothing here */
1494  break;
1495  case GLP_ICUTGEN:
1496  /* Do nothing here */
1497  break;
1498  case GLP_IBRANCH:
1499  /* Do nothing here */
1500  break;
1501  case GLP_IBINGO:
1502  /* A better solution was found */
1503  mlp->ps.mlp_gap = glp_ios_mip_gap (tree);
1504  mlp_obj = glp_mip_obj_val (mlp->p.prob);
1505  mlp->ps.lp_mlp_gap = (abs(mlp_obj - mlp->ps.lp_objective_value)) / (abs(mlp_obj) + DBL_EPSILON);
1506 
1508  "Found better integer solution, current gaps: %.3f <= %.3f, %.3f <= %.3f\n",
1509  mlp->ps.mlp_gap, mlp->pv.mip_gap,
1510  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1511 
1512  if (mlp->ps.mlp_gap <= mlp->pv.mip_gap)
1513  {
1515  "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n",
1516  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1517  glp_ios_terminate (tree);
1518  }
1519 
1520  if (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap)
1521  {
1523  "Current LP/MLP gap of %.3f smaller than tolerated gap of %.3f, terminating search\n",
1524  mlp->ps.lp_mlp_gap, mlp->pv.lp_mip_gap);
1525  glp_ios_terminate (tree);
1526  }
1527 
1528  break;
1529  default:
1530  break;
1531  }
1532  //GNUNET_break (0);
1533 }
glp_prob * prob
GLPK (MLP) problem object.
struct MLP_Variables pv
Encapsulation for the MLP problem variables.
double lp_mlp_gap
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 1543 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().

1544 {
1545  struct GAS_MLP_Handle *mlp = solver;
1546  char *filename;
1547  int res_lp = 0;
1548  int mip_res = 0;
1549  int mip_status = 0;
1550 
1551  struct GNUNET_TIME_Absolute start_total;
1552  struct GNUNET_TIME_Absolute start_cur_op;
1553  struct GNUNET_TIME_Relative dur_total;
1554  struct GNUNET_TIME_Relative dur_setup;
1555  struct GNUNET_TIME_Relative dur_lp;
1556  struct GNUNET_TIME_Relative dur_mlp;
1557 
1558  GNUNET_assert(NULL != solver);
1559  dur_lp = GNUNET_TIME_UNIT_ZERO;
1560 
1561  if (GNUNET_YES == mlp->stat_bulk_lock)
1562  {
1563  mlp->stat_bulk_requests++;
1564  return GNUNET_NO;
1565  }
1568  start_total = GNUNET_TIME_absolute_get();
1569 
1571  {
1573  return GNUNET_OK; /* No pending requests */
1574  }
1576  {
1578  return GNUNET_OK; /* No addresses available */
1579  }
1580 
1581  if ((GNUNET_NO == mlp->stat_mlp_prob_changed)
1582  && (GNUNET_NO == mlp->stat_mlp_prob_updated))
1583  {
1584  LOG(GNUNET_ERROR_TYPE_DEBUG, "No changes to problem\n");
1586  return GNUNET_OK;
1587  }
1588  if (GNUNET_YES == mlp->stat_mlp_prob_changed)
1589  {
1590  LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem size changed, rebuilding\n");
1592  mlp_delete_problem (mlp);
1593  if (GNUNET_SYSERR == mlp_create_problem (mlp))
1594  {
1596  return GNUNET_SYSERR;
1597  }
1599  if (GNUNET_NO == mlp->opt_dbg_intopt_presolver)
1600  {
1601  mlp->control_param_lp.presolve = GLP_YES; /* LP presolver, we need lp solution */
1602  mlp->control_param_mlp.presolve = GNUNET_NO; /* No presolver, we have LP solution */
1603  }
1604  else
1605  {
1606  mlp->control_param_lp.presolve = GNUNET_NO; /* LP presolver, we need lp solution */
1607  mlp->control_param_mlp.presolve = GLP_YES; /* No presolver, we have LP solution */
1608  dur_lp = GNUNET_TIME_UNIT_ZERO;
1609  }
1610  }
1611  else
1612  {
1613  LOG(GNUNET_ERROR_TYPE_DEBUG, "Problem was updated, resolving\n");
1614  }
1615 
1616  /* Reset solution info */
1617  mlp->ps.lp_objective_value = 0.0;
1618  mlp->ps.mlp_gap = 1.0;
1619  mlp->ps.mlp_objective_value = 0.0;
1620  mlp->ps.lp_mlp_gap = 0.0;
1621 
1622  dur_setup = GNUNET_TIME_absolute_get_duration (start_total);
1623 
1624  /* Run LP solver */
1625  if (GNUNET_NO == mlp->opt_dbg_intopt_presolver)
1626  {
1630  "Running LP solver %s\n",
1631  (GLP_YES == mlp->control_param_lp.presolve)? "with presolver": "without presolver");
1632  start_cur_op = GNUNET_TIME_absolute_get();
1633 
1634  /* Solve LP */
1635  /* Only for debugging:
1636  * Always use LP presolver:
1637  * mlp->control_param_lp.presolve = GLP_YES; */
1638  res_lp = mlp_solve_lp_problem(mlp);
1639  if (GNUNET_OK == res_lp)
1640  {
1641  mlp->ps.lp_objective_value = glp_get_obj_val (mlp->p.prob);
1643  "LP solution was: %.3f\n",
1644  mlp->ps.lp_objective_value);
1645  }
1646 
1647  dur_lp = GNUNET_TIME_absolute_get_duration (start_cur_op);
1649  (GNUNET_OK == res_lp) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1651  }
1652 
1654  res_lp = GNUNET_OK;
1655 
1656  /* Run MLP solver */
1657  if ((GNUNET_OK == res_lp) || (GNUNET_YES == mlp->opt_dbg_intopt_presolver))
1658  {
1659  LOG(GNUNET_ERROR_TYPE_DEBUG, "Running MLP solver \n");
1662  start_cur_op = GNUNET_TIME_absolute_get();
1663 
1664  /* Solve MIP */
1665 
1666  /* Only for debugging, always use LP presolver */
1668  mlp->control_param_mlp.presolve = GNUNET_YES;
1669 
1670  mip_res = glp_intopt (mlp->p.prob, &mlp->control_param_mlp);
1671  switch (mip_res)
1672  {
1673  case 0:
1674  /* Successful */
1676  "Solving MLP problem: %s\n",
1677  mlp_solve_to_string (mip_res));
1678  break;
1679  case GLP_ETMLIM: /* Time limit reached */
1680  case GLP_EMIPGAP: /* MIP gap tolerance limit reached */
1681  case GLP_ESTOP: /* Solver was instructed to stop*/
1682  /* Semi-successful */
1684  "Solving MLP problem solution was interupted: %s\n",
1685  mlp_solve_to_string (mip_res));
1686  break;
1687  case GLP_EBOUND:
1688  case GLP_EROOT:
1689  case GLP_ENOPFS:
1690  case GLP_ENODFS:
1691  case GLP_EFAIL:
1692  default:
1693  /* Fail */
1695  "Solving MLP problem failed: %s\n",
1696  mlp_solve_to_string (mip_res));
1697  break;
1698  }
1699 
1700  /* Analyze problem status */
1701  mip_status = glp_mip_status(mlp->p.prob);
1702  switch (mip_status)
1703  {
1704  case GLP_OPT: /* solution is optimal */
1706  "Solution of MLP problem is optimal: %s, %s\n",
1707  mlp_solve_to_string (mip_res),
1708  mlp_status_to_string (mip_status));
1709  mip_res = GNUNET_OK;
1710  break;
1711  case GLP_FEAS: /* solution is feasible but not proven optimal */
1712 
1713  if ( (mlp->ps.mlp_gap <= mlp->pv.mip_gap) ||
1714  (mlp->ps.lp_mlp_gap <= mlp->pv.lp_mip_gap) )
1715  {
1717  "Solution of MLP problem is feasible and solution within gap constraints: %s, %s\n",
1718  mlp_solve_to_string (mip_res),
1719  mlp_status_to_string (mip_status));
1720  mip_res = GNUNET_OK;
1721  }
1722  else
1723  {
1725  "Solution of MLP problem is feasible but solution not within gap constraints: %s, %s\n",
1726  mlp_solve_to_string (mip_res),
1727  mlp_status_to_string (mip_status));
1728  mip_res = GNUNET_SYSERR;
1729  }
1730  break;
1731  case GLP_UNDEF: /* Solution undefined */
1732  case GLP_NOFEAS: /* No feasible solution */
1733  default:
1735  "Solving MLP problem failed: %s %s\n",
1736  mlp_solve_to_string (mip_res),
1737  mlp_status_to_string (mip_status));
1738  mip_res = GNUNET_SYSERR;
1739  break;
1740  }
1741 
1742  dur_mlp = GNUNET_TIME_absolute_get_duration (start_cur_op);
1743  dur_total = GNUNET_TIME_absolute_get_duration (start_total);
1744 
1746  (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1748  }
1749  else
1750  {
1751  /* Do not execute mip solver since lp solution is invalid */
1752  dur_mlp = GNUNET_TIME_UNIT_ZERO;
1753  dur_total = GNUNET_TIME_absolute_get_duration (start_total);
1754 
1757  mip_res = GNUNET_SYSERR;
1758  }
1759 
1760  /* Notify about end */
1762  ((GNUNET_OK == mip_res) && (GNUNET_OK == mip_res)) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1764 
1766  "Execution time for %s solve: (total/setup/lp/mlp) : %llu %llu %llu %llu\n",
1767  (GNUNET_YES == mlp->stat_mlp_prob_changed) ? "full" : "updated",
1768  (unsigned long long) dur_total.rel_value_us,
1769  (unsigned long long) dur_setup.rel_value_us,
1770  (unsigned long long) dur_lp.rel_value_us,
1771  (unsigned long long) dur_mlp.rel_value_us);
1772 
1773  /* Save stats */
1774  mlp->ps.lp_res = res_lp;
1775  mlp->ps.mip_res = mip_res;
1776  mlp->ps.lp_presolv = mlp->control_param_lp.presolve;
1777  mlp->ps.mip_presolv = mlp->control_param_mlp.presolve;
1778  mlp->ps.p_cols = glp_get_num_cols(mlp->p.prob);
1779  mlp->ps.p_rows = glp_get_num_rows(mlp->p.prob);
1780  mlp->ps.p_elements = mlp->p.num_elements;
1781 
1782  /* Propagate result*/
1784  (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1785  GAS_INFO_NONE);
1786  if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res))
1787  {
1789  &mlp_propagate_results, mlp);
1790  }
1792  (GNUNET_OK == res_lp) && (GNUNET_OK == mip_res) ? GAS_STAT_SUCCESS : GAS_STAT_FAIL,
1793  GAS_INFO_NONE);
1794 
1796  if ( (GNUNET_YES == mlp->opt_dump_problem_all) ||
1797  (mlp->opt_dump_problem_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != mip_res))) )
1798  {
1799  /* Write problem to disk */
1800  switch (mlp->opt_log_format) {
1801  case MLP_CPLEX:
1802  GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.cplex", mlp->p.num_peers,
1803  mlp->p.num_addresses, time.abs_value_us);
1804  glp_write_lp (mlp->p.prob, NULL, filename);
1805  break;
1806  case MLP_GLPK:
1807  GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.glpk", mlp->p.num_peers,
1808  mlp->p.num_addresses, time.abs_value_us);
1809  glp_write_prob (mlp->p.prob, 0, filename);
1810  break;
1811  case MLP_MPS:
1812  GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.mps", mlp->p.num_peers,
1813  mlp->p.num_addresses, time.abs_value_us);
1814  glp_write_mps (mlp->p.prob, GLP_MPS_FILE, NULL, filename);
1815  break;
1816  default:
1817  break;
1818  }
1819  LOG(GNUNET_ERROR_TYPE_ERROR, "Dumped problem to file: `%s' \n", filename);
1820  GNUNET_free(filename);
1821  }
1822  if ( (mlp->opt_dump_solution_all) ||
1823  (mlp->opt_dump_solution_on_fail && ((GNUNET_OK != res_lp) || (GNUNET_OK != mip_res))) )
1824  {
1825  /* Write solution to disk */
1826  GNUNET_asprintf(&filename, "problem_p_%u_a%u_%llu.sol", mlp->p.num_peers,
1827  mlp->p.num_addresses, time.abs_value_us);
1828  glp_print_mip(mlp->p.prob, filename);
1829  LOG(GNUNET_ERROR_TYPE_ERROR, "Dumped solution to file: `%s' \n", filename);
1830  GNUNET_free(filename);
1831  }
1832 
1833  /* Reset change and update marker */
1834  mlp->control_param_lp.presolve = GLP_NO;
1837 
1838  if ((GNUNET_OK == res_lp) && (GNUNET_OK == mip_res))
1839  return GNUNET_OK;
1840  else
1841  return GNUNET_SYSERR;
1842 }
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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.
double lp_mlp_gap
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:79
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:80
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 1852 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().

1855 {
1856  struct GAS_MLP_Handle *mlp = solver;
1857 
1858  if (GNUNET_NT_COUNT <= network)
1859  {
1860  GNUNET_break (0);
1861  return;
1862  }
1863 
1864  if (NULL == address->solver_information)
1865  {
1866  address->solver_information = GNUNET_new (struct MLP_information);
1867  }
1868  else
1870  _("Adding address for peer `%s' multiple times\n"),
1871  GNUNET_i2s(&address->peer));
1872 
1873  /* Is this peer included in the problem? */
1874  if (NULL ==
1876  &address->peer))
1877  {
1878  /* FIXME: should this be an error? */
1880  "Adding address for peer `%s' without address request\n",
1881  GNUNET_i2s(&address->peer));
1882  return;
1883  }
1884 
1886  "Adding address for peer `%s' with address request \n",
1887  GNUNET_i2s(&address->peer));
1888  /* Problem size changed: new address for peer with pending request */
1890  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
1891  GAS_mlp_solve_problem (solver);
1892 }
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:208
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:80
#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 1902 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().

1904 {
1905  struct MLP_information *mlpi = address->solver_information;
1906  struct GAS_MLP_Handle *mlp = solver;
1907 
1908  if (NULL == mlp->p.prob)
1909  return; /* There is no MLP problem to update yet */
1910 
1911  if (NULL == mlpi)
1912  {
1914  _("Updating address property for peer `%s' %p not added before\n"),
1915  GNUNET_i2s (&address->peer),
1916  address);
1917  GNUNET_break (0);
1918  return;
1919  }
1920  if (NULL ==
1922  &address->peer))
1923  {
1924  /* Peer is not requested, so no need to update problem */
1925  return;
1926  }
1928  "Updating properties for peer `%s'\n",
1929  GNUNET_i2s(&address->peer));
1930 
1932  return;
1933 
1934  /* Update c7) [r_q[index]][c_b] = f_q * q_averaged[type_index] */
1935  if ( (GNUNET_YES ==
1938  mlpi->c_b,
1939  address->norm_delay.norm,
1940  __LINE__)) ||
1941  (GNUNET_YES ==
1944  mlpi->c_b,
1945  address->norm_distance.norm,
1946  __LINE__)) )
1947  {
1949  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
1950  GAS_mlp_solve_problem (solver);
1951  }
1952 
1953 }
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:208
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:80
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 1964 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().

1967 {
1968  static int counter = 0;
1969  struct ATS_Address **aa = cls;
1970  struct ATS_Address *addr = value;
1971  struct MLP_information *mlpi = addr->solver_information;
1972 
1973  if (mlpi == NULL)
1974  return GNUNET_YES;
1975 
1976  /*
1977  * Debug output
1978  * GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1979  * "MLP [%u] Peer `%s' %s length %u session %u active %s mlp active %s\n",
1980  * counter, GNUNET_i2s (&addr->peer), addr->plugin, addr->addr_len, addr->session_id,
1981  * (GNUNET_YES == addr->active) ? "active" : "inactive",
1982  * (GNUNET_YES == mlpi->n) ? "active" : "inactive");
1983  */
1984 
1985  if (GNUNET_YES == mlpi->n)
1986  {
1987 
1988  (*aa) = addr;
1989  (*aa)->assigned_bw_in = mlpi->b_in;
1990  (*aa)->assigned_bw_out = mlpi->b_out;
1991  return GNUNET_NO;
1992  }
1993  counter++;
1994  return GNUNET_YES;
1995 }
uint32_t b_in
Bandwidth assigned inbound.
const void * addr
Address (in plugin-specific binary format).
#define GNUNET_NO
Definition: gnunet_common.h:81
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:80
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 1999 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().

2001 {
2002  double res;
2003  const double *preferences;
2004  int c;
2005 
2006  preferences = mlp->env->get_preferences (mlp->env->cls, peer);
2007  res = 0.0;
2008  for (c = 0; c < GNUNET_ATS_PREFERENCE_END; c++)
2009  {
2010  /* fprintf (stderr, "VALUE[%u] %s %.3f \n",
2011  * c, GNUNET_i2s (&cur->addr->peer), t[c]); */
2012  res += preferences[c];
2013  }
2014 
2016  res += 1.0;
2017 
2019  "Peer preference for peer `%s' == %.2f\n",
2020  GNUNET_i2s(peer), res);
2021 
2022  return res;
2023 }
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 2033 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().

2035 {
2036  struct GAS_MLP_Handle *mlp = solver;
2037  struct ATS_Peer *p;
2038  struct ATS_Address *res;
2039 
2041  "Getting preferred address for `%s'\n",
2042  GNUNET_i2s (peer));
2043 
2044  /* Is this peer included in the problem? */
2045  if (NULL ==
2047  peer))
2048  {
2049  LOG (GNUNET_ERROR_TYPE_INFO, "Adding peer `%s' to list of requested_peers with requests\n",
2050  GNUNET_i2s (peer));
2051 
2052  p = GNUNET_new (struct ATS_Peer);
2053  p->id = (*peer);
2054  p->f = get_peer_pref_value (mlp, peer);
2056  peer, p,
2058 
2059  /* Added new peer, we have to rebuild problem before solving */
2061 
2062  if ((GNUNET_YES == mlp->opt_mlp_auto_solve)&&
2064  peer)))
2065  {
2066  mlp->exclude_peer = peer;
2067  GAS_mlp_solve_problem (mlp);
2068  mlp->exclude_peer = NULL;
2069  }
2070  }
2071  /* Get prefered address */
2072  res = NULL;
2075  if (NULL != res)
2076  mlp->env->bandwidth_changed_cb (mlp->env->cls,
2077  res);
2078 }
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:80
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 2090 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().

2092 {
2093  struct GAS_MLP_Handle *mlp = solver;
2094  struct MLP_information *mlpi;
2095  struct ATS_Address *res;
2096  int was_active;
2097 
2098  mlpi = address->solver_information;
2099  if (NULL != mlpi)
2100  {
2101  /* Remove full address */
2102  GNUNET_free (mlpi);
2103  address->solver_information = NULL;
2104  }
2105  was_active = address->active;
2106  address->active = GNUNET_NO;
2107  address->assigned_bw_in = 0;
2108  address->assigned_bw_out = 0;
2109 
2110  /* Is this peer included in the problem? */
2111  if (NULL ==
2113  &address->peer))
2114  {
2116  "Deleting address for peer `%s' without address request \n",
2117  GNUNET_i2s(&address->peer));
2118  return;
2119  }
2121  "Deleting address for peer `%s' with address request \n",
2122  GNUNET_i2s (&address->peer));
2123 
2124  /* Problem size changed: new address for peer with pending request */
2126  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2127  {
2128  GAS_mlp_solve_problem (solver);
2129  }
2130  if (GNUNET_YES == was_active)
2131  {
2132  GAS_mlp_get_preferred_address (solver, &address->peer);
2133  res = NULL;
2135  &address->peer,
2137  &res);
2138  if (NULL == res)
2139  {
2140  /* No alternative address, disconnecting peer */
2141  mlp->env->bandwidth_changed_cb (mlp->env->cls, address);
2142  }
2143  }
2144 }
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:81
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:80
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 2153 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().

2154 {
2155  struct GAS_MLP_Handle *s = solver;
2156 
2158  "Locking solver for bulk operation ...\n");
2159  GNUNET_assert (NULL != solver);
2160  s->stat_bulk_lock ++;
2161 }
#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 2165 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().

2166 {
2167  struct GAS_MLP_Handle *s = solver;
2168 
2170  "Unlocking solver from bulk operation ...\n");
2171  GNUNET_assert (NULL != solver);
2172 
2173  if (s->stat_bulk_lock < 1)
2174  {
2175  GNUNET_break (0);
2176  return;
2177  }
2178  s->stat_bulk_lock --;
2179 
2180  if (0 < s->stat_bulk_requests)
2181  {
2182  GAS_mlp_solve_problem (solver);
2183  s->stat_bulk_requests= 0;
2184  }
2185 }
#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 2196 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().

2198 {
2199  struct GAS_MLP_Handle *mlp = solver;
2200  struct ATS_Peer *p = NULL;
2201 
2202  GNUNET_assert (NULL != solver);
2203  GNUNET_assert (NULL != peer);
2204  if (NULL != (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, peer)))
2205  {
2208  GNUNET_free (p);
2209 
2211  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2212  {
2213  GAS_mlp_solve_problem (solver);
2214  }
2215  }
2216 }
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:80
#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 2228 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().

2232 {
2233  struct GAS_MLP_Handle *mlp = solver;
2234  struct ATS_Peer *p;
2235 
2237  "Changing preference for address for peer `%s' to %.2f\n",
2238  GNUNET_i2s(peer),
2239  pref_rel);
2240 
2242  "# LP address preference changes", 1, GNUNET_NO);
2243  /* Update the constraints with changed preferences */
2244 
2245 
2246 
2247  /* Update relativity constraint c9 */
2248  if (NULL == (p = GNUNET_CONTAINER_multipeermap_get (mlp->requested_peers, peer)))
2249  {
2251  "Updating preference for unknown peer `%s'\n",
2252  GNUNET_i2s(peer));
2253  return;
2254  }
2255 
2256  if (GNUNET_NO == mlp->opt_dbg_feasibility_only)
2257  {
2258  p->f = get_peer_pref_value (mlp, peer);
2260  p->r_c9,
2261  mlp->p.c_r,
2262  - p->f,
2263  __LINE__);
2264 
2265  /* Problem size changed: new address for peer with pending request */
2267  if (GNUNET_YES == mlp->opt_mlp_auto_solve)
2268  GAS_mlp_solve_problem (solver);
2269  }
2270 }
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:81
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:80
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 2284 of file plugin_ats_mlp.c.

References GNUNET_assert.

Referenced by libgnunet_plugin_ats_mlp_init().

2290 {
2291  struct GAS_PROPORTIONAL_Handle *s = solver;
2292 
2293  GNUNET_assert (NULL != solver);
2294  GNUNET_assert (NULL != peer);
2295  GNUNET_assert (NULL != s);
2296 }
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 2300 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().

2302 {
2303  struct GNUNET_CONTAINER_MultiPeerMap *map = cls;
2304  struct ATS_Peer *p = value;
2305 
2308  GNUNET_free (p);
2309 
2310  return GNUNET_OK;
2311 }
#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:78
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:80
#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 2321 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.

2322 {
2323  struct GNUNET_ATS_SolverFunctions *sf = cls;
2324  struct GAS_MLP_Handle *mlp = sf->cls;
2325 
2327  "Shutting down mlp solver\n");
2328  mlp_delete_problem (mlp);
2330  &mlp_free_peers,
2331  mlp->requested_peers);
2333  mlp->requested_peers = NULL;
2334 
2335  /* Clean up GLPK environment */
2336  glp_free_env();
2337  GNUNET_free (mlp);
2338 
2340  "Shutdown down of mlp solver complete\n");
2341  return NULL;
2342 }
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 2346 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.

2347 {
2348  static struct GNUNET_ATS_SolverFunctions sf;
2350  struct GAS_MLP_Handle * mlp = GNUNET_new (struct GAS_MLP_Handle);
2351  float f_tmp;
2352  unsigned long long tmp;
2353  unsigned int b_min;
2354  unsigned int n_min;
2355  int c;
2356  char *outputformat;
2357 
2358  struct GNUNET_TIME_Relative max_duration;
2359  long long unsigned int max_iterations;
2360 
2361  /* Init GLPK environment */
2362  int res = glp_init_env();
2363  switch (res) {
2364  case 0:
2365  LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
2366  "initialization successful");
2367  break;
2368  case 1:
2369  LOG (GNUNET_ERROR_TYPE_DEBUG, "GLPK: `%s'\n",
2370  "environment is already initialized");
2371  break;
2372  case 2:
2373  LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
2374  "initialization failed (insufficient memory)");
2375  GNUNET_free(mlp);
2376  return NULL;
2377  break;
2378  case 3:
2379  LOG (GNUNET_ERROR_TYPE_ERROR, "Could not init GLPK: `%s'\n",
2380  "initialization failed (unsupported programming model)");
2381  GNUNET_free(mlp);
2382  return NULL;
2383  break;
2384  default:
2385  break;
2386  }
2387 
2389  "ats", "MLP_DUMP_PROBLEM_ALL");
2390  if (GNUNET_SYSERR == mlp->opt_dump_problem_all)
2392 
2394  "ats", "MLP_DUMP_SOLUTION_ALL");
2397 
2399  "ats", "MLP_DUMP_PROBLEM_ON_FAIL");
2402 
2404  "ats", "MLP_DUMP_SOLUTION_ON_FAIL");
2407 
2409  "ats", "MLP_DBG_GLPK_VERBOSE");
2410  if (GNUNET_SYSERR == mlp->opt_dbg_glpk_verbose)
2412 
2414  "ats", "MLP_DBG_FEASIBILITY_ONLY");
2419  "MLP solver is configured to check feasibility only!\n");
2420 
2422  "ats", "MLP_DBG_AUTOSCALE_PROBLEM");
2427  "MLP solver is configured automatically scale the problem!\n");
2428 
2430  "ats", "MLP_DBG_INTOPT_PRESOLVE");
2435  "MLP solver is configured use the mlp presolver\n");
2436 
2438  "ats", "MLP_DBG_OPTIMIZE_DIVERSITY");
2443  "MLP solver is not optimizing for diversity\n");
2444 
2446  "ats", "MLP_DBG_OPTIMIZE_RELATIVITY");
2451  "MLP solver is not optimizing for relativity\n");
2452 
2454  "ats", "MLP_DBG_OPTIMIZE_QUALITY");
2457  if (GNUNET_NO == mlp->opt_dbg_optimize_quality)
2459  "MLP solver is not optimizing for quality\n");
2460 
2462  "ats", "MLP_DBG_OPTIMIZE_UTILITY");
2465  if (GNUNET_NO == mlp->opt_dbg_optimize_utility)
2467  "MLP solver is not optimizing for utility\n");
2468 
2469  if ( (GNUNET_NO == mlp->opt_dbg_optimize_utility) &&
2470  (GNUNET_NO == mlp->opt_dbg_optimize_quality) &&
2472  (GNUNET_NO == mlp->opt_dbg_optimize_utility) &&
2474  {
2476  _("MLP solver is not optimizing for anything, changing to feasibility check\n"));
2478  }
2479 
2481  "ats", "MLP_LOG_FORMAT", &outputformat))
2482  mlp->opt_log_format = MLP_CPLEX;
2483  else
2484  {
2485  GNUNET_STRINGS_utf8_toupper(outputformat, outputformat);
2486  if (0 == strcmp (outputformat, "MPS"))
2487  {
2488  mlp->opt_log_format = MLP_MPS;
2489  }
2490  else if (0 == strcmp (outputformat, "CPLEX"))
2491  {
2492  mlp->opt_log_format = MLP_CPLEX;
2493  }
2494  else if (0 == strcmp (outputformat, "GLPK"))
2495  {
2496  mlp->opt_log_format = MLP_GLPK;
2497  }
2498  else
2499  {
2501  "Invalid log format `%s' in configuration, using CPLEX!\n",
2502  outputformat);
2503  mlp->opt_log_format = MLP_CPLEX;
2504  }
2505  GNUNET_free (outputformat);
2506  }
2507 
2508  mlp->pv.BIG_M = (double) BIG_M_VALUE;
2509 
2510  mlp->pv.mip_gap = (double) 0.0;
2512  "MLP_MAX_MIP_GAP", &f_tmp))
2513  {
2514  if ((f_tmp < 0.0) || (f_tmp > 1.0))
2515  {
2516  LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid %s configuration %f \n"),
2517  "MIP gap", f_tmp);
2518  }
2519  else
2520  {
2521  mlp->pv.mip_gap = f_tmp;
2522  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s of %.3f\n",
2523  "MIP gap", f_tmp);
2524  }
2525  }
2526 
2527  mlp->pv.lp_mip_gap = (double) 0.0;
2529  "MLP_MAX_LP_MIP_GAP", &f_tmp))
2530  {
2531  if ((f_tmp < 0.0) || (f_tmp > 1.0))
2532  {
2533  LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid %s configuration %f \n"),
2534  "LP/MIP", f_tmp);
2535  }
2536  else
2537  {
2538  mlp->pv.lp_mip_gap = f_tmp;
2539  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2540  "LP/MIP", f_tmp);
2541  }
2542  }
2543 
2544  /* Get timeout for iterations */
2546  "MLP_MAX_DURATION", &max_duration))
2547  {
2548  max_duration = MLP_MAX_EXEC_DURATION;
2549  }
2550 
2551  /* Get maximum number of iterations */
2553  "MLP_MAX_ITERATIONS", &max_iterations))
2554  {
2555  max_iterations = MLP_MAX_ITERATIONS;
2556  }
2557 
2558  /* Get diversity coefficient from configuration */
2559  mlp->pv.co_D = MLP_DEFAULT_D;
2561  "MLP_COEFFICIENT_D", &f_tmp))
2562  {
2563  if ((f_tmp < 0.0))
2564  {
2565  LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid %s configuration %f \n"),
2566  "MLP_COEFFICIENT_D", f_tmp);
2567  }
2568  else
2569  {
2570  mlp->pv.co_D = f_tmp;
2571  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2572  "MLP_COEFFICIENT_D", f_tmp);
2573  }
2574  }
2575 
2576  /* Get relativity coefficient from configuration */
2577  mlp->pv.co_R = MLP_DEFAULT_R;
2579  "MLP_COEFFICIENT_R", &f_tmp))
2580  {
2581  if ((f_tmp < 0.0))
2582  {
2583  LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid %s configuration %f \n"),
2584  "MLP_COEFFICIENT_R", f_tmp);
2585  }
2586  else
2587  {
2588  mlp->pv.co_R = f_tmp;
2589  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2590  "MLP_COEFFICIENT_R", f_tmp);
2591  }
2592  }
2593 
2594 
2595  /* Get utilization coefficient from configuration */
2596  mlp->pv.co_U = MLP_DEFAULT_U;
2598  "MLP_COEFFICIENT_U", &f_tmp))
2599  {
2600  if ((f_tmp < 0.0))
2601  {
2602  LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid %s configuration %f \n"),
2603  "MLP_COEFFICIENT_U", f_tmp);
2604  }
2605  else
2606  {
2607  mlp->pv.co_U = f_tmp;
2608  LOG (GNUNET_ERROR_TYPE_INFO, "Using %s gap of %.3f\n",
2609  "MLP_COEFFICIENT_U", f_tmp);
2610  }
2611  }
2612 
2613  /* Get quality metric coefficients from configuration */
2614  for (c = 0; c < RQ_QUALITY_METRIC_COUNT; c++)
2615  {
2616  /* initialize quality coefficients with default value 1.0 */
2617  mlp->pv.co_Q[c] = MLP_DEFAULT_QUALITY;
2618  }
2619 
2620 
2621  if (GNUNET_OK ==
2623  "MLP_COEFFICIENT_QUALITY_DELAY",
2624  &tmp))
2625  mlp->pv.co_Q[RQ_QUALITY_METRIC_DELAY] = (double) tmp / 100;
2626  else
2628 
2629  if (GNUNET_OK ==
2631  "MLP_COEFFICIENT_QUALITY_DISTANCE",
2632  &tmp))
2633  mlp->pv.co_Q[RQ_QUALITY_METRIC_DISTANCE] = (double) tmp / 100;
2634  else
2636 
2637  /* Get minimum bandwidth per used address from configuration */
2639  "MLP_MIN_BANDWIDTH",
2640  &tmp))
2641  b_min = tmp;
2642  else
2643  {
2644  b_min = ntohl (GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT.value__);
2645  }
2646 
2647  /* Get minimum number of connections from configuration */
2649  "MLP_MIN_CONNECTIONS",
2650  &tmp))
2651  n_min = tmp;
2652  else
2654 
2655  /* Init network quotas */
2656  for (c = 0; c < GNUNET_NT_COUNT; c++)
2657  {
2658  mlp->pv.quota_index[c] = c;
2659  mlp->pv.quota_out[c] = env->out_quota[c];
2660  mlp->pv.quota_in[c] = env->in_quota[c];
2661 
2663  "Quota for network `%s' (in/out) %llu/%llu\n",
2664  GNUNET_NT_to_string (c),
2665  mlp->pv.quota_out[c],
2666  mlp->pv.quota_in[c]);
2667  /* Check if defined quota could make problem unsolvable */
2668  if ((n_min * b_min) > mlp->pv.quota_out[c])
2669  {
2671  _("Adjusting inconsistent outbound quota configuration for network `%s', is %llu must be at least %llu\n"),
2673  mlp->pv.quota_out[c],
2674  (n_min * b_min));
2675  mlp->pv.quota_out[c] = (n_min * b_min);
2676  }
2677  if ((n_min * b_min) > mlp->pv.quota_in[c])
2678  {
2680  _("Adjusting inconsistent inbound quota configuration for network `%s', is %llu must be at least %llu\n"),
2682  mlp->pv.quota_in[c],
2683  (n_min * b_min));
2684  mlp->pv.quota_in[c] = (n_min * b_min);
2685  }
2686  /* Check if bandwidth is too big to make problem solvable */
2687  if (mlp->pv.BIG_M < mlp->pv.quota_out[c])
2688  {
2690  _("Adjusting outbound quota configuration for network `%s'from %llu to %.0f\n"),
2692  mlp->pv.quota_out[c],
2693  mlp->pv.BIG_M);
2694  mlp->pv.quota_out[c] = mlp->pv.BIG_M ;
2695  }
2696  if (mlp->pv.BIG_M < mlp->pv.quota_in[c])
2697  {
2699  _("Adjusting inbound quota configuration for network `%s' from %llu to %.0f\n"),
2701  mlp->pv.quota_in[c],
2702  mlp->pv.BIG_M);
2703  mlp->pv.quota_in[c] = mlp->pv.BIG_M ;
2704  }
2705  }
2706  mlp->env = env;
2707  sf.cls = mlp;
2717 
2718  /* Setting MLP Input variables */
2719  mlp->pv.b_min = b_min;
2720  mlp->pv.n_min = n_min;
2726  mlp->stat_bulk_requests = 0;
2727  mlp->stat_bulk_lock = 0;
2728 
2729  /* Setup GLPK */
2730  /* Redirect GLPK output to GNUnet logging */
2731  glp_term_hook (&mlp_term_hook, (void *) mlp);
2732 
2733  /* Init LP solving parameters */
2734  glp_init_smcp(&mlp->control_param_lp);
2735  mlp->control_param_lp.msg_lev = GLP_MSG_OFF;
2736  if (GNUNET_YES == mlp->opt_dbg_glpk_verbose)
2737  mlp->control_param_lp.msg_lev = GLP_MSG_ALL;
2738 
2739  mlp->control_param_lp.it_lim = max_iterations;
2740  mlp->control_param_lp.tm_lim = max_duration.rel_value_us / 1000LL;
2741 
2742  /* Init MLP solving parameters */
2743  glp_init_iocp(&mlp->control_param_mlp);
2744  /* Setting callback function */
2745  mlp->control_param_mlp.cb_func = &mlp_branch_and_cut_cb;
2746  mlp->control_param_mlp.cb_info = mlp;
2747  mlp->control_param_mlp.msg_lev = GLP_MSG_OFF;
2748  mlp->control_param_mlp.mip_gap = mlp->pv.mip_gap;
2749  if (GNUNET_YES == mlp->opt_dbg_glpk_verbose)
2750  mlp->control_param_mlp.msg_lev = GLP_MSG_ALL;
2751  mlp->control_param_mlp.tm_lim = max_duration.rel_value_us / 1000LL;
2752 
2753  LOG (GNUNET_ERROR_TYPE_DEBUG, "solver ready\n");
2754 
2755  return &sf;
2756 }
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:43
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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:208
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:580
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:79
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:80
#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: