Source code for dit.multivariate.common_informations.kamath_common_information

"""
The Kamath-Anantharam dual common information.

A new dual to the Gács-Körner common information, defined via the Gray-Wyner
system. See Kamath & Anantharam (2010).
"""

from ...algorithms.minimal_sufficient_statistic import insert_mss
from ...helpers import normalize_rvs, parse_rvs
from ...shannon import conditional_entropy as H
from ...utils import flatten, unitful

__all__ = (
    "directed_kamath_common_information",
    "kamath_common_information",
)


def _directed_value(dist, rvs, about, crvs):
    """
    Compute H(Phi^{about}_{rvs} | crvs) as a plain float.

    Phi^{about}_{rvs} is the minimal sufficient statistic of `rvs` about
    `about` (Kamath & Anantharam 2010, Lemma 3.5(5)).
    """
    rvs_idx = list(parse_rvs(dist, rvs)[1])
    about_idx = list(parse_rvs(dist, about)[1])
    crvs_idx = list(parse_rvs(dist, crvs)[1]) if crvs else []

    d = insert_mss(dist, -1, rvs=rvs_idx, about=about_idx)
    new_idx = d.outcome_length() - 1
    return H(d, [new_idx], crvs_idx)


[docs] @unitful def directed_kamath_common_information(dist, rvs, about, crvs=None): """ Calculates the directed Kamath-Anantharam common information G(rvs -> about) = H(Phi^{about}_{rvs}), where Phi^{about}_{rvs} is the minimal sufficient statistic of `rvs` about `about`. In the bivariate notation of Kamath & Anantharam (2010), this computes G(Y -> X) when called with `rvs=Y, about=X`. The variable on the tail of the arrow (`rvs`) is compressed via the minimal sufficient statistic; the variable on the head (`about`) is what that statistic preserves information about. Parameters ---------- dist : Distribution The distribution from which the directed common information is calculated. rvs : list The indexes (or names) of the random variables on the tail of the arrow. These are compressed to their minimal sufficient statistic about `about`. about : list The indexes (or names) of the random variables on the head of the arrow. The minimal sufficient statistic preserves all information about these variables. crvs : list, None The indexes of the random variables to condition on. If None, then no conditioning is performed. Returns ------- G : float The directed Kamath-Anantharam common information. Raises ------ ditException Raised if `rvs`, `about`, or `crvs` contain non-existant random variables. """ rvs = list(flatten([rvs])) about = list(flatten([about])) crvs = [] if crvs is None else list(flatten([crvs])) return _directed_value(dist, rvs, about, crvs)
[docs] @unitful def kamath_common_information(dist, rvs=None, crvs=None): """ Calculates the Kamath-Anantharam dual common information U[X1:X2...] of the random variables in `rvs`. For two variables this is U(X; Y) = max{ G(Y -> X), G(X -> Y) } = max{ H(Phi^X_Y), H(Phi^Y_X) }, the symmetric "dual" to the Gács-Körner common information introduced by Kamath & Anantharam (2010). It is generalized to n variables as U(X_{0:n}) = max_i H(Phi^{X_{!=i}}_{X_i}), the maximum entropy of the minimal sufficient statistic of one variable about all the others. Parameters ---------- dist : Distribution The distribution from which the common information is calculated. rvs : list, None A list of lists. Each inner list specifies the indexes of a random variable to compress via its minimal sufficient statistic about the rest. If None, then each single random variable is used. crvs : list, None A single list of indexes specifying the random variables to condition on. If None, then no conditioning is performed. Returns ------- U : float The Kamath-Anantharam dual common information. Raises ------ ditException Raised if `rvs` or `crvs` contain non-existant random variables. """ rvs, crvs = normalize_rvs(dist, rvs, crvs) values = [] for i, rv in enumerate(rvs): rv_flat = list(flatten([rv])) rest = list(flatten(rvs[:i] + rvs[i + 1 :])) values.append(_directed_value(dist, rv_flat, rest, crvs)) return max(values)