15.1.253. tablet_qt/maths/linkfunctionfamily.cpp

/*
    Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
    Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

    This file is part of CamCOPS.

    CamCOPS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    CamCOPS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
*/

#include "linkfunctionfamily.h"

#include "maths/statsfunc.h"


LinkFunctionFamily::LinkFunctionFamily(
    const QString& family_name,
    const LinkFnType& link_fn,
    const InvLinkFnType& inv_link_fn,
    const DerivativeInvLinkFnType& derivative_inv_link_fn,
    const VarianceFnType& variance_fn,
    const DevResidsFnType& dev_resids_fn,
    const ValidEtaFnType& valid_eta_fn,
    const ValidMuFnType& valid_mu_fn,
    const InitializeFnType& initialize_fn
#ifdef LINK_FUNCTION_FAMILY_USE_AIC
    ,
    const AICFnType& aic_fn
#endif
) :
    family_name(family_name),
    link_fn(link_fn),
    inv_link_fn(inv_link_fn),
    derivative_inv_link_fn(derivative_inv_link_fn),
    variance_fn(variance_fn),
    dev_resids_fn(dev_resids_fn),
    valid_eta_fn(valid_eta_fn),
    valid_mu_fn(valid_mu_fn),
    initialize_fn(initialize_fn)
#ifdef LINK_FUNCTION_FAMILY_USE_AIC
    ,
    aic_fn(aic_fn)
#endif
{
}


const QString LINK_FAMILY_NAME_GAUSSIAN("gaussian");
const QString LINK_FAMILY_NAME_BINOMIAL("binomial");
const QString LINK_FAMILY_NAME_POISSON("poisson");


// Disambiguating overloaded functions:
// - https://stackoverflow.com/questions/10111042/wrap-overloaded-function-via-stdfunction

const LinkFunctionFamily LINK_FN_FAMILY_LOGIT(
    // R: binomial(), or binomial(link = "logit") to be explicit.
    LINK_FAMILY_NAME_BINOMIAL,
    // ... family_name; binomial()$family
    statsfunc::logitArray,
    // ... link function; binomial()$linkfun; eta = logit(mu)
    statsfunc::logisticArray,
    // ... inverse link function; binomial()$linkinv; mu = logistic(eta)
    statsfunc::derivativeOfLogisticArray,
    // ... derivative of inverse link function; binomial()$mu.eta
    statsfunc::binomialVariance,
    // ... variance function; binomial()$variance; V(mu) = mu * (1 - mu)
    statsfunc::binomialDevResids,
    // ... dev_resids_fn; binomial()$dev.resids
    statsfunc::alwaysTrue,
    // ... valid_eta_fn; binomial()$valideta
    statsfunc::binomialValidMu,
    // ... valid_mu_fn; binomial()validmu
    statsfunc::binomialInitialize
// ... initialize_fn; binomial()$initialize
#ifdef LINK_FUNCTION_FAMILY_USE_AIC
    ,
    statsfunc::binomialAIC
// ... aic_fn; binomial()$aic
#endif
);


const LinkFunctionFamily LINK_FN_FAMILY_GAUSSIAN(
    // R: gaussian(), or gaussian(link = "identity").
    LINK_FAMILY_NAME_GAUSSIAN,
    // ... family_name; gaussian()$family
    statsfunc::identityArray,
    // ... link function; gaussian()$linkfun; eta = me
    statsfunc::identityArray,
    // ... inverse link function; gaussian()$linkinv; mu = eta
    statsfunc::oneArray,
    // ... derivative of inverse link function; gaussian()$mu.eta;
    //     y = x => dy/dx = y' = 1
    statsfunc::oneArray,
    // ... variance function; gaussian()$variance; V(mu) = 1
    // ... variance is independent of the mean
    // ... https://en.wikipedia.org/wiki/Variance_function#Example_.E2.80.93_normal
    statsfunc::gaussianDevResids,
    // ... dev_resids_fn; gaussian()$dev.resids
    statsfunc::alwaysTrue,
    // ... valid_eta_fn; gaussian()$valideta
    statsfunc::alwaysTrue,
    // ... valid_mu_fn; gaussian()validmu
    statsfunc::gaussianInitialize
// ... initialize_fn; gaussian()$initialize
#ifdef LINK_FUNCTION_FAMILY_USE_AIC
    ,
    statsfunc::gaussianAIC
// ... aic_fn; gaussian()$aic
#endif
);


const LinkFunctionFamily LINK_FN_FAMILY_POISSON(
    // R: poisson(), or poisson(link = "log").
    LINK_FAMILY_NAME_POISSON,
    // ... family_name; poisson()$family
    statsfunc::logArray,
    // ... link function; poisson()$linkfun; eta = log(mu)
    statsfunc::expArray,
    // ... inverse link function; poisson()$linkinv; mu = exp(eta)
    statsfunc::expArray,
    // ... derivative of inverse link function;
    //     poisson()$mu.eta; mu' = exp(eta)
    statsfunc::identityArray,
    // ... variance function; poisson()$variance; V(mu) = mu
    statsfunc::poissonDevResids,
    // ... dev_resids_fn; poisson()$dev.resids
    statsfunc::alwaysTrue,
    // ... valid_eta_fn; poisson()$valideta
    statsfunc::poissonValidMu,
    // ... valid_mu_fn; poisson()$validmu
    statsfunc::poissonInitialize
// ... initialize_fn; poisson()$initialize
#ifdef LINK_FUNCTION_FAMILY_USE_AIC
    ,
    statsfunc::poissonAIC
// ... aic_fn; poisson()$aic
#endif
);

// For link function families, see also:
// - https://stats.stackexchange.com/questions/212430/what-are-the-error-distribution-and-link-functions-of-a-model-family-in-r
// - https://en.wikipedia.org/wiki/Generalized_linear_model#Link_function
// - R: ?family