Convex Optimization page 208

An example from Convex Optimization page 208

The original equation:

placeholder

I❤️LA implementation:

`I(X;Y)` = ∑_i ∑_j x_j p_i,j log₂(p_i,j/∑_k x_k p_i,k)

where

x ∈ ℝ^n
p ∈ ℝ^(m×n)

I❤️LA compiled to C++/Eigen:

/*
`I(X;Y)` = ∑_i ∑_j x_j p_i,j log₂(p_i,j/∑_k x_k p_i,k)

where

x ∈ ℝ^n
p ∈ ℝ^(m×n)
*/
#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <iostream>
#include <set>

struct convex_optimization_208ResultType {
    double I_left_parenthesis_X_semicolon_Y_right_parenthesis;
    convex_optimization_208ResultType(const double & I_left_parenthesis_X_semicolon_Y_right_parenthesis)
    : I_left_parenthesis_X_semicolon_Y_right_parenthesis(I_left_parenthesis_X_semicolon_Y_right_parenthesis)
    {}
};

convex_optimization_208ResultType convex_optimization_208(
    const Eigen::VectorXd & x,
    const Eigen::MatrixXd & p)
{
    const long n = x.size();
    const long m = p.rows();
    assert( p.cols() == n );

    double sum_0 = 0;
    for(int i=1; i<=p.rows(); i++){
        double sum_1 = 0;
        for(int j=1; j<=x.size(); j++){
            double sum_2 = 0;
            for(int k=1; k<=p.cols(); k++){
                sum_2 += x[k-1] * p(i-1, k-1);
            }
            sum_1 += x[j-1] * p(i-1, j-1) * (log10(p(i-1, j-1) / double(sum_2)) / log10(2));
        }
        sum_0 += sum_1;
    }
    double I_left_parenthesis_X_semicolon_Y_right_parenthesis = sum_0;

    return convex_optimization_208ResultType(I_left_parenthesis_X_semicolon_Y_right_parenthesis);
}


void generateRandomData(Eigen::VectorXd & x,
    Eigen::MatrixXd & p)
{
    const int n = rand()%10;
    const int m = rand()%10;
    x = Eigen::VectorXd::Random(n);
    p = Eigen::MatrixXd::Random(m, n);
}


int main(int argc, char *argv[])
{
    srand((int)time(NULL));
    Eigen::VectorXd x;
    Eigen::MatrixXd p;
    generateRandomData(x, p);
    convex_optimization_208ResultType func_value = convex_optimization_208(x, p);
    std::cout<<"return value:\n"<<func_value.I_left_parenthesis_X_semicolon_Y_right_parenthesis<<std::endl;
    return 0;
}

I❤️LA compiled to Python/NumPy/SciPy:

"""
`I(X;Y)` = ∑_i ∑_j x_j p_i,j log₂(p_i,j/∑_k x_k p_i,k)

where

x ∈ ℝ^n
p ∈ ℝ^(m×n)
"""
import numpy as np
import scipy
import scipy.linalg
from scipy import sparse
from scipy.integrate import quad
from scipy.optimize import minimize


class convex_optimization_208ResultType:
    def __init__( self, I_left_parenthesis_X_semicolon_Y_right_parenthesis):
        self.I_left_parenthesis_X_semicolon_Y_right_parenthesis = I_left_parenthesis_X_semicolon_Y_right_parenthesis


def convex_optimization_208(x, p):
    x = np.asarray(x, dtype=np.float64)
    p = np.asarray(p, dtype=np.float64)

    n = x.shape[0]
    m = p.shape[0]
    assert x.shape == (n,)
    assert p.shape == (m, n)

    sum_0 = 0
    for i in range(1, p.shape[0]+1):
        sum_1 = 0
        for j in range(1, len(x)+1):
            sum_2 = 0
            for k in range(1, p.shape[1]+1):
                sum_2 += x[k-1] * p[i-1, k-1]
            sum_1 += x[j-1] * p[i-1, j-1] * np.log2(p[i-1, j-1] / sum_2)
        sum_0 += sum_1
    I_left_parenthesis_X_semicolon_Y_right_parenthesis = sum_0
    return convex_optimization_208ResultType(I_left_parenthesis_X_semicolon_Y_right_parenthesis)


def generateRandomData():
    n = np.random.randint(10)
    m = np.random.randint(10)
    x = np.random.randn(n)
    p = np.random.randn(m, n)
    return x, p


if __name__ == '__main__':
    x, p = generateRandomData()
    print("x:", x)
    print("p:", p)
    func_value = convex_optimization_208(x, p)
    print("return value: ", func_value.I_left_parenthesis_X_semicolon_Y_right_parenthesis)

I❤️LA compiled to MATLAB:

function output = convex_optimization_208(x, p)
% output = convex_optimization_208(x, p)
%
%    `I(X;Y)` = ∑_i ∑_j x_j p_i,j log₂(p_i,j/∑_k x_k p_i,k)
%    
%    where
%    
%    x ∈ ℝ^n
%    p ∈ ℝ^(m×n)
    if nargin==0
        warning('generating random input data');
        [x, p] = generateRandomData();
    end
    function [x, p] = generateRandomData()
        n = randi(10);
        m = randi(10);
        x = randn(n,1);
        p = randn(m, n);
    end

    x = reshape(x,[],1);

    n = size(x, 1);
    m = size(p, 1);
    assert( numel(x) == n );
    assert( isequal(size(p), [m, n]) );

    sum_0 = 0;
    for i = 1:size(p,1)
        sum_1 = 0;
        for j = 1:size(x,1)
            sum_2 = 0;
            for k = 1:size(p,2)
                sum_2 = sum_2 + x(k) * p(i, k);
            end
            sum_1 = sum_1 + x(j) * p(i, j) * log2(p(i, j) / sum_2);
        end
        sum_0 = sum_0 + sum_1;
    end
    I_X_semicolon_Y = sum_0;
    output.I_X_semicolon_Y = I_X_semicolon_Y;
end

I❤️LA compiled to LaTeX:

\documentclass[12pt]{article}
\usepackage{mathdots}
\usepackage[bb=boondox]{mathalfa}
\usepackage{mathtools}
\usepackage{amssymb}
\usepackage{libertine}
\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}
\usepackage[paperheight=8in,paperwidth=4in,margin=.3in,heightrounded]{geometry}
\let\originalleft\left
\let\originalright\right
\renewcommand{\left}{\mathopen{}\mathclose\bgroup\originalleft}
\renewcommand{\right}{\aftergroup\egroup\originalright}
\begin{document}

\begin{center}
\resizebox{\textwidth}{!} 
{
\begin{minipage}[c]{\textwidth}
\begin{align*}
\textit{I(X;Y)} & = \sum_\mathit{i} \sum_\mathit{j} \mathit{x}_{ \mathit{j} }\mathit{p}_{\mathit{i}, \mathit{j}} \log_2{ \frac{\mathit{p}_{\mathit{i}, \mathit{j}}}{\sum_\mathit{k} \mathit{x}_{ \mathit{k} }\mathit{p}_{\mathit{i}, \mathit{k}}} } \\
\intertext{where} 
\mathit{x} & \in \mathbb{R}^{ \mathit{n}} \\
\mathit{p} & \in \mathbb{R}^{ \mathit{m} \times \mathit{n} } \\
\\
\end{align*}
\end{minipage}
}
\end{center}

\end{document}

I❤️LA LaTeX output: