<commit_before>/*
 * OrderedLatentLiabilityLikelihood.java
 *
 * Copyright (c) 2002-2015 <NAME>, <NAME> and <NAME>
 *
 * This file is part of BEAST.
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership and licensing.
 *
 * BEAST is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 *  BEAST 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with BEAST; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package dr.evomodel.continuous;

import dr.evolution.alignment.PatternList;
import dr.evolution.tree.NodeRef;
import dr.evomodel.tree.TreeModel;
import dr.inference.model.*;
import dr.math.distributions.Distribution;
import dr.util.Citable;
import dr.util.Citation;
import dr.util.CommonCitations;
import dr.xml.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;


/**
 * A class to model multivariate ordered data as realizations from a latent (liability) multivariate Brownian diffusion
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 * @version $Id$
 */

public class OrderedLatentLiabilityLikelihood extends AbstractModelLikelihood implements LatentTruncation, Citable, SoftThresholdLikelihood {

    public final static String ORDERED_LATENT_LIABILITY_LIKELIHOOD = "orderedLatentLiabilityLikelihood";

    public OrderedLatentLiabilityLikelihood(TreeModel treeModel, PatternList patternList, CompoundParameter tipTraitParameter, CompoundParameter thresholdParameter, Parameter numClasses, boolean isUnordered) {
        super(ORDERED_LATENT_LIABILITY_LIKELIHOOD);
        this.treeModel = treeModel;
        this.patternList = patternList;
        this.tipTraitParameter = tipTraitParameter;
        this.thresholdParameter = thresholdParameter;
        this.numClasses = numClasses;
        this.isUnordered = isUnordered;
        this.NAcode = setNAcode();

        addVariable(tipTraitParameter);
        addVariable(thresholdParameter);

        setTipDataValuesForAllNodes();

        StringBuilder sb = new StringBuilder();
        sb.append("Constructing a latent liability likelihood model:\n");
        sb.append("\tBinary patterns: ").append(patternList.getId()).append("\n");
        sb.append("\tPlease cite:\n").append(Citable.Utils.getCitationString(this));
        Logger.getLogger("dr.evomodel.continous").info(sb.toString());
    }

    public CompoundParameter getTipTraitParameter() {
        return tipTraitParameter;
    }

    public PatternList getPatternList() {
        return patternList;
    }

    private void setTipDataValuesForAllNodes() {
        if (tipData == null) {
            tipData = new int[treeModel.getExternalNodeCount()][patternList.getPatternCount()];
        }

        final int dim = tipTraitParameter.getParameter(0).getDimension();

        double[] upperBoundsOneNode = new double[dim];
        double[] lowerBoundsOneNode = new double[dim];
        double[] upperBoundsAllNodes = new double[dim * treeModel.getExternalNodeCount()];
        double[] lowerBoundsAllNodes = new double[dim * treeModel.getExternalNodeCount()];

        for (int i = 0; i < treeModel.getExternalNodeCount(); i++) {

            NodeRef node = treeModel.getExternalNode(i);
            String id = treeModel.getTaxonId(i);
            int index = patternList.getTaxonIndex(id);
            setTipDataValueForNodeAndGetBounds(node, index, upperBoundsOneNode,lowerBoundsOneNode);

            System.arraycopy(upperBoundsOneNode, 0, upperBoundsAllNodes, i*dim, dim);
            System.arraycopy(lowerBoundsOneNode, 0, lowerBoundsAllNodes, i*dim, dim);

            tipTraitParameter.addBounds(new Parameter.DefaultBounds(upperBoundsAllNodes,lowerBoundsAllNodes));

            if (DEBUG) {
                System.err.println("\t For node: " + i + " with ID " + id + " you get taxon " + index + " with ID " + patternList.getTaxonId(index));
            }
        }

        if (DEBUG) {
            Bounds<Double> bounds = tipTraitParameter.getBounds();
            for (int i = 0; i < tipTraitParameter.getDimension(); ++i) {
                double value = tipTraitParameter.getParameterValue(i);
                if (value <= bounds.getLowerLimit(i) || value >= bounds.getUpperLimit(i)) {
                    System.err.println("tipTrait error: " + i);
                    System.exit(-1);
                }
            }

            System.err.println("Setup bounds correctly");
        }
    }

    private void setTipDataValueForNodeAndGetBounds(NodeRef node, int index, double[] upperBounds, double[] lowerBounds) {

        final int Nindex = node.getNumber();

        // TODO - This class appears to work for only binary data; how does it handle ordered-multistate data?

        for (int datum = 0; datum < patternList.getPatternCount(); ++datum) {
            tipData[Nindex][datum] = patternList.getPattern(datum)[index];

            switch(tipData[Nindex][datum]) {
                case 0:
                    upperBounds[datum] = 0;
                    lowerBounds[datum] = Double.NEGATIVE_INFINITY;
                    break;
                case 1:
                    upperBounds[datum] = Double.POSITIVE_INFINITY;
                    lowerBounds[datum] = 0;
                    break;
                default:
                    upperBounds[datum] = Double.POSITIVE_INFINITY;
                    lowerBounds[datum] = Double.NEGATIVE_INFINITY;
                    break;
            }
        }

        tipTraitParameter.getParameter(Nindex).addBounds(new Parameter.DefaultBounds(upperBounds,lowerBounds));
        //what these bounds in "ParameterProxy" do?
    }

    @Override
    protected void handleModelChangedEvent(Model model, Object object, int index) {
    }

