<commit_before>package eu.amidst.core.exponentialfamily;

import eu.amidst.core.database.DataInstance;
import eu.amidst.core.utils.ArrayVector;
import eu.amidst.core.utils.Vector;
import eu.amidst.core.variables.Variable;

import org.apache.commons.math.linear.*;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * Created by <EMAIL> on 08/12/14.
 */
public class EF_Normal_NormalParents extends EF_ConditionalDistribution  {

    int sizeSS;

    int nOfParents;

    public EF_Normal_NormalParents(Variable var_, List<Variable> parents_) {

        this.var = var_;
        this.parents = parents_;

        if (!var_.isGaussian())
            throw new UnsupportedOperationException("Creating a Normal|Normal EF distribution for a non-gaussian child variable.");

        for (Variable v : parents) {
            if (!v.isGaussian())
                throw new UnsupportedOperationException("Creating a Normal|Normal EF distribution for a non-gaussian parent variable.");
        }

        nOfParents = parents.size();
        sizeSS = nOfParents^2 + 3 * nOfParents + 2 ; // (n+1)^2 (covariance matrix of YX) + n (E(Y)) + 1 (E(X))

        this.var=var_;
        this.momentParameters = this.createEmtpyCompoundVector();
        this.naturalParameters = this.createEmtpyCompoundVector();
    }

    @Override
    public void updateNaturalFromMomentParameters() {

        /*
         * First step: means and convariances
         */
        CompoundVector globalMomentParam = (CompoundVector)this.momentParameters;
        double mean_X = globalMomentParam.getXYbaseMatrix().getEntry(0);
        RealVector mean_Y = globalMomentParam.getXYbaseMatrix().getSubVector(1,nOfParents);

        double cov_XX = globalMomentParam.getcovbaseMatrix().getEntry(0, 0) - mean_X*mean_X;
        RealMatrix cov_YY = globalMomentParam.getcovbaseMatrix().getSubMatrix(1, nOfParents, 1, nOfParents).
                            subtract(mean_Y.outerProduct(mean_Y));
        RealVector cov_XY = globalMomentParam.getcovbaseMatrix().getSubMatrix(0, 0, 1, nOfParents).getRowVector(0).
                            subtract(mean_Y.mapMultiply(mean_X));
        //RealVector cov_YX = cov_XY; //outerProduct transposes the vector automatically

        /*
         * Second step: betas and variance
         */
        RealMatrix cov_YYInverse = new LUDecompositionImpl(cov_YY).getSolver().getInverse();
        RealVector beta = cov_YYInverse.preMultiply(cov_XY);


        double beta_0 = mean_X - beta.dotProduct(mean_Y);
        double variance = cov_XX - beta.dotProduct(cov_XY);


        /*
         * Third step: natural parameters (5 in total)
         */

        /*
         * 1) theta_0
         */
        double theta_0 = beta_0 / variance;
        double[] theta_0array = {theta_0};

        /*
         * 2) theta_0Theta
         */
        double variance2Inv =  1.0/(2*variance);
        RealVector theta_0Theta = beta.mapMultiply(-beta_0 * variance2Inv);
        ((CompoundVector) this.naturalParameters).setXYbaseVector(new ArrayRealVector(theta_0array, theta_0Theta.getData()));

        /*
         * 3) theta_Minus1
         */
        double theta_Minus1 = -variance2Inv;

        /*
         * 4) theta_beta
         */
        RealVector theta_beta = beta.mapMultiply(1.0 / variance);

        /*
         * 5) theta_betaBeta
         */
        RealMatrix theta_betaBeta = beta.outerProduct(beta).scalarMultiply(-variance2Inv);

        /*
         * Store natural parameters
         */
        RealMatrix natural_XY = new Array2DRowRealMatrix(nOfParents+1,nOfParents+1);
        double[] theta_Minus1array = {theta_Minus1};
        RealVector covXY = new ArrayRealVector(theta_Minus1array, theta_beta.getData());
        natural_XY.setColumnVector(0, covXY);
        natural_XY.setRowVector(0, covXY);
        natural_XY.setSubMatrix(theta_betaBeta.getData(),1,1);
        ((CompoundVector) this.naturalParameters).setcovbaseVector(natural_XY);

    }

    @Override
    public void updateMomentFromNaturalParameters() {
        //throw new UnsupportedOperationException("Method not implemented yet!");
    }

