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

org.powertac.factoredcustomer.ProbabilityDistribution Maven / Gradle / Ivy

/* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an
* "AS IS" BASIS,  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

package org.powertac.factoredcustomer;

import java.util.Random;
import org.w3c.dom.*;
import org.apache.commons.math.MathException;
import org.apache.commons.math.distribution.*; 
import org.powertac.common.repo.RandomSeedRepo;
import org.powertac.common.spring.SpringApplicationContext;

/**
 * Container class for one a large set of probability distribution samplers.
 * The various samplers are implemented as nested classes.
 * 
 * @author Prashant Reddy
 */
final class ProbabilityDistribution
{       
    enum DistType { DEGENERATE, POINTMASS, UNIFORM, INTERVAL, NORMAL, GAUSSIAN, STDNORMAL, LOGNORMAL, 
                    CAUCHY, BETA, BINOMIAL, POISSON, CHISQUARED, EXPONENTIAL, GAMMA, WEIBULL, STUDENT, SNEDECOR }  

    private RandomSeedRepo randomSeedRepo;

    private static long distCounter = 0;
    private final long distId = ++distCounter;

    private final DistType type;
    private final Sampler sampler;
    private double param1, param2, param3, param4;
        
    
    ProbabilityDistribution(Element xml)
    {
        randomSeedRepo = (RandomSeedRepo) SpringApplicationContext.getBean("randomSeedRepo");

        type = Enum.valueOf(DistType.class, xml.getAttribute("distribution"));
        switch (type) {
        case POINTMASS:
        case DEGENERATE:
            param1 = Double.parseDouble(xml.getAttribute("value"));
            sampler = new DegenerateSampler(param1);
            break;
        case UNIFORM:
            param1 = Double.parseDouble(xml.getAttribute("low"));
            param2 = Double.parseDouble(xml.getAttribute("high"));
            sampler = new UniformSampler(param1, param2);
            break;
        case INTERVAL:
            param1 = Double.parseDouble(xml.getAttribute("mean"));
            param2 = Double.parseDouble(xml.getAttribute("stdDev"));
            param3 = Double.parseDouble(xml.getAttribute("low"));
            param4 = Double.parseDouble(xml.getAttribute("high")); 
            sampler = new IntervalSampler(param1, param2, param3, param4);
            break;
        case NORMAL:
        case GAUSSIAN:
            param1 = Double.parseDouble(xml.getAttribute("mean"));
            param2 = Double.parseDouble(xml.getAttribute("stdDev"));
            sampler = new ContinuousSampler(new NormalDistributionImpl(param1, param2));
            break;
        case STDNORMAL:
            param1 = 0; param2 = 1;
            sampler = new ContinuousSampler(new NormalDistributionImpl(param1, param2));
            break;
        case LOGNORMAL:
            param1 = Double.parseDouble(xml.getAttribute("expMean"));
            param2 = Double.parseDouble(xml.getAttribute("expStdDev"));
            sampler = new LogNormalSampler(param1, param2);
            break;         
        case CAUCHY:
            param1 = Double.parseDouble(xml.getAttribute("median"));
            param2 = Double.parseDouble(xml.getAttribute("scale"));
            sampler = new ContinuousSampler(new CauchyDistributionImpl(param1, param2));
            break;
        case BETA:
            param1 = Double.parseDouble(xml.getAttribute("alpha"));
            param2 = Double.parseDouble(xml.getAttribute("beta"));
            sampler = new ContinuousSampler(new BetaDistributionImpl(param1, param2));
            break;
        case BINOMIAL:
            param1 = Double.parseDouble(xml.getAttribute("trials"));
            param2 = Double.parseDouble(xml.getAttribute("success"));
            sampler = new DiscreteSampler(new BinomialDistributionImpl((int) param1, param2));
            break;
        case POISSON:
            param1 = Double.parseDouble(xml.getAttribute("lambda"));
            sampler = new DiscreteSampler(new PoissonDistributionImpl(param1));
            break;
        case CHISQUARED:
            param1 = Double.parseDouble(xml.getAttribute("dof"));
            sampler = new ContinuousSampler(new ChiSquaredDistributionImpl(param1));
            break;
        case EXPONENTIAL:
            param1 = Double.parseDouble(xml.getAttribute("mean"));
            sampler = new ContinuousSampler(new ExponentialDistributionImpl(param1));
            break;
        case GAMMA:
            param1 = Double.parseDouble(xml.getAttribute("alpha"));
            param2 = Double.parseDouble(xml.getAttribute("beta"));
            sampler = new ContinuousSampler(new GammaDistributionImpl(param1, param2));
            break;
        case WEIBULL:
            param1 = Double.parseDouble(xml.getAttribute("alpha"));
            param2 = Double.parseDouble(xml.getAttribute("beta"));
            sampler = new ContinuousSampler(new WeibullDistributionImpl(param1, param2));
            break;
        case STUDENT:
            param1 = Double.parseDouble(xml.getAttribute("dof"));
            sampler = new ContinuousSampler(new TDistributionImpl(param1));
            break;
        case SNEDECOR:
            param1 = Double.parseDouble(xml.getAttribute("d1"));
            param2 = Double.parseDouble(xml.getAttribute("d2"));
            sampler = new ContinuousSampler(new FDistributionImpl(param1, param2));
            break;
        default: throw new Error("Invalid probability distribution type!");
        } 
        sampler.reseedRandomGenerator(randomSeedRepo.getRandomSeed("factoredcustomer.ProbabilityDistribution", 
                                                                   distId, "Sampler").getValue());
    }
        
