initial commit
This commit is contained in:
commit
eb46da71b8
107
code.R
Normal file
107
code.R
Normal file
|
@ -0,0 +1,107 @@
|
|||
## ------------- secretary_problem.R ------------
|
||||
## Title: The Secretary (Marriage) Problem
|
||||
##
|
||||
## Description: Simulation of optimal halting problem. Trying
|
||||
## to see how different utility scoring affects expected outcomes.
|
||||
## - Uniform, set range to sqrt(12) for sd == 1
|
||||
## - Normal, roughly the distribution of people?
|
||||
## - Exponential, mostly not suitable, but some will change your world?
|
||||
##
|
||||
## Author: MollieTheMare
|
||||
## Date Created: 2024-04-19
|
||||
## Notes:
|
||||
## - Subtracted 1 from exponential distribution to get mean 0
|
||||
## - For ordinal information stopping at 1/e (~37%) is most
|
||||
## likely to find the optimal partner, but you only have a 37% chance.
|
||||
## - Wikipedia for the Cardinal payoff variant gives the solution to
|
||||
## a uniform as sqrt(n)
|
||||
## - Also links Sakaguchi that gives a general solution, but looks
|
||||
## like a pain to go through.
|
||||
## ---------------------------
|
||||
library(data.table)
|
||||
library(knitr)
|
||||
|
||||
select_best_after_k <-
|
||||
function(rnkx, k) {
|
||||
n <- length(rnkx)
|
||||
selected <- which(rnkx > max(rnkx[1:k]))
|
||||
if (length(selected) == 0) {
|
||||
selected <- n
|
||||
} else if (length(selected) > 1) {
|
||||
selected <- selected[[1]]
|
||||
}
|
||||
selected
|
||||
}
|
||||
|
||||
# x is a vector of utilities, the larger the better
|
||||
run_selection <- function(x) {
|
||||
n <- length(x)
|
||||
rnkx <- frank(x)
|
||||
# actual best
|
||||
i_best <- which(rnkx == length(x))
|
||||
x_best <- x[[i_best]]
|
||||
# exp stopping
|
||||
i_exp <- select_best_after_k(rnkx, round(n / exp(1)))
|
||||
x_exp <- x[[i_exp]]
|
||||
# sqrt stopping
|
||||
i_sqrt <- select_best_after_k(rnkx, round(sqrt(n)))
|
||||
x_sqrt <- x[[i_sqrt]]
|
||||
# fist love
|
||||
x_1 <- x[[1]]
|
||||
|
||||
result_table <-
|
||||
data.table(
|
||||
is_best = i_best == c(i_exp, i_sqrt),
|
||||
x = c(x_exp, x_sqrt),
|
||||
loss = x_best - c(x_exp, x_sqrt),
|
||||
gain = c(x_exp, x_sqrt) - x_1,
|
||||
# best = i_best,
|
||||
r = c("n/e","sqrt(n)")
|
||||
)
|
||||
|
||||
result_table
|
||||
}
|
||||
|
||||
run_rounds <- function(FUN, rounds = 1000, n = 256, ...) {
|
||||
runs <- list()
|
||||
for (i in 1:rounds) {
|
||||
x <- FUN(n, ...)
|
||||
runs[[i]] <- run_selection(x)
|
||||
}
|
||||
rbindlist(runs)
|
||||
}
|
||||
|
||||
# Expected 5%ile shortfall
|
||||
ES5 <- function(loss) {
|
||||
mean(loss[loss > quantile(loss, 0.95)])
|
||||
}
|
||||
|
||||
{# simulation runs ------------
|
||||
set.seed(0)
|
||||
rounds <- 50000
|
||||
unif_runs <- run_rounds(runif, rounds, min = -sqrt(12)/2, max = sqrt(12)/2)
|
||||
normal_runs <- run_rounds(rnorm, rounds)
|
||||
exp_runs <- run_rounds(FUN = function(n) {rexp(n) - 1}, rounds)
|
||||
unif_runs[, gen_dist := 'unif']
|
||||
normal_runs[, gen_dist := 'norm']
|
||||
exp_runs[, gen_dist := 'exp']
|
||||
results <- rbind(unif_runs, normal_runs, exp_runs)
|
||||
}
|
||||
|
||||
summary_table <-
|
||||
results[, .(
|
||||
`P(r)` = scales::label_percent()(sum(is_best) / .N),
|
||||
`P(miss)`= scales::label_percent()(sum(gain < 0) / .N),
|
||||
`<u>` = mean(x), #since we have set the mean 0 ~ gain
|
||||
# `<gain>` = mean(gain),
|
||||
`<loss>` = mean(loss),
|
||||
sd_loss = sd(loss),
|
||||
#sd_x = sd(x),
|
||||
ES_5 = ES5(loss),
|
||||
# best_stop = mean((best-1) / 256),
|
||||
max_loss = max(loss)
|
||||
),
|
||||
keyby = .(gen_dist, r)]
|
||||
summary_table
|
||||
|
||||
kable(summary_table, digits = 1, align = c('c'))
|
Loading…
Reference in New Issue
Block a user