    @Override
    public SufficientStatistics getSufficientStatistics(DataInstance data) {
        CompoundVector vectorSS = this.createEmtpyCompoundVector();

        double[] Xarray = {data.getValue(this.var)};

        double[] Yarray = this.parents.stream()
                                         .mapToDouble(w->data.getValue(w))
                                         .toArray();
        RealVector XYRealVector = new ArrayRealVector(Xarray,Yarray);
        vectorSS.setXYbaseVector(XYRealVector);

        RealMatrix covRealmatrix = XYRealVector.outerProduct(XYRealVector);

        vectorSS.setcovbaseVector(covRealmatrix);

        return vectorSS;
    }

    @Override
    public int sizeOfSufficientStatistics() {
        return sizeSS;
    }



    @Override
    public double computeLogBaseMeasure(DataInstance dataInstance) {
        return -0.5*Math.log(2*Math.PI);
    }

    @Override
    public double computeLogNormalizer() {
        CompoundVector globalNaturalParameters = (CompoundVector)this.naturalParameters;
        double theta_0 = globalNaturalParameters.get(0);
        double theta_Minus1 = globalNaturalParameters.getcovbaseMatrix().getEntry(0,0);
        double variance = -0.5/theta_Minus1;
        double beta_0 = theta_0 * variance;

        return (beta_0*beta_0)/(2*variance) + 0.5*Math.log(variance);
    }

    @Override
    public CompoundVector createZeroedVector() {
        return new CompoundVector(nOfParents);
    }

    @Override
    public double getExpectedLogNormalizer(Map<Variable, MomentParameters> momentParents) {
        return 0;
    }

    @Override
    public NaturalParameters getExpectedNaturalFromParents(Map<Variable, MomentParameters> momentParents) {
        return null;
    }

