# Path: Utility.py
# def l2(x):
# def apply_scale(w, a, b):
# def logabsdiffexp(x, y):
#     def f(x, y):
# def logit_mean(x):
# def digest(x):
# def tree():
# def lift_tree(src, dst):
# def init_latex_rendering():
# def draw_confidence(a, m, S, levels = [0.95]):


import numpy as np
    import ctypes
            import sys; sys.exit()
from scipy import optimize as opt
from Utility import logsumexp, logabsdiffexp, digest, apply_scale
    
Return the approximate nll of an observed binary matrix given
specified Bernoulli weights, conditioned on having the observed
margins.

Inputs:
  A: observed data, (m x n) binary matrix
  w: weight matrix, (m x n) matrix with values in (0, +infty)
Output:
  ncll: negative conditional log-likelihood
"""
    assert(A.shape == w.shape)

    r = A.sum(1, dtype=np.int)
    c = A.sum(0, dtype=np.int)

    r, c, arrays, _ = _prune(r, c, A, w)
    A, w = arrays

    # Sizing
    m, n = len(r), len(c)
    if (m == 0) or (n == 0):
        return 0.0

    # Sort the row margins (descending)
    rndx = np.argsort(-r)
    rsort = r[rndx]

    # Balance the weights
    a_scale, b_scale = canonical_scalings(w, r, c)

# Path: Utility.py
# def l2(x):
# def apply_scale(w, a, b):
# def logabsdiffexp(x, y):
#     def f(x, y):
# def logit_mean(x):
# def digest(x):
# def tree():
# def lift_tree(src, dst):
# def init_latex_rendering():
# def draw_confidence(a, m, S, levels = [0.95]):


# Path: BinaryMatrix.py
import numpy as np
    import ctypes
            import sys; sys.exit()
from scipy import optimize as opt
from Utility import logsumexp, logabsdiffexp, digest, apply_scale

    
Return the approximate nll of an observed binary matrix given
specified Bernoulli weights, conditioned on having the observed
margins.

Inputs:
  A: observed data, (m x n) binary matrix
  w: weight matrix, (m x n) matrix with values in (0, +infty)
Output:
  ncll: negative conditional log-likelihood
"""
    assert(A.shape == w.shape)

    r = A.sum(1, dtype=np.int)
    c = A.sum(0, dtype=np.int)

    r, c, arrays, _ = _prune(r, c, A, w)
    A, w = arrays

    # Sizing
    m, n = len(r), len(c)
    if (m == 0) or (n == 0):
        return 0.0

    # Sort the row margins (descending)
    rndx = np.argsort(-r)
    rsort = r[rndx]

    # Balance the weights
    a_scale, b_scale = canonical_scalings(w, r, c)

    wopt = apply_scale(w, a_scale, b_scale)