Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions r/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# moocore 0.2.0.900

* `generate_ndset()`: New shapes `"inverted-simplex"` and `"concave-simplex"`. Shape `"convex-simplex"` is now equivalent to `generate_ndset(..., method="simplex")^2`, which is slightly more uniform than the previous approach.
* `r2_exact()` implements the exact computation of the R2 indicator for bi-objective solution sets.
* `hypervolume()` is significantly faster for more than four dimensions (Andreia P. Guerreiro).
* `hypervolume()` now handles 1D inputs and provides a clear error for 0D inputs (#58).
Expand Down
49 changes: 35 additions & 14 deletions r/R/generate.R
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,21 @@
#' standard simplex.
#' * `"concave-sphere"`, `"sphere"`, or `"C"`: Uniformly samples points
#' on the positive orthant of the unit hypersphere (concave for minimisation).
#' * `"convex-sphere"` or `"X"`: Equivalent to `1 - generate_ndset(..., method="concave-sphere")`,
#' which is convex for minimisation.
#' * `"convex-simplex"`: Equivalent to `generate_ndset(..., method="concave-sphere")^4`,
#' * `"convex-simplex"`: Equivalent to `generate_ndset(..., method="simplex")^2`,
#' which is convex for minimisation. Such a set cannot be obtained by any
#' affine transformation of a subset of the hyper-sphere.
#' affine transformation of a subset of the hyper-sphere. This sampling is
#' *not* uniform.
#' * `"convex-sphere"` or `"X"`: Equivalent to `1 - generate_ndset(...,
#' method="concave-sphere")`, which is convex for minimisation. This shape
#' has also been called *inverted convex* \citep{IshHeSha2019regular}. This
#' sampling is uniform.
#' * `"inverted-simplex"` or `"inverted-linear"`: Equivalent to `1 -
#' generate_ndset(..., method="simplex")`. This sampling is uniform.
#' * `"concave-simplex"`: Equivalent to `1 - generate_ndset(...,
#' method="convex-simplex")`, which is concave for minimisation. This shape
#' has also been called *inverted concave* \citep{IshHeSha2019regular}. This
#' sampling is *not* uniform because `method="convex-simplex"` is also not
#' uniform.
#'
#' Method `"simplex"` uniformly samples points on the standard
#' \eqn{(d-1)}-simplex defined by \eqn{\{x \in R_+^d : \sum_i x_i = 1\}}. This
Expand All @@ -46,7 +56,7 @@
#'
#' Sampling from either the standard normal distribution
#' \citep{GueFonPaq2021hv} or the uniform distribution \citep{LacKlaFon2017box}
#' does not produce a uniform distribution when projected into the simplex.
#' does not produce a uniform distribution when projected onto the simplex.
#'
#' Method `"concave-sphere"` uniformly samples points on the positive orthant
#' of the hyper-sphere, which is concave when all objectives are minimised.
Expand All @@ -56,19 +66,26 @@
#' then dividing each value by the l2-norm of the vector, \eqn{z_i =
#' \frac{|x_i|}{\|\vec{x}\|_2}} \citep{Muller1959sphere}. The absolute value in
#' the numerator ensures that points are sampled on the positive orthant of the
#' hyper-sphere. Sampling from the uniform distribution
#' \citep{LacKlaFon2017box} does not result in a uniform sampling when
#' projected onto the surface of the hyper-sphere.
#' hyper-sphere. Sampling from the uniform distribution \citep{LacKlaFon2017box} would
#' not result in a uniform sampling when projected onto the surface of the
#' hyper-sphere.
#'
#' Method `"convex-simplex"` is equivalent to `generate_ndset(...,
#' method="simplex")^2`, which is convex for minimisation problems. The
#' corresponding surface is equivalent to a simplex curved towards the
#' origin. Although the sampling on the simplex is uniform, the transformed
#' points are not.
#'
#' Method `"convex-sphere"` is equivalent to `1 - generate_ndset(...,
#' method="concave-sphere")`, which is convex for minimisation problems. It
#' corresponds to translating points from the negative orthant of the
#' hyper-sphere to the positive orthant.
#' hyper-sphere to the positive orthant. Thus, the sampling remains uniform.
#'
#' Method `"convex-simplex"` is equivalent to `generate_ndset(...,
#' method="concave-sphere")^4`, which is convex for minimisation problems.
#' The corresponding surface is equivalent to a simplex curved towards the
#' origin.
#' Methods `"inverted-simplex"` and `"concave-simplex"` are similar
#' translations of `"simplex"` and `"convex-simplex"`, respectively.
#' These translations have been called `inverted` shapes in the literature and
#' have different properties than their `regular` counterparts
#' \citep{IshHeSha2019regular}.
#'
#' @references
#'
Expand Down Expand Up @@ -102,13 +119,17 @@ generate_ndset <- function(n, d, method, seed = NULL, integer = FALSE)
}

