The density backend of a point hypothesis (the density_method of hypothesis_BF() and hypothesis_BF_model()) decides how the posterior ordinate at the null value is obtained. The built-in backends "KDE" and "normal" estimate it from the posterior draws, and "precomputed" uses ordinates that are stored on the draws (it is for draw inputs only, not for fitted models). A package that computes posterior ordinates itself, for example by a likelihood-aware estimator that cannot be written as a function of the draws, registers an ordinate backend. hypothesis_density_backend() creates a backend object, register_hypothesis_density_backend() adds it to the registry (a package registers its backends in .onLoad() and removes them with unregister_hypothesis_density_backend() in .onUnload()), and hypothesis_density_backends() lists the registered backends.

hypothesis_density_backend(
  name,
  type = c("ordinate", "draws", "stored"),
  available = NULL,
  control = NULL,
  attach = NULL,
  reuse = NULL,
  warnings = NULL,
  diagnostics = NULL,
  bind_diagnostics = NULL,
  rescale_failure = NULL,
  refusal_classes = NULL,
  clear_cache = NULL,
  method = NULL,
  policy = list(),
  advertised = TRUE,
  package = NULL
)

register_hypothesis_density_backend(backend, overwrite = FALSE)

unregister_hypothesis_density_backend(name)

hypothesis_density_backends()

Arguments

name

the name of the density method (a single string that starts with a letter).

type

"ordinate", "draws", or "stored".

available, control, attach, reuse, warnings, diagnostics, bind_diagnostics, rescale_failure, refusal_classes, clear_cache

the callbacks of the backend, functions or NULL for the default; see Details.

method

for a "draws" backend, the evaluation of hypothesis_BF() that it stands for: "KDE" or "normal".

policy

a list of declared settings of the backend.

advertised

whether hypothesis_quantities() lists the backend among the methods that evaluate a quantity.

package

the name of the package that provides the backend.

backend

a backend created with hypothesis_density_backend().

overwrite

whether registering replaces a registered backend of the same name. Replacing a built-in backend is not possible.

Value

hypothesis_density_backend() returns an object of class BayesTools_hypothesis_density_backend. register_hypothesis_density_backend() returns the backend invisibly, and unregister_hypothesis_density_backend() returns whether a backend was removed (invisibly). hypothesis_density_backends() returns a data frame with one row per registered backend in the order of registration: name, type, package, advertised, and the list column policy.

Details

A backend has a type: "draws" (evaluated from the posterior draws by hypothesis_BF() with the density method method), "ordinate" (the backend attaches the posterior ordinates of the tested values to the draws; they are then evaluated as "precomputed" ordinates), or "stored" (the ordinates are already attached to the draws). Matching of density_method to the registered names ignores case and accepts unambiguous partial names.

The engine calls the callbacks of a backend as follows; each is optional except attach of an ordinate backend.

available(object, plan, control)

whether the backend can evaluate the statement plan of the model object (the capability_object of the provider) with the normalized control, the settings that control() returns for the call (for the stored marginal means of a model, for the settings of the call or the stored settings that the provider inherits). For the stored marginal means, settings that control() refuses reach available() as they were supplied, and the engine stops with the failure of control() after the plans are checked; for a fitted model, the failure of control() stops the call before any plan is checked. It is evaluated on every call and never cached. It returns NULL when the backend can, and otherwise a refusal: a list with the reason (a string) and optionally class (additional condition classes appended to BayesTools_hypothesis_method and BayesTools_hypothesis_unavailable) and fields (a named list of further fields of the condition). The engine stops with the refusal before any statement is evaluated.

control(control)

the normalized density_control of the backend (defaults filled in), stopping on invalid settings. It is called with the settings of the call (or the stored settings of the provider) on every call with an ordinate backend, and for the settings that a call supplies to another backend, after the check_density_control() of the provider (hypothesis_provider()). The default accepts no settings: NULL and an empty list give NULL, anything else is an error.

attach(posterior, request, control, cache)