    @Override
    protected void handleVariableChangedEvent(Variable variable, int index, Variable.ChangeType type) {
        likelihoodKnown = false;<commit_msg>revert changes in adding bounds in liabilitylikelihood<commit_after>/*
 * OrderedLatentLiabilityLikelihood.java
 *
 * Copyright (c) 2002-2015 <NAME>, <NAME> and <NAME>
 *
 * This file is part of BEAST.
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership and licensing.
 *
 * BEAST is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 *  BEAST 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with BEAST; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA  02110-1301  USA
 */

package dr.evomodel.continuous;

import dr.evolution.alignment.PatternList;
import dr.evolution.tree.NodeRef;
import dr.evomodel.tree.TreeModel;
import dr.inference.model.*;
import dr.math.distributions.Distribution;
import dr.util.Citable;
import dr.util.Citation;
import dr.util.CommonCitations;
import dr.xml.*;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;


/**
 * A class to model multivariate ordered data as realizations from a latent (liability) multivariate Brownian diffusion
 *
 * @author <NAME>
 * @author <NAME>
 * @author <NAME>
 * @version $Id$
 */

public class OrderedLatentLiabilityLikelihood extends AbstractModelLikelihood implements LatentTruncation, Citable, SoftThresholdLikelihood {

    public final static String ORDERED_LATENT_LIABILITY_LIKELIHOOD = "orderedLatentLiabilityLikelihood";

    public OrderedLatentLiabilityLikelihood(TreeModel treeModel, PatternList patternList, CompoundParameter tipTraitParameter, CompoundParameter thresholdParameter, Parameter numClasses, boolean isUnordered) {
        super(ORDERED_LATENT_LIABILITY_LIKELIHOOD);
        this.treeModel = treeModel;
        this.patternList = patternList;
        this.tipTraitParameter = tipTraitParameter;
        this.thresholdParameter = thresholdParameter;
        this.numClasses = numClasses;
        this.isUnordered = isUnordered;
        this.NAcode = setNAcode();

        addVariable(tipTraitParameter);
        addVariable(thresholdParameter);

        setTipDataValuesForAllNodes();

        StringBuilder sb = new StringBuilder();
        sb.append("Constructing a latent liability likelihood model:\n");
        sb.append("\tBinary patterns: ").append(patternList.getId()).append("\n");
        sb.append("\tPlease cite:\n").append(Citable.Utils.getCitationString(this));
        Logger.getLogger("dr.evomodel.continous").info(sb.toString());
    }

    public CompoundParameter getTipTraitParameter() {
        return tipTraitParameter;
    }

    public PatternList getPatternList() {
        return patternList;
    }

    private void setTipDataValuesForAllNodes() {
        if (tipData == null) {
            tipData = new int[treeModel.getExternalNodeCount()][patternList.getPatternCount()];
        }
        for (int i = 0; i < treeModel.getExternalNodeCount(); i++) {
            NodeRef node = treeModel.getExternalNode(i);
            String id = treeModel.getTaxonId(i);
            int index = patternList.getTaxonIndex(id);
            setTipDataValuesForNode(node, index);

            if (DEBUG) {
                System.err.println("\t For node: " + i + " with ID " + id + " you get taxon " + index + " with ID " + patternList.getTaxonId(index));
            }
        }

        if (DEBUG) {
            Bounds<Double> bounds = tipTraitParameter.getBounds();
            for (int i = 0; i < tipTraitParameter.getDimension(); ++i) {
                double value = tipTraitParameter.getParameterValue(i);
                if (value <= bounds.getLowerLimit(i) || value >= bounds.getUpperLimit(i)) {
                    System.err.println("tipTrait error: " + i);
                    System.exit(-1);
                }
            }

            System.err.println("Setup bounds correctly");
        }
    }

    private void setTipDataValuesForNode(NodeRef node, int index) {
        // Set tip data values
        final int Nindex = node.getNumber();
        final int dim = tipTraitParameter.getParameter(0).getDimension();

        // TODO - This class appears to work for only binary data; how does it handle ordered-multistate data?

        // boolean isBinary = patternList.getDataType() == TwoStates.INSTANCE;

        double[] upperBounds = new double[dim];
        double[] lowerBounds = new double[dim];

        for (int datum = 0; datum < patternList.getPatternCount(); ++datum) {
            tipData[Nindex][datum] = (int) patternList.getPattern(datum)[index];

            switch(tipData[Nindex][datum]) {
                case 0:
                    upperBounds[datum] = 0;
                    lowerBounds[datum] = Double.NEGATIVE_INFINITY;
                    break;
                case 1:
                    upperBounds[datum] = Double.POSITIVE_INFINITY;
                    lowerBounds[datum] = 0;
                    break;
                default:
                    upperBounds[datum] = Double.POSITIVE_INFINITY;
                    lowerBounds[datum] = Double.NEGATIVE_INFINITY;
                    break;
            }
        }

        tipTraitParameter.getParameter(Nindex).addBounds(new Parameter.DefaultBounds(upperBounds,lowerBounds));
    }

    @Override
    protected void handleModelChangedEvent(Model model, Object object, int index) {
    }

    @Override
    protected void handleVariableChangedEvent(Variable variable, int index, Variable.ChangeType type) {
        likelihoodKnown = false;
{'fraction_non_alphanumeric': 0.09232256505276726, 'fraction_numerical': 0.004833642149359542, 'mean_word_length': 2.8314814814814815, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2652724', 'n_tokens_mistral': 3451, 'n_tokens_neox': 3273, 'n_words': 901}