15.1.249. 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