hyper3
objectshyper3.Rd
Objects of class hyper3
are a generalization of hyper2
objects
that allow the brackets to contain weighted probabilities.
As a motivating example, suppose two players with Bradley-Terry strengths \(p_1,p_2\) play chess where we quantify the first-mover advantage with a term \(\lambda\). If \(p_1\) plays white \(a+b\) times with \(a\) wins and \(b\) losses, and plays black \(c+d\) times with \(c\) wins and \(d\) losses, then a sensible likelihood function might be
$$ \left(\frac{\lambda p_1}{\lambda p_1 + p_2}\right)^{a} \left(\frac{p_2 }{\lambda p_1 + p_2}\right)^{b} \left(\frac{p_1 }{p_1 + \lambda p_2}\right)^{c} \left(\frac{\lambda p_2}{p_1 + \lambda p_2}\right)^{d} $$
If \(a=1,b=2,c=3,d=4\) and \(\lambda=1.3\) appropriate package idiom might be:
H <- hyper3()
H[c(p1=1.3)] %<>% inc(1) # a=1
H[c(p2=1)] %<>% inc(2) # b=2
H[c(p1=1.3,p2=1)] %<>% dec(3) # a+b=1+2=3
H[c(p1=1)] %<>% inc(3) # c=3
H[c(p2=1.3)] %<>% inc(4) # d=4
H[c(p1=1,p2=1.3)] %<>% dec(7) # c+d=3+4=7
H
> log( (p1=1)^3 * (p1=1, p2=1.3)^-7 * (p1=1.3)^1 * (p1=1.3, p2=1)^-3 *
(p2=1)^2 * (p2=1.3)^4)
The general form of terms of a hyper3
object would be
\(\left(w_1p_1+\cdots+w_rp_r\right)^{\alpha}\); the
complete object would be
$$ \mathcal{L}\left(p_1,\ldots,p_n\right)= \prod_{j=1}^N\left(\sum_{i=1}^n w_{ij}p_i\right)^{\alpha_i} $$
where we understand that \(p_n=1-\sum_{i=1}^{n-1}p_i\);
many of the weights might be zero. We see that the weights
\(w_{ij}\) may be arranged as a matrix and this form is taken
by function hyper3_m()
.
A list of brackets
A list of weights
A list of named vectors
Numeric vector of powers
Character vector of player names
Matrix of weights, column names being player names
Vector of powers, length equal to ncol(M)
Boolean with default TRUE
meaning to silently
remove all-zero rows of M
Function hyper3()
is the user-friendly creation method,
which dispatches to a helper function depending on its arguments.
Function hyper3_bw()
takes a list of brackets
(character vectors) and a list of weights (numeric vectors) and
returns a hyper3
object.
Function hyper3_nv()
takes a list of named vectors and
returns a hyper3
object.
Function hyper3_m()
takes a matrix with rows being the
brackets (entries are weights) and a numeric vector of powers.
Function evaluate3()
is a low-level helper function
that evaluates a log-likelihood at a point in probability space.
Don't use this: use the user-friendly loglik()
instead, which
dispatches to evaluate3()
.
Function maxp3()
is a placeholder (it is not yet
written). But the intention is that it will maximize the
log-likelihood of a hyper3
object over the Bradley Terry
strengths and any weights given. This might not be possible
as envisaged right now; I present some thoughts in
inst/kka.Rmd
.
Function list2nv()
converts a list of character vectors
into a named vector suitable for use as argument e
of
function cheering3()
. It is used in
inst/global_liveability_ranking.Rmd
.
Function as.namedvectorlist()
takes a hyper3
object and returns a disoRdered list of named vectors corresponding
to the brackets and their weights.
Function setweight()
alters the weight of every
occurrence of a set of players. It is vectorised, so
setweight(H,c("a","b"),88:89)
sets the weight of a
to
88 and b
to 89. Replacement methods are defined, so
“H["a"] <- as.weight(3)
” will set the weight of every
occurrence of player a
to 3. If H
is a hyper2
object, it will be coerced to hyper3
.
Generally return or deal with hyper3
objects
Functionality for hyper3
objects is generally indicated by adding
a “3
” to function names, eg gradient()
goes to
gradient3()
.
hyper3(B=list("a",c("a","b"),"b"),W=list(1.2,c(1.2,1),1),powers=c(3,4,-7))
#> log( (a=1.2)^3 * (a=1.2, b=1)^4 * (b=1)^-7)
hyper3(list(c(a=1.2),c(b=1),c(a=1.2,b=1)),powers=c(3,4,-7))
#> log( (a=1.2)^3 * (a=1.2, b=1)^-7 * (b=1)^4)
## Above two objects should be identical.
## Third method, send a matrix:
M <- matrix(rpois(15,3),5,3)
colnames(M) <- letters[1:3]
hyper3(M,c(2,3,-1,-5,1)) # second argument interpreted as powers
#> log( (a=3, b=3, c=3)^-1 * (a=3, b=4, c=2)^3 * (a=3, b=5)^-5 * (a=3,
#> b=6)^1 * (a=4, b=1, c=1)^2)
## Standard way to generate a hyper3 object is to create an empty object
## and populate it using the replacement methods:
a <- hyper3() # default creation method [empty object]
a[c(p1=1.3)] <- 5
a[c(p2=1 )] <- 2
a[c(p1=1.3,p2=1)] <- -7
a
#> log( (p1=1.3)^5 * (p1=1.3, p2=1)^-7 * (p2=1)^2)
chess3 # representative simple hyper3 object
#> log( (Anand=1)^15 * (Anand=2.09)^24 * (Anand=2.43, Karpov=2.43)^49 *
#> (Anand=2.43, Kasparov=2.43)^46 * (Anand=3.43, Karpov=4.52)^-49 *
#> (Anand=3.43, Kasparov=4.52)^-43 * (Anand=4.52, Karpov=3.43)^-43 *
#> (Anand=4.52, Kasparov=3.43)^-37 * (Karpov=1)^12 * (Karpov=2.09)^25 *
#> (Karpov=2.43, Kasparov=2.43)^129 * (Karpov=3.43, Kasparov=4.52)^-94 *
#> (Karpov=4.52, Kasparov=3.43)^-99 * (Kasparov=1)^20 *
#> (Kasparov=2.09)^45)
H1 <- rankvec_likelihood(letters[sample(6)])
H2 <- rankvec_likelihood(letters[sample(6)])
H1["a"] <- as.weight(1.2) # "a" has some disadvantage in H1
H1[c("b","c")] <- as.weight(2:3) # "b" and "c" have some advantage in H1
H2[c("c","d")] <- as.weight(1.5) # "c" and "d" have some advantage in H2
H1+H2
#> log( (a=1)^1 * (a=1, b=1, c=1.5, d=1.5, e=1, f=1)^-1 * (a=1, b=1,
#> c=1.5, e=1, f=1)^-1 * (a=1.2)^1 * (a=1.2, b=2, c=3, d=1, e=1, f=1)^-1 *
#> (b=1)^1 * (b=1, c=1.5, e=1, f=1)^-1 * (b=2, c=3, d=1, e=1, f=1)^-1 *
#> (b=2, c=3, e=1, f=1)^-1 * (b=2, e=1, f=1)^-1 * (b=2, f=1)^-1 *
#> (c=1.5)^1 * (c=1.5, e=1, f=1)^-1 * (c=3)^1 * (d=1)^1 * (d=1.5)^1 *
#> (e=1)^1 * (e=1, f=1)^-1 * (f=1)^2)