sample_convex_sphere <- function() 1. - sample_sphere()
sample_convex_simplex <- function() sample_sphere()^4L
sample_convex_simplex <- function() sample_simplex()^2
sample_inverted_simplex <- function() 1. - sample_simplex()
sample_concave_simplex <- function() 1. - sample_convex_simplex()

sample_fun <- (
if (method %in% c("simplex", "linear", "L")) sample_simplex
else if (method %in% c("concave-sphere", "sphere", "C")) sample_sphere
else if (method %in% c("convex-sphere", "X")) sample_convex_sphere
else if (method == "convex-simplex") sample_convex_simplex
else if (method %in% c("inverted-simplex", "inverted-linear")) sample_inverted_simplex
else if (method == "concave-simplex") sample_concave_simplex
else stop("Unknown method =", method)
)

Expand Down
48 changes: 38 additions & 10 deletions r/vignettes/articles/generate.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ mutually nondominated points.

```{r generate_rnd_2d}
n <- 100
methods <- c("simplex", "concave-sphere", "convex-sphere", "convex-simplex")
colors <- c("red", "blue", "green", "purple")
shapes <- c(16, 15, 17, 18) # ggplot2 shape codes
methods <- c("simplex", "concave-sphere", "convex-sphere", "convex-simplex",
"inverted-simplex", "concave-simplex")
colors <- c("red", "blue", "green", "purple", "orange", "yellow")
shapes <- c(16, 15, 17, 18, 16, 15) # ggplot2 shape codes

df_all <- do.call(rbind.data.frame, lapply(methods, function(method) {
points <- moocore::generate_ndset(n, 2, method = method, seed = 42)
Expand Down Expand Up @@ -86,9 +87,9 @@ ggplot(df_int, aes(x = x, y = y, color = method, shape = method)) +
A popular way to generate a convex nondominated set is to translate the
negative orthant of the hyper-sphere to the unit hyper-cube
(`convex-sphere`). However, there are other possible convex sets with
different properties. For example the method `convex-simplex` applies a
non-linear transformation to a `concave-sphere` set, resulting in a convex
transformation of the standard simplex.
different properties. For example the method `convex-simplex` squares the
points generated by method `simplex`, resulting in a convex transformation
of the standard simplex.

First, let's define a few functions useful for plotting:
<details><summary>(show plotting code)</summary>
Expand Down Expand Up @@ -179,11 +180,38 @@ plotly_side_by_side <- function(fig1, fig2, height="500px") {
```{r generate_3d_convex}
n <- 2000

points1 <- moocore::generate_ndset(n, 3, "convex-sphere", seed = 42)
fig1 <- plot_3d("simplex", points1, title = "Convex-sphere")
fig1 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "convex-sphere", seed = 42), title = 'method="convex-sphere"')
fig2 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "convex-simplex", seed = 42), title = 'method="convex-simplex"')

points2 <- moocore::generate_ndset(n, 3, "convex-simplex", seed = 42)
fig2 <- plot_3d("simplex", points2, title = "Convex-simplex")
plotly_side_by_side(fig1, fig2)
```

# Inverted shapes

@IshHeSha2019regular analyze the differences between *regular* and
*inverted* shapes, shown below on the left and right figures,
respectively. The differences between `simplex` and `inverted-simplex`
are not noticeable in 2D, but are significant in higher dimensions.

```{r generate_3d_inverted_simplex}
n <- 2000

fig1 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "simplex", seed = 42), title = 'method="simplex"')
fig2 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "inverted-simplex", seed = 42), title = 'method="inverted-simplex"')

plotly_side_by_side(fig1, fig2)
```

```{r generate_3d_concave_convex_sphere}
fig1 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "concave-sphere", seed = 42), title = 'method="concave-sphere"')
fig2 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "convex-sphere", seed = 42), title = 'method="convex-sphere"')

plotly_side_by_side(fig1, fig2)
```

```{r generate_3d_convex_concave_simplex}
fig1 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "convex-simplex", seed = 42), title = 'method="convex-simplex"')
fig2 <- plot_3d("simplex", moocore::generate_ndset(n, 3, "concave-simplex", seed = 42), title = 'method="concave-simplex"')

plotly_side_by_side(fig1, fig2)
```
Expand Down
Loading