All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.sandia.cognition.statistics.AbstractDataDistribution Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * File:                AbstractDataDistribution.java
 * Authors:             Kevin R. Dixon
 * Company:             Sandia National Laboratories
 * Project:             Cognitive Foundry
 * 
 * Copyright Apr 25, 2011, Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
 * license for use of this work by or on behalf of the U.S. Government.
 * Export of this program may require a license from the United States
 * Government. See CopyrightHistory.txt for complete details.
 * 
 */

package gov.sandia.cognition.statistics;

import gov.sandia.cognition.collection.AbstractMutableDoubleMap;
import gov.sandia.cognition.collection.ScalarMap;
import gov.sandia.cognition.math.matrix.DefaultInfiniteVector;
import gov.sandia.cognition.math.matrix.InfiniteVector;
import gov.sandia.cognition.math.MathUtil;
import gov.sandia.cognition.math.MutableDouble;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * An abstract implementation of the {@code DataDistribution} interface.
 *
 * @param 
 *       The type of data stored at the indices, the hash keys.
 * @author  Justin Basilico
 * @author  Kevin R. Dixon
 * @since   3.3.0
 */
public abstract class AbstractDataDistribution
    extends AbstractMutableDoubleMap
    implements DataDistribution
{

    /**
     * Creates a new {@code AbstractDataDistribution}.
     * @param map
     * Map that stores the data
     */
    public AbstractDataDistribution(
        final Map map )
    {
        super( map );
    }

    @Override
    @SuppressWarnings("unchecked")
    public AbstractDataDistribution clone()
    {
        return (AbstractDataDistribution) super.clone();
    }

    @Override
    public int getDomainSize()
    {
        return this.map.size();
    }

    @Override
    public double getEntropy()
    {
        double entropy = 0.0;
        final double total = this.getTotal();
        final double denom = (total != 0.0) ? total : 1.0;
        for (ScalarMap.Entry entry : this.entrySet())
        {
            double p = entry.getValue() / denom;
            if (p != 0.0)
            {
                entropy -= p * MathUtil.log2(p);
            }
        }
        return entropy;
    }

    @Override
    public double getLogFraction(
        KeyType key)
    {
        final double total = this.getTotal();
        return (total != 0.0) ? (Math.log(this.get(key)) - Math.log(total))
            : Double.NEGATIVE_INFINITY;
    }

    @Override
    public double getFraction(
        KeyType key)
    {
        final double total = this.getTotal();
        return (total != 0.0) ? (this.get(key) / this.getTotal()) : 0.0;
    }

    @Override
    public KeyType sample(
        final Random random)
    {
        double w = random.nextDouble() * this.getTotal();
        for (ScalarMap.Entry entry : this.entrySet())
        {
            w -= entry.getValue();
            if (w <= 0.0)
            {
                return entry.getKey();
            }
        }
        return null;
    }

    @Override
    public ArrayList sample(
        final Random random,
        final int numSamples)
    {
        final ArrayList result = new ArrayList(numSamples);
        this.sampleInto(random, numSamples, result);
        return result;
    }

    @Override
    public void sampleInto(
        final Random random,
        final int sampleCount,
        final Collection output)
    {
        // Compute the cumulative weights
        final int size = this.getDomainSize();
        double[] cumulativeWeights = new double[size];
        double cumulativeSum = 0.0;
        ArrayList domain = new ArrayList(size);
        int index = 0;
        for (ScalarMap.Entry entry : this.entrySet())
        {
            domain.add(entry.getKey());
            final double value = entry.getValue();
            cumulativeSum += value;
            cumulativeWeights[index] = cumulativeSum;
            index++;
        }
        
        ProbabilityMassFunctionUtil.sampleMultipleInto(
            cumulativeWeights, domain, random, sampleCount, output);
    }

    @Override
    public InfiniteVector toInfiniteVector()
    {
        final DefaultInfiniteVector result =
            new DefaultInfiniteVector(this.size());

        for (ScalarMap.Entry entry : this.entrySet())
        {
            result.set(entry.getKey(), entry.getValue());
        }

        return result;
    }

    @Override
    public void fromInfiniteVector(
        final InfiniteVector vector)
    {
        this.clear();

        for (ScalarMap.Entry entry : vector.entrySet())
        {
            this.set(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public double getMaxValue()
    {
        double result = super.getMaxValue();
        if( result == Double.NEGATIVE_INFINITY )
        {
            return 0.0;
        }
        else
        {
            return result;
        }
    }

    @Override
    public double getMinValue()
    {
        double result = super.getMinValue();
        if( result == Double.POSITIVE_INFINITY )
        {
            return 0.0;
        }
        else
        {
            return result;
        }
    }

    @Override
    public Set getDomain()
    {
        return this.keySet();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy