001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math3.distribution; 018 019import org.apache.commons.math3.exception.NotStrictlyPositiveException; 020import org.apache.commons.math3.exception.OutOfRangeException; 021import org.apache.commons.math3.exception.util.LocalizedFormats; 022import org.apache.commons.math3.random.RandomGenerator; 023import org.apache.commons.math3.random.Well19937c; 024import org.apache.commons.math3.util.FastMath; 025 026/** 027 * This class implements the Laplace distribution. 028 * 029 * @see <a href="http://en.wikipedia.org/wiki/Laplace_distribution">Laplace distribution (Wikipedia)</a> 030 * 031 * @since 3.4 032 */ 033public class LaplaceDistribution extends AbstractRealDistribution { 034 035 /** Serializable version identifier. */ 036 private static final long serialVersionUID = 20141003; 037 038 /** The location parameter. */ 039 private final double mu; 040 /** The scale parameter. */ 041 private final double beta; 042 043 /** 044 * Build a new instance. 045 * <p> 046 * <b>Note:</b> this constructor will implicitly create an instance of 047 * {@link Well19937c} as random generator to be used for sampling only (see 048 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 049 * needed for the created distribution, it is advised to pass {@code null} 050 * as random generator via the appropriate constructors to avoid the 051 * additional initialisation overhead. 052 * 053 * @param mu location parameter 054 * @param beta scale parameter (must be positive) 055 * @throws NotStrictlyPositiveException if {@code beta <= 0} 056 */ 057 public LaplaceDistribution(double mu, double beta) { 058 this(new Well19937c(), mu, beta); 059 } 060 061 /** 062 * Build a new instance. 063 * 064 * @param rng Random number generator 065 * @param mu location parameter 066 * @param beta scale parameter (must be positive) 067 * @throws NotStrictlyPositiveException if {@code beta <= 0} 068 */ 069 public LaplaceDistribution(RandomGenerator rng, double mu, double beta) { 070 super(rng); 071 072 if (beta <= 0.0) { 073 throw new NotStrictlyPositiveException(LocalizedFormats.NOT_POSITIVE_SCALE, beta); 074 } 075 076 this.mu = mu; 077 this.beta = beta; 078 } 079 080 /** 081 * Access the location parameter, {@code mu}. 082 * 083 * @return the location parameter. 084 */ 085 public double getLocation() { 086 return mu; 087 } 088 089 /** 090 * Access the scale parameter, {@code beta}. 091 * 092 * @return the scale parameter. 093 */ 094 public double getScale() { 095 return beta; 096 } 097 098 /** {@inheritDoc} */ 099 public double density(double x) { 100 return FastMath.exp(-FastMath.abs(x - mu) / beta) / (2.0 * beta); 101 } 102 103 /** {@inheritDoc} */ 104 public double cumulativeProbability(double x) { 105 if (x <= mu) { 106 return FastMath.exp((x - mu) / beta) / 2.0; 107 } else { 108 return 1.0 - FastMath.exp((mu - x) / beta) / 2.0; 109 } 110 } 111 112 /** {@inheritDoc} */ 113 @Override 114 public double inverseCumulativeProbability(double p) throws OutOfRangeException { 115 if (p < 0.0 || p > 1.0) { 116 throw new OutOfRangeException(p, 0.0, 1.0); 117 } else if (p == 0) { 118 return Double.NEGATIVE_INFINITY; 119 } else if (p == 1) { 120 return Double.POSITIVE_INFINITY; 121 } 122 double x = (p > 0.5) ? -Math.log(2.0 - 2.0 * p) : Math.log(2.0 * p); 123 return mu + beta * x; 124 } 125 126 /** {@inheritDoc} */ 127 public double getNumericalMean() { 128 return mu; 129 } 130 131 /** {@inheritDoc} */ 132 public double getNumericalVariance() { 133 return 2.0 * beta * beta; 134 } 135 136 /** {@inheritDoc} */ 137 public double getSupportLowerBound() { 138 return Double.NEGATIVE_INFINITY; 139 } 140 141 /** {@inheritDoc} */ 142 public double getSupportUpperBound() { 143 return Double.POSITIVE_INFINITY; 144 } 145 146 /** {@inheritDoc} */ 147 public boolean isSupportLowerBoundInclusive() { 148 return false; 149 } 150 151 /** {@inheritDoc} */ 152 public boolean isSupportUpperBoundInclusive() { 153 return false; 154 } 155 156 /** {@inheritDoc} */ 157 public boolean isSupportConnected() { 158 return true; 159 } 160 161}