File: eps_ind.c

package info (click to toggle)
r-cran-emoa 0.5-3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 588 kB
  • sloc: ansic: 4,033; sh: 13; makefile: 2
file content (99 lines) | stat: -rw-r--r-- 3,940 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*===========================================================================*
 * eps_ind.c: implements the unary epsilon indicator as proposed in
 *            Zitzler, E., Thiele, L., Laumanns, M., Fonseca, C., and
 *            Grunert da Fonseca, V (2003): Performance Assessment of
 *            Multiobjective Optimizers: An Analysis and Review. IEEE
 *            Transactions on Evolutionary Computation, 7(2), 117-132.
 *
 * IMPORTANT:
 *   To make the epsilon indicator work for mixed optimization problems
 *   where some objectives are to be maximized while others are to be
 *   minimized, in the case of minimization the value -epsilon (for the
 *   additive case) resp. 1/epsilon (for the multiplicative version) is
 *   considered and returned. Example: suppose f1 is to be minimized and
 *   f2 to be maximized, and the multiplicative epsilon value computed by
 *   this program is 3.0; this means that the considered nondominated front
 *   needs to be multiplied by 1/3 for all f1 values and by 3 for all
 *   f2 values. Thus, independently of which type of problem one considers
 *   (minimization, maximization, mixed minimization/maximization), a lower
 *   indicator value corresponds to a better approximation set.
 *
 * Author:
 *   Eckart Zitzler, February 3, 2005 / last update August 9, 2005
 *
 * Adapted for use in R by:
 *   Olaf Mersmann <olafm@statistik.tu-dortmund.de>
 */

#include "extern.h"

#include <R.h>
#include <Rmath.h>
#include <Rinternals.h>
#include <R_ext/Applic.h>

typedef enum { additive, multiplicative } method_t;

#define MAX(A, B) ((A > B) ? A : B)
#define MIN(A, B) ((A < B) ? A : B)

/*
 * calc_eps_ind:
 *  a - reference front
 *  b - current front
 */
static double calc_eps_ind(double *a, const size_t a_points, double *b,
                           const size_t b_points,
                           const size_t number_of_objectives, method_t method) {
  size_t i, j, current_objective;
  double maximal_eps, minimal_pointwise_eps, pointwise_eps, eps;

  maximal_eps = (additive == method) ? -DBL_MAX : 0.0;
  for (i = 0; i < a_points; i++) {
    minimal_pointwise_eps = DBL_MAX;
    const double *ai = a + i * number_of_objectives;
    for (j = 0; j < b_points; j++) {
      pointwise_eps = -DBL_MAX;
      const double *bj = b + j * number_of_objectives;
      for (current_objective = 0; current_objective < number_of_objectives;
           ++current_objective) {
        switch (method) {
        case additive:
          eps = bj[current_objective] - ai[current_objective];
          break;
        case multiplicative:
          eps = bj[current_objective] / ai[current_objective];
          break;
        }
        pointwise_eps = MAX(pointwise_eps, eps);
      }
      minimal_pointwise_eps = MIN(minimal_pointwise_eps, pointwise_eps);
    }
    maximal_eps = MAX(maximal_eps, minimal_pointwise_eps);
  }
  return maximal_eps;
}

#define UNPACK_REAL_VECTOR(S, D, N)                                            \
  double *D = REAL(S);                                                         \
  const R_len_t N = length(S);

#define UNPACK_REAL_MATRIX(S, D, N, K)                                         \
  double *D = REAL(S);                                                         \
  const R_len_t N = nrows(S);                                                  \
  const R_len_t K = ncols(S);

SEXP do_eps_ind(SEXP s_data, SEXP s_ref) {
  /* Unpack arguments */
  UNPACK_REAL_MATRIX(s_data, data, number_of_objectives, number_of_points);
  UNPACK_REAL_MATRIX(s_ref, ref, number_of_ref_objectives,
                     number_of_ref_points);

  if (number_of_ref_objectives != number_of_objectives)
    error("Reference and current front must have the same dimension.");

  /* Calculate criterion */
  double res = calc_eps_ind(ref, number_of_ref_points, data, number_of_points,
                            number_of_objectives, additive);
  return ScalarReal(res);
}