    double drawSample()
    {
        try {
            return sampler.sample();
        } 
        catch (MathException e) 
        {
            System.err.println("ProbabilityDistribution(" + toString() + ") - drawSample():" + toString() + " Caught MathException:\n");
            e.printStackTrace(System.err);
            throw new Error("ProbabilityDistribution(" + toString() + ") - drawSample(): Caught MathException: " + e.toString());
        }
    }
 
    @Override
    public String toString() 
    {
        return this.getClass().getCanonicalName() + ":" + distId + ":" + type + 
               "(" + param1 + ", " + param2 + ", " + param3 + ", " + param4 + ")";
    }

    
    ///////////////////////////// HELPER CLASSES //////////////////////////////

    interface Sampler
    {
        public void reseedRandomGenerator(long seed);
        
        public double sample() throws MathException;
    }
    
    final class DegenerateSampler implements Sampler
    {
        final double value;
        
        DegenerateSampler(double v) { value = v; }
        
        public void reseedRandomGenerator(long seed) {}
            
        public double sample()  throws MathException { return value; }
    }
    
    final class UniformSampler implements Sampler
    {
        final Random random;
        final double low;
        final int range;
        
        UniformSampler(double l, double h) 
        { 
            low = l; 
            range = safeLongToInt(Math.round(h - low));
            random = new Random();
        }
        
        public void reseedRandomGenerator(long seed)
        {
            random.setSeed(seed);
        }
        
        public double sample() throws MathException
        {
            return low + random.nextInt(range);
        }

        protected int safeLongToInt(long x) 
        {
            if (x < Integer.MIN_VALUE || x > Integer.MAX_VALUE) {
                throw new IllegalArgumentException(x + " cannot be cast to int without changing its value.");
            } else return (int) x;
        }
    }
    
    final class IntervalSampler implements Sampler
    {
        final double low;
        final double high;
        final NormalDistributionImpl normalSampler;

        IntervalSampler(double m, double s, double l, double h) 
        {
            normalSampler = new NormalDistributionImpl(m, s);
            low = l;
            high = h;
        }
        
        public void reseedRandomGenerator(long seed)
        {
            normalSampler.reseedRandomGenerator(seed);
        }
        
        public double sample() throws MathException
        {
            return Math.min(high, Math.max(low, normalSampler.sample()));
        }
    }
    
    final class LogNormalSampler implements Sampler
    {
        final NormalDistributionImpl normalSampler;

        LogNormalSampler(double m, double s) 
        {
            normalSampler = new NormalDistributionImpl(Math.log(m), Math.log(s));
        }
        
        public void reseedRandomGenerator(long seed)
        {
            normalSampler.reseedRandomGenerator(seed);
        }
        
        public double sample() throws MathException
        {
            return Math.exp(normalSampler.sample());
        }
    }
    
    final class DiscreteSampler implements Sampler
    {
        final AbstractIntegerDistribution impl;
        
        DiscreteSampler(AbstractIntegerDistribution i)
        {
            impl = i;
        }
        
        public void reseedRandomGenerator(long seed)
        {
            impl.reseedRandomGenerator(seed);
        }
        
        public double sample() throws MathException
        {
            return impl.sample();
        }
    }
    
    final class ContinuousSampler implements Sampler
    {
        final AbstractContinuousDistribution impl;
        
        ContinuousSampler(AbstractContinuousDistribution i)
        {
            impl = i;
        }
        
        public void reseedRandomGenerator(long seed)
        {
            impl.reseedRandomGenerator(seed);
        }
        
        public double sample() throws MathException
        {
            return impl.sample();
        }
    }
    
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy