diff --git a/DESCRIPTION b/DESCRIPTION index 4d46739e..b0c49d86 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: BayesMallows Type: Package Title: Bayesian Preference Learning with the Mallows Rank Model -Version: 2.1.1.9005 +Version: 2.1.1.9006 Authors@R: c(person("Oystein", "Sorensen", email = "oystein.sorensen.1985@gmail.com", role = c("aut", "cre"), diff --git a/NAMESPACE b/NAMESPACE index ff22ee2f..df1d6ffa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -28,6 +28,7 @@ export(assess_convergence) export(assign_cluster) export(burnin) export(compute_consensus) +export(compute_exact_partition_function) export(compute_expected_distance) export(compute_mallows) export(compute_mallows_mixtures) diff --git a/NEWS.md b/NEWS.md index f1ed9c21..997e4ef0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # BayesMallows (development versions) +* A function compute_exact_partition_function() is now added, which returns the + logarithm of the exact partition function for Cayley, Hamming, and Kendall + distance. * Fixed a bug in the Ulam distance. Thanks for Marta Crispino for discovering it. * Fixed a bug in SMC algorithm for pairwise preference data, where the proposal diff --git a/R/compute_exact_partition_function.R b/R/compute_exact_partition_function.R new file mode 100644 index 00000000..1c54bd14 --- /dev/null +++ b/R/compute_exact_partition_function.R @@ -0,0 +1,26 @@ +#' @title Compute exact partition function +#' +#' @description For Cayley, Hamming, and Kendall distances, computationally +#' tractable functions are available for the exact partition function. +#' +#' @param alpha Dispersion parameter. +#' @param n_items Number of items. +#' @param metric Distance function, one of "cayley", "hamming", or "kendall". +#' +#' @return The logarithm of the partition function. +#' @export +#' +#' @references \insertAllCited{} +#' +#' @example inst/examples/compute_exact_partition_function_example.R +#' @family partition function +compute_exact_partition_function <- function( + alpha, n_items, + metric = c("cayley", "hamming", "kendall")) { + metric <- match.arg(metric, c("cayley", "hamming", "kendall")) + validate_integer(n_items) + validate_positive(n_items) + validate_positive(alpha) + + get_partition_function(alpha, n_items, metric, NULL) +} diff --git a/R/estimate_partition_function.R b/R/estimate_partition_function.R index e052947e..ee00ebcc 100644 --- a/R/estimate_partition_function.R +++ b/R/estimate_partition_function.R @@ -10,7 +10,7 @@ #' any number of items, for footrule distances with up to 50 items, Spearman #' distance with up to 20 items, and Ulam distance with up to 60 items. This #' function is thus intended for the complement of these cases. See -#' [get_cardinalities()] for details. +#' [get_cardinalities()] and [compute_exact_partition_function()] for details. #' #' @param method Character string specifying the method to use in order to #' estimate the logarithm of the partition function. Available options are diff --git a/R/get_cardinalities.R b/R/get_cardinalities.R index ab3a7031..75d32b94 100644 --- a/R/get_cardinalities.R +++ b/R/get_cardinalities.R @@ -3,7 +3,7 @@ #' @description The partition function for the Mallows model can be defined in a #' computationally efficient manner as #' \deqn{Z_{n}(\alpha) = \sum_{d_{n} \in -#' \mathcal{D}_{n}} N_{m,n} e^{-(\alpha/n) d_{m}}}. +#' \mathcal{D}_{n}} N_{m,n} e^{-(\alpha/n) d_{m}}.} #' In this equation, \eqn{\mathcal{D}_{n}} a set containing all possible #' distances at the given number of items, and \eqn{d_{m}} is on element of #' this set. Finally, \eqn{N_{m,n}} is the number of possible configurations diff --git a/R/validation_functions.R b/R/validation_functions.R index 3770c07a..956421c9 100644 --- a/R/validation_functions.R +++ b/R/validation_functions.R @@ -14,7 +14,7 @@ validate_integer <- function(argument) { } validate_positive <- function(argument) { - if (argument <= 0 || !is.numeric(argument)) { + if (length(argument) > 1 || argument <= 0 || !is.numeric(argument)) { stop(paste( deparse(substitute(argument)), "must be a strictly positive number of length one" diff --git a/inst/examples/compute_exact_partition_function_example.R b/inst/examples/compute_exact_partition_function_example.R new file mode 100644 index 00000000..94d57338 --- /dev/null +++ b/inst/examples/compute_exact_partition_function_example.R @@ -0,0 +1,11 @@ +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "cayley" +) + +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "hamming" +) + +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "kendall" +) diff --git a/man/compute_exact_partition_function.Rd b/man/compute_exact_partition_function.Rd new file mode 100644 index 00000000..cd59a781 --- /dev/null +++ b/man/compute_exact_partition_function.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/compute_exact_partition_function.R +\name{compute_exact_partition_function} +\alias{compute_exact_partition_function} +\title{Compute exact partition function} +\usage{ +compute_exact_partition_function( + alpha, + n_items, + metric = c("cayley", "hamming", "kendall") +) +} +\arguments{ +\item{alpha}{Dispersion parameter.} + +\item{n_items}{Number of items.} + +\item{metric}{Distance function, one of "cayley", "hamming", or "kendall".} +} +\value{ +The logarithm of the partition function. +} +\description{ +For Cayley, Hamming, and Kendall distances, computationally +tractable functions are available for the exact partition function. +} +\examples{ +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "cayley" +) + +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "hamming" +) + +compute_exact_partition_function( + alpha = 3.4, n_items = 34, metric = "kendall" +) +} +\references{ +\insertAllCited{} +} +\seealso{ +Other partition function: +\code{\link{estimate_partition_function}()}, +\code{\link{get_cardinalities}()} +} +\concept{partition function} diff --git a/man/estimate_partition_function.Rd b/man/estimate_partition_function.Rd index 5bfb4104..4c9dae02 100644 --- a/man/estimate_partition_function.Rd +++ b/man/estimate_partition_function.Rd @@ -54,7 +54,7 @@ can be computed efficiently for Cayley, Hamming and Kendall distances with any number of items, for footrule distances with up to 50 items, Spearman distance with up to 20 items, and Ulam distance with up to 60 items. This function is thus intended for the complement of these cases. See -\code{\link[=get_cardinalities]{get_cardinalities()}} for details. +\code{\link[=get_cardinalities]{get_cardinalities()}} and \code{\link[=compute_exact_partition_function]{compute_exact_partition_function()}} for details. } \examples{ # IMPORTANCE SAMPLING @@ -116,6 +116,7 @@ model_fit <- compute_mallows( } \seealso{ Other partition function: +\code{\link{compute_exact_partition_function}()}, \code{\link{get_cardinalities}()} } \concept{partition function} diff --git a/man/get_cardinalities.Rd b/man/get_cardinalities.Rd index 3b53d7d6..f10005d2 100644 --- a/man/get_cardinalities.Rd +++ b/man/get_cardinalities.Rd @@ -21,7 +21,7 @@ i.e., \eqn{N_{m,n}}. The partition function for the Mallows model can be defined in a computationally efficient manner as \deqn{Z_{n}(\alpha) = \sum_{d_{n} \in - \mathcal{D}_{n}} N_{m,n} e^{-(\alpha/n) d_{m}}}. + \mathcal{D}_{n}} N_{m,n} e^{-(\alpha/n) d_{m}}.} In this equation, \eqn{\mathcal{D}_{n}} a set containing all possible distances at the given number of items, and \eqn{d_{m}} is on element of this set. Finally, \eqn{N_{m,n}} is the number of possible configurations @@ -60,6 +60,7 @@ sum(apply(perms, 1, function(x) exp(-alpha / n_items * sum((x - 1:4)^2)))) } \seealso{ Other partition function: +\code{\link{compute_exact_partition_function}()}, \code{\link{estimate_partition_function}()} } \concept{partition function} diff --git a/tests/testthat/test-compute_exact_partition_function.R b/tests/testthat/test-compute_exact_partition_function.R new file mode 100644 index 00000000..fd39f8f3 --- /dev/null +++ b/tests/testthat/test-compute_exact_partition_function.R @@ -0,0 +1,35 @@ +test_that("compute_exact_partition_function works", { + expect_error( + compute_exact_partition_function(3, -1), + "n_items must be a positive integer" + ) + expect_error( + compute_exact_partition_function(3, 2.3), + "n_items must be a positive integer" + ) + expect_error( + compute_exact_partition_function(3, 0), + "n_items must be a strictly positive number of length one" + ) + expect_error( + compute_exact_partition_function(-2, 3), + "alpha must be a strictly positive number of length one" + ) + expect_error( + compute_exact_partition_function(rnorm(2), 3), + "alpha must be a strictly positive number of length one" + ) + + expect_equal( + compute_exact_partition_function(alpha = 3, n_items = 10, metric = "cayley"), + 13.0481794289176 + ) + expect_equal( + compute_exact_partition_function(alpha = 3, n_items = 10, metric = "hamming"), + 12.4542713806513 + ) + expect_equal( + compute_exact_partition_function(alpha = 3, n_items = 10, metric = "kendall"), + 9.69641008390133 + ) +})