-
Notifications
You must be signed in to change notification settings - Fork 7
/
rescaleNetwork.R
99 lines (92 loc) · 3.4 KB
/
rescaleNetwork.R
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
#' @title Rescale network
#'
#' @description Normalize network coordinates to the unit cube while maintaining
#' its geography.
#'
#' @template arg_network
#' @param method [\code{character(1)}]\cr
#' Rescaling method which actually modifies the coordinates.
#' Currently there are three methods available:
#' \describe{
#' \item{by.dimension}{Scaling is performed for each dimension independently.}
#' \item{global}{Here we shift all the points toward the origin by the minimum of both
#' x and y coordiantes and devide by the range of global maximim and minimum.}
#' \item{global2}{Here wer shift - analogously to the \code{by.dimension} strategy -
#' dimension wise and devide by the maximum of the ranges in x respectivly y direction.}
#' }
#' Default is \code{global2}, which leads to the most \dQuote{natural} rescaling.
#' @examples
#' \dontrun{
#' library(gridExtra)
#' x = generateClusteredNetwork(n.points = 100L, n.cluster = 4L, name = "Rescaling Demo")
#'
#' # here we "stretch" the instance x direction to visualize the differences of
#' # the rescaling mehtods
#' x$coordinates[, 1] = x$coordinates[, 1] * 10L
#' x$upper = x$upper * 10L
#' pls = list(
#' autoplot(x) + ggtitle("Original"),
#' autoplot(rescaleNetwork(x, method = "by.dimension")) + ggtitle("By dimension"),
#' autoplot(rescaleNetwork(x, method = "global")) + ggtitle("Global"),
#' autoplot(rescaleNetwork(x, method = "global2")) + ggtitle("Global2")
#' )
#' pls$nrow = 1L
#' do.call(grid.arrange, pls)
#' }
#' @return [\code{Network}]
#' @export
rescaleNetwork = function(x, method = "global2") {
assertClass(x, "Network")
if (!isEuclidean(x)) {
stopf("Rescaling for non-euclidean networks unsupported.")
}
coordinates = x$coordinates
if (hasDepots(x)) {
coordinates = rbind(x$depot.coordinates, coordinates)
}
method.mapping = list(
"by.dimension" = rescaleNetworkByDimension,
"global" = rescaleNetworkGlobal,
"global2" = rescaleNetworkGlobal2
)
assertChoice(method, choices = names(method.mapping))
rescaleMethod = method.mapping[[method]]
rescaled.coordinates = rescaleMethod(coordinates)
if (hasDepots(x)) {
n.depots = getNumberOfDepots(x)
x$depot.coordinates = rescaled.coordinates[1:n.depots, , drop = FALSE]
x$coordinates = rescaled.coordinates[-(1:n.depots), , drop = FALSE]
} else {
x$coordinates = rescaled.coordinates
}
# distance matrix needs an update (probably there is a nice formula for that
# without O(n^2) recomputation of the distance matrix)
# recalculate only if it was present
if (!is.null(x$distance.matrix))
x$distance.matrix = as.matrix(dist(x$coordinates))
# rescaling is a normalization to [0,1]^dim
x$lower = 0
x$upper = 1
return(x)
}
# Rescale by normalizing with global min/max values.
rescaleNetworkGlobal = function(x) {
rg = range(x)
return((x - rg[1]) / (rg[2] - rg[1]))
}
# Rescale by shifting dimension-wise and scaling with the maximal range
rescaleNetworkGlobal2 = function(x) {
rgs = apply(x, 2, range)
# we could transpose x first and transpose another time after rescaling,
# but this is more efficient
x[, 1] = (x[, 1] - rgs[1, 1])
x[, 2] = (x[, 2] - rgs[1, 2])
scale = max(rgs[2,] - rgs[1,])
return(x / scale)
}
# Rescale by normalizing dimension-wise with min/max values
rescaleNetworkByDimension = function(x) {
min = apply(x, 2, min)
max = apply(x, 2, max)
return(t((t(x) - min) / (max - min)))
}