    @Override
    public NaturalParameters getExpectedNaturalToParent(Variable parent, Map<Variable, MomentParameters> momentChildCoParents) {<commit_msg>no message<commit_after>package eu.amidst.core.exponentialfamily;

import eu.amidst.core.database.DataInstance;
import eu.amidst.core.utils.ArrayVector;
import eu.amidst.core.utils.Vector;
import eu.amidst.core.variables.Assignment;
import eu.amidst.core.variables.Variable;

import org.apache.commons.math.linear.*;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * Created by <EMAIL> on 08/12/14.
 */
public class EF_Normal_NormalParents extends EF_ConditionalDistribution  {

    int sizeSS;

    int nOfParents;

    public EF_Normal_NormalParents(Variable var_, List<Variable> parents_) {

        this.var = var_;
        this.parents = parents_;

        if (!var_.isGaussian())
            throw new UnsupportedOperationException("Creating a Normal|Normal EF distribution for a non-gaussian child variable.");

        for (Variable v : parents) {
            if (!v.isGaussian())
                throw new UnsupportedOperationException("Creating a Normal|Normal EF distribution for a non-gaussian parent variable.");
        }

        nOfParents = parents.size();
        sizeSS = nOfParents^2 + 3 * nOfParents + 2 ; // (n+1)^2 (covariance matrix of YX) + n (E(Y)) + 1 (E(X))

        this.var=var_;
        this.momentParameters = this.createEmtpyCompoundVector();
        this.naturalParameters = this.createEmtpyCompoundVector();
    }

    @Override
    public void updateNaturalFromMomentParameters() {

        /*
         * First step: means and convariances
         */
        CompoundVector globalMomentParam = (CompoundVector)this.momentParameters;
        double mean_X = globalMomentParam.getXYbaseMatrix().getEntry(0);
        RealVector mean_Y = globalMomentParam.getXYbaseMatrix().getSubVector(1,nOfParents);

        double cov_XX = globalMomentParam.getcovbaseMatrix().getEntry(0, 0) - mean_X*mean_X;
        RealMatrix cov_YY = globalMomentParam.getcovbaseMatrix().getSubMatrix(1, nOfParents, 1, nOfParents).
                            subtract(mean_Y.outerProduct(mean_Y));
        RealVector cov_XY = globalMomentParam.getcovbaseMatrix().getSubMatrix(0, 0, 1, nOfParents).getRowVector(0).
                            subtract(mean_Y.mapMultiply(mean_X));
        //RealVector cov_YX = cov_XY; //outerProduct transposes the vector automatically

        /*
         * Second step: betas and variance
         */
        RealMatrix cov_YYInverse = new LUDecompositionImpl(cov_YY).getSolver().getInverse();
        RealVector beta = cov_YYInverse.preMultiply(cov_XY);


        double beta_0 = mean_X - beta.dotProduct(mean_Y);
        double variance = cov_XX - beta.dotProduct(cov_XY);


        /*
         * Third step: natural parameters (5 in total)
         */

        /*
         * 1) theta_0
         */
        double theta_0 = beta_0 / variance;
        double[] theta_0array = {theta_0};

        /*
         * 2) theta_0Theta
         */
        double variance2Inv =  1.0/(2*variance);
        RealVector theta_0Theta = beta.mapMultiply(-beta_0 * variance2Inv);
        ((CompoundVector) this.naturalParameters).setXYbaseVector(new ArrayRealVector(theta_0array, theta_0Theta.getData()));

        /*
         * 3) theta_Minus1
         */
        double theta_Minus1 = -variance2Inv;

        /*
         * 4) theta_beta
         */
        RealVector theta_beta = beta.mapMultiply(1.0 / variance);

        /*
         * 5) theta_betaBeta
         */
        RealMatrix theta_betaBeta = beta.outerProduct(beta).scalarMultiply(-variance2Inv);

        /*
         * Store natural parameters
         */
        RealMatrix natural_XY = new Array2DRowRealMatrix(nOfParents+1,nOfParents+1);
        double[] theta_Minus1array = {theta_Minus1};
        RealVector covXY = new ArrayRealVector(theta_Minus1array, theta_beta.getData());
        natural_XY.setColumnVector(0, covXY);
        natural_XY.setRowVector(0, covXY);
        natural_XY.setSubMatrix(theta_betaBeta.getData(),1,1);
        ((CompoundVector) this.naturalParameters).setcovbaseVector(natural_XY);

    }

    @Override
    public void updateMomentFromNaturalParameters() {
        //throw new UnsupportedOperationException("Method not implemented yet!");
    }

    @Override
    public SufficientStatistics getSufficientStatistics(DataInstance data) {
        CompoundVector vectorSS = this.createEmtpyCompoundVector();

        double[] Xarray = {data.getValue(this.var)};

        double[] Yarray = this.parents.stream()
                                         .mapToDouble(w->data.getValue(w))
                                         .toArray();
        RealVector XYRealVector = new ArrayRealVector(Xarray,Yarray);
        vectorSS.setXYbaseVector(XYRealVector);

        RealMatrix covRealmatrix = XYRealVector.outerProduct(XYRealVector);

        vectorSS.setcovbaseVector(covRealmatrix);

        return vectorSS;
    }

    @Override
    public int sizeOfSufficientStatistics() {
        return sizeSS;
    }



    @Override
    public double computeLogBaseMeasure(DataInstance dataInstance) {
        return -0.5*Math.log(2*Math.PI);
    }

    @Override
    public double computeLogNormalizer() {
        CompoundVector globalNaturalParameters = (CompoundVector)this.naturalParameters;
        double theta_0 = globalNaturalParameters.get(0);
        double theta_Minus1 = globalNaturalParameters.getcovbaseMatrix().getEntry(0,0);
        double variance = -0.5/theta_Minus1;
        double beta_0 = theta_0 * variance;

        return (beta_0*beta_0)/(2*variance) + 0.5*Math.log(variance);
    }

    @Override
    public CompoundVector createZeroedVector() {
        return new CompoundVector(nOfParents);
    }

    @Override
    public double getExpectedLogNormalizer(Map<Variable, MomentParameters> momentParents) {
        return 0;
    }

    @Override
    public NaturalParameters getExpectedNaturalFromParents(Map<Variable, MomentParameters> momentParents) {
        return null;
    }

    @Override
    public NaturalParameters getExpectedNaturalToParent(Variable parent, Map<Variable, MomentParameters> momentChildCoParents) {
        return null;
    }

    @Override
    public EF_UnivariateDistribution getEmptyEFUnivariateDistribution() {
        return null;
    }

    @Override
    public EF_UnivariateDistribution getEFUnivariateDistribution(Assignment assignment) {
{'fraction_non_alphanumeric': 0.0962511037970619, 'fraction_numerical': 0.012683631693024002, 'mean_word_length': 2.7490219681011134, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6205106', 'n_tokens_mistral': 3760, 'n_tokens_neox': 3500, 'n_words': 680}