the whole ordinate step of an ordinate backend. posterior is the marginal posterior of the tested quantity (a vector, or for the request of a factor level the list of the posteriors of the levels of the factor term); it returns it with the ordinates of the requested values stored in its posterior_ordinate metadata (posterior_metadata(), posterior_ordinate_attribute(), posterior_ordinate_append()), one entry per value, and the parameter, conditional, conditional_rule, and condition_key metadata of the draws, or stops with its own typed condition when an ordinate cannot be constructed. cache is an environment that lives for the evaluation of one group of statements, for objects that the requests of the group share. The request is a list with the elements kind ("scalar": the values of the vector posterior; "level": the values of the level level), route (the kind of the statement plan: "scalar", "linear", "random", "exp_affine", or "marginal_mean"), object (the model object, or the object that the provider names as its capability_object), model (the object of the provider), parameter, label (the tested quantity, as the table names it), level, values (the point values to compute), conditional (the conditioning of the draws: the parameter whose inclusion event the draws are conditioned on, or NULL), condition (the declared conditioning of the draws that the ordinates belong to, read from their metadata (posterior_metadata(), "condition"): the elements conditional (the effective conditioning, a character vector that is empty for averaged draws), conditional_rule, condition_key, condition_event, and resolved_condition_event, those the draws declare; an empty list for draws without a declaration), spec (the structure of the tested quantity that the provider declares: for example type = "primitive" or "linear" with the weights on the fitted coordinates and the prior_density), display_transform (the transformation from the evaluated to the tested scale, or NULL), density_method (the name of the backend), and inference_type (marginal means: the marginal inference the draws belong to).

reuse(entry, request, control, posterior)

whether the ordinate entry that is stored on the draws posterior at a requested value is current for the request (the method, control, source of the fit, target, and conditioning agree), so that it is not computed again. posterior are the draws that carry entry (for the request of a factor level, the draws of that level), with their metadata; request$condition is their declared conditioning. The default reuses nothing: stored ordinates at the requested values are replaced.

warnings(posterior, request)

the warnings of the ordinates stored on posterior (recursively over the levels of a list), as a data frame with the columns warning, parameter, level, label, and value. The engine puts each warning on the rows of the statements it belongs to. The default reads the warning element of the diagnostics of each stored ordinate. The request is the request that attach received for the group of statements, before the values whose stored ordinates reuse accepted were left out of values; for a group that is attached level by level (the levels of a factor term, marginal means) it is the request of the first level, and the requests of the group differ in their level, values, label, spec, and condition only.

diagnostics(posterior, request)

the public diagnostics of the stored ordinates (a data frame; request as for warnings), stored as the density_diagnostics attribute of the table, and bind_diagnostics(list), which combines the diagnostics of several groups of statements. Without diagnostics the table has no such attribute; the default of bind_diagnostics row-binds the data frames.

rescale_failure(condition, requested, evaluated, label, density_method)

restates a condition that attach raised for the evaluated values evaluated of a request for the values requested of a quantity that is evaluated through a transformation of itself (a variance through its standard deviation); it returns the condition to signal, or NULL to signal the original one.

refusal_classes(cause)

additional condition classes for the refusals of the ordinate backends for a generic cause ("original_scale", "conditional_random", or "random_target"); they follow the classes of the refusal of the engine (for example BayesTools_hypothesis_target and BayesTools_hypothesis_unavailable). A provider names the cause of the refusal of a random-effect quantity (hypothesis_provider()).

clear_cache()

drops the caches of the backend; the engine calls it when it drops its own caches.

policy is a list of the settings that the backend declares for its acceptance of ordinates (thresholds on its error estimates, for example). It is reported by hypothesis_density_backends() and not used by the engine: the backend applies its own acceptance rules in attach, and the engine only checks that the attached ordinates are valid (posterior_ordinate_supports_bf()).

Examples

hypothesis_density_backends()
#>          name   type    package advertised policy
#> 1         KDE  draws BayesTools       TRUE       
#> 2      normal  draws BayesTools      FALSE       
#> 3 precomputed stored BayesTools      FALSE       

# a toy backend that evaluates the ordinate of a normal posterior exactly
normal_ordinate <- hypothesis_density_backend(
  name   = "exactNormal",
  type   = "ordinate",
  attach = function(posterior, request, control, cache) {
    draws    <- as.numeric(posterior)
    ordinate <- stats::dnorm(request$values, mean(draws), stats::sd(draws))
    posterior_metadata(posterior, "posterior_ordinate") <-
      posterior_ordinate_attribute(
        value = request$values, ordinate = ordinate,
        method = "exact normal", density_method = "exactNormal",
        parameter = attr(posterior, "parameter")
      )
    posterior
  }
)
register_hypothesis_density_backend(normal_ordinate)
hypothesis_density_backends()$name
#> [1] "KDE"         "normal"      "precomputed" "exactNormal"
unregister_hypothesis_density_backend("exactNormal")