Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

183 lines (149 sloc) 5.523 kB
%%% This code was developped by IDEALX (http://IDEALX.org/) and
%%% contributors (their names can be found in the CONTRIBUTORS file).
%%% Copyright (C) 2000-2001 IDEALX
%%%
%%% This program is free software; you can redistribute it and/or modify
%%% it under the terms of the GNU General Public License as published by
%%% the Free Software Foundation; either version 2 of the License, or
%%% (at your option) any later version.
%%%
%%% This program 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 General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
%%%
%%% In addition, as a special exception, you have the permission to
%%% link the code of this program with any library released under
%%% the EPL license and distribute linked combinations including
%%% the two.
%%% Random Generators for several probability distributions
-module(ts_stats).
-created('Date: 2000/10/20 13:58:56 nniclausse Exp ').
-vc('$Id$ ').
-author('nicolas.niclausse@niclux.org').
-export([exponential/1, exponential/2, pareto/2,
normal/0, normal/1, normal/2, uniform/2,
invgaussian/2,
mean/1, mean/3,
variance/1,
meanvar/4,
meanvar_minmax/6,
stdvar/1]).
-import(math, [log/1, pi/0, sqrt/1, pow/2]).
-record(pareto, {a = 1 , beta}).
-record(normal, {mean = 0 , stddev= 1 }).
-record(invgaussian, {mu , lambda}).
%% get n samples from a function F with parameter Param
sample (F, Param, N) ->
sample(F, [], Param, N-1).
sample (F, X, Param, 0) ->
[F(Param) | X] ;
sample (F, X, Param, N) ->
sample(F, [F(Param)|X], Param, N-1 ).
uniform(Min,Max)->
Min+random:uniform(Max-Min+1)-1.
%% random sample from an exponential distribution
exponential(Param) ->
-math:log(random:uniform())/Param.
%% N samples from an exponential distribution
exponential(Param, N) ->
sample(fun(X) -> exponential(X) end , Param, N).
%% random sample from a Pareto distribution
pareto(#pareto{a=A, beta=Beta}) ->
A/(math:pow(random:uniform(), 1/Beta)).
%% if a list is given, construct a record for the parameters
pareto([A, Beta], N) ->
pareto(#pareto{a = A , beta = Beta }, N);
%% N samples from a Pareto distribution
pareto(Param, N) ->
sample(fun(X) -> pareto(X) end , Param, N).
invgaussian([Mu,Lambda],N) ->
invgaussian(#invgaussian{mu=Mu,lambda=Lambda},N);
invgaussian(Param,N) ->
sample(fun(X) -> invgaussian(X) end , Param, N).
%% random sample from a Inverse Gaussian distribution
invgaussian(#invgaussian{mu=Mu, lambda=Lambda}) ->
Y = Mu*pow(normal(), 2),
X1 = Mu+Mu*Y/(2*Lambda)-Mu*sqrt(4*Lambda*Y+pow(Y,2))/(2*Lambda),
U = random:uniform(),
X = (Mu/(Mu+X1))-U,
case X >=0 of
true -> X1;
false -> Mu*Mu/X1
end.
normal() ->
[Val] = normal(#normal{},1),
Val.
normal([Mean,StdDev],N) ->
normal(#normal{mean=Mean,stddev=StdDev},N);
normal(Param,N) ->
sample(fun(X) -> normal(X) end , Param, N).
normal(N) when is_integer(N)->
normal(#normal{},N);
normal(#normal{mean=M,stddev=S}) ->
normal_boxm(M,S,0,0,1).
%%% use the polar form of the Box-Muller transformation
normal_boxm(M,S,X1,_X2,W) when W < 1->
W2 = sqrt( (-2.0 * log( W ) ) / W ),
Y1 = X1 * W2,
M + Y1 * S;
normal_boxm(M,S,_,_,_W) ->
X1 = 2.0 * random:uniform() - 1.0,
X2 = 2.0 * random:uniform() - 1.0,
normal_boxm(M,S,X1,X2,X1 * X1 + X2 * X2).
%%%
%% incremental computation of the mean
mean(Esp, [], _) -> Esp;
mean(Esp, [X|H], I) ->
Next = I+1,
mean((Esp+(X-Esp)/(Next)), H, Next).
%% compute the mean of a list
mean([]) -> 0;
mean(H) ->
mean(0, H, 0).
%% @spec meanvar(Esp::number(),Var::number(),X::list() | number(),I::integer()) ->
%% {NewEsp::number(), NewVar::number(), Next::integer()}
%% @doc incremental computation of the mean and variance together. The
%% algorithm should limit the round-off errors
%% @end
%% single value
meanvar(Esp, Var, X, I) when is_number(X) ->
Next = I+1,
C = X - Esp,
NewEsp = (X+Esp*I)/(Next),
NewVar = Var+C*(X-NewEsp),
{ NewEsp, NewVar, Next };
%% list of samples
meanvar(Esp, Var,[], I) ->
{Esp, Var, I};
meanvar(Esp, Var, [X|H], I) ->
{NewEsp, NewVar, Next} = meanvar(Esp,Var,X,I),
meanvar(NewEsp, NewVar, H, Next).
%% compute min and max also
meanvar_minmax(Esp, Var, Min, Max, X, I) when is_number(X)->
meanvar_minmax(Esp, Var, Min, Max, [X], I);
meanvar_minmax(Esp, Var, Min, Max, [], I) ->
{Esp, Var, Min, Max, I};
meanvar_minmax(Esp, Var, 0, 0, [X|H], I) -> % first data, set min and max
meanvar_minmax(Esp, Var, X, X, [X|H], I);
meanvar_minmax(Esp, Var, Min, Max, [X|H], I) ->
{NewEsp, NewVar, Next} = meanvar(Esp,Var,X,I),
if
X > Max -> % new max, min unchanged
meanvar_minmax(NewEsp, NewVar, Min, X, H, Next);
X < Min -> % new min, max unchanged
meanvar_minmax(NewEsp, NewVar, X, Max, H, Next);
true ->
meanvar_minmax(NewEsp, NewVar, Min, Max, H, Next)
end.
%% compute the variance of a list
variance([]) -> 0;
variance(H) ->
{_Mean, Var, I} = meanvar(0, 0, H, 0),
Var/I.
stdvar(H) ->
math:sqrt(variance(H)).
Jump to Line
Something went wrong with that request. Please try again.