ProbabilisticLaneBasedRouteGenerator.java

package org.opentrafficsim.road.network.route;

import java.io.Serializable;
import java.util.List;

import nl.tudelft.simulation.jstats.distributions.DistUniform;
import nl.tudelft.simulation.jstats.streams.StreamInterface;

import org.opentrafficsim.core.network.NetworkException;

/**
 * <p>
 * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
 * <p>
 * $LastChangedDate: 2015-07-26 01:01:13 +0200 (Sun, 26 Jul 2015) $, @version $Revision: 1155 $, by $Author: averbraeck $,
 * initial version 20 Mar 2015 <br>
 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
 */
public class ProbabilisticLaneBasedRouteGenerator implements LaneBasedRouteGenerator
{
    /** The list of RouteProbability. */
    private final List<LaneBasedRouteProbability> laneBasedRouteProbabilities;

    /** Cumulative probabilities or frequencies corresponding to the routes. */
    private final double[] cumulativeProbabilities;

    /** The uniform random generator used to select from routes. */
    private final DistUniform random;

    /**
     * Construct a new ProbabilistiRouteGenerator using the given random stream.
     * @param laneBasedRouteProbabilities the Routes with the probabilities for each one. Instead of probabilities, (observed)
     *            frequencies may be used; i.e. the provided values are internally scaled to add up to 1.0.
     * @param stream the random stream to use
     * @throws NetworkException when the probabilities or frequencies are invalid (negative, or all zero)
     */
    public ProbabilisticLaneBasedRouteGenerator(final List<LaneBasedRouteProbability> laneBasedRouteProbabilities,
        final StreamInterface stream) throws NetworkException
    {
        double sum = 0;
        for (LaneBasedRouteProbability rp : laneBasedRouteProbabilities)
        {
            double frequency = rp.getProbability();
            if (frequency < 0)
            {
                throw new NetworkException("Negative probability or frequency is not allowed (got " + frequency + ")");
            }
            sum += frequency;
        }
        if (0 == sum)
        {
            throw new NetworkException("Sum of probabilities or freqencies must be > 0");
        }
        this.cumulativeProbabilities = new double[laneBasedRouteProbabilities.size()];
        int index = 0;
        double cumFreq = 0.0;
        for (LaneBasedRouteProbability rp : laneBasedRouteProbabilities)
        {
            double frequency = rp.getProbability();
            cumFreq += frequency;
            this.cumulativeProbabilities[index++] = cumFreq / sum;
        }
        this.random = new DistUniform(stream, 0, 1);
        this.laneBasedRouteProbabilities = laneBasedRouteProbabilities;
    }

    /** {@inheritDoc} */
    @Override
    public final CompleteLaneBasedRouteNavigator generateRouteNavigator()
    {
        double randomValue = this.random.draw();
        for (int index = 0; index < this.cumulativeProbabilities.length; index++)
        {
            if (this.cumulativeProbabilities[index] >= randomValue)
            {
                return this.laneBasedRouteProbabilities.get(index).getRouteNavigator();
            }
        }
        return this.laneBasedRouteProbabilities.get(0).getRouteNavigator();
    }

    /**
     * Combination of route and probability or frequency.
     * <p>
     * Copyright (c) 2013-2015 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br>
     * All rights reserved. <br>
     * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
     * <p>
     * @version Jul 22, 2015 <br>
     * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
     * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
     * @author <a href="http://www.citg.tudelft.nl">Guus Tamminga</a>
     */
    public static class LaneBasedRouteProbability implements Serializable
    {
        /** */
        private static final long serialVersionUID = 20150722L;

        /** the route navigator. */
        private final CompleteLaneBasedRouteNavigator laneBasedRouteNavigator;

        /** the probability or frequency of the route. */
        private final double probability;

        /**
         * @param routeNavigator the route navigator.
         * @param probability the probability or frequency of the route.
         */
        public LaneBasedRouteProbability(final CompleteLaneBasedRouteNavigator routeNavigator, final double probability)
        {
            super();
            this.laneBasedRouteNavigator = routeNavigator;
            this.probability = probability;
        }

        /**
         * @return route.
         */
        public final CompleteLaneBasedRouteNavigator getRouteNavigator()
        {
            return this.laneBasedRouteNavigator;
        }

        /**
         * @return probability.
         */
        public final double getProbability()
        {
            return this.probability;
        }

    }
}