diff toolboxes/FullBNT-1.0.7/netlab3.3/metrop.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/FullBNT-1.0.7/netlab3.3/metrop.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,193 @@
+function [samples, energies, diagn] = metrop(f, x, options, gradf, varargin)
+%METROP	Markov Chain Monte Carlo sampling with Metropolis algorithm.
+%
+%	Description
+%	 SAMPLES = METROP(F, X, OPTIONS) uses the Metropolis algorithm to
+%	sample from the distribution P ~ EXP(-F), where F is the first
+%	argument to METROP.   The Markov chain starts at the point X and each
+%	candidate state is picked from a Gaussian proposal distribution and
+%	accepted or rejected according to the Metropolis criterion.
+%
+%	SAMPLES = METROP(F, X, OPTIONS, [], P1, P2, ...) allows additional
+%	arguments to be passed to F().  The fourth argument is ignored, but
+%	is included for compatibility with HMC and the optimisers.
+%
+%	[SAMPLES, ENERGIES, DIAGN] = METROP(F, X, OPTIONS) also returns a log
+%	of the energy values (i.e. negative log probabilities) for the
+%	samples in ENERGIES and DIAGN, a structure containing diagnostic
+%	information (position and acceptance threshold) for each step of the
+%	chain in DIAGN.POS and DIAGN.ACC respectively.  All candidate states
+%	(including rejected ones) are stored in DIAGN.POS.
+%
+%	S = METROP('STATE') returns a state structure that contains the state
+%	of the two random number generators RAND and RANDN. These are
+%	contained in fields randstate,  randnstate.
+%
+%	METROP('STATE', S) resets the state to S.  If S is an integer, then
+%	it is passed to RAND and RANDN. If S is a structure returned by
+%	METROP('STATE') then it resets the generator to exactly the same
+%	state.
+%
+%	The optional parameters in the OPTIONS vector have the following
+%	interpretations.
+%
+%	OPTIONS(1) is set to 1 to display the energy values and rejection
+%	threshold at each step of the Markov chain. If the value is 2, then
+%	the position vectors at each step are also displayed.
+%
+%	OPTIONS(14) is the number of samples retained from the Markov chain;
+%	default 100.
+%
+%	OPTIONS(15) is the number of samples omitted from the start of the
+%	chain; default 0.
+%
+%	OPTIONS(18) is the variance of the proposal distribution; default 1.
+%
+%	See also
+%	HMC
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+if nargin <= 2
+  if ~strcmp(f, 'state')
+    error('Unknown argument to metrop');
+  end
+  switch nargin
+    case 1
+      % Return state of sampler
+      samples = get_state(f);	% Function defined in this module
+      return;
+    case 2
+      % Set the state of the sampler
+      set_state(f, x);		% Function defined in this module
+      return;
+  end
+end
+
+if 0
+seed = 42;
+randn('state', seed);
+rand('state', seed)
+end
+
+display = options(1);
+if options(14) > 0
+  nsamples = options(14);
+else
+  nsamples = 100;
+end
+if options(15) >= 0
+  nomit = options(15);
+else
+  nomit = 0;
+end
+if options(18) > 0.0
+  std_dev = sqrt(options(18));
+else
+  std_dev = 1.0;   % default
+end			
+nparams = length(x);
+
+% Set up string for evaluating potential function.
+f = fcnchk(f, length(varargin));
+
+samples = zeros(nsamples, nparams);		% Matrix of returned samples.
+if nargout >= 2
+  en_save = 1;
+  energies = zeros(nsamples, 1);
+else
+  en_save = 0;
+end
+if nargout >= 3
+  diagnostics = 1;
+  diagn_pos = zeros(nsamples, nparams);
+  diagn_acc = zeros(nsamples, 1);
+else
+  diagnostics = 0;
+end
+
+% Main loop.
+n = - nomit + 1;
+Eold = feval(f, x, varargin{:});	% Evaluate starting energy.
+nreject = 0;				% Initialise count of rejected states.
+while n <= nsamples
+
+  xold = x;
+  % Sample a new point from the proposal distribution
+  x = xold + randn(1, nparams)*std_dev;
+  %fprintf('netlab propose: xold = %5.3f,%5.3f, xnew = %5.3f,%5.3f\n',...
+  %	xold(1), xold(2), x(1), x(2));
+
+  % Now apply Metropolis algorithm.
+  Enew = feval(f, x, varargin{:});	% Evaluate new energy.
+  a = exp(Eold - Enew);			% Acceptance threshold.
+  if (diagnostics & n > 0)
+    diagn_pos(n,:) = x;
+    diagn_acc(n,:) = a;
+  end
+  if (display > 1)
+    fprintf(1, 'New position is\n');
+    disp(x);
+  end
+
+  r = rand(1);
+  %fprintf('netlab: n=%d, a=%f/%f=%5.3f (%5.3f), r=%5.3f\n',...
+  %	  n, exp(-Enew), exp(-Eold), a, exp(-Enew)/exp(-Eold), r);
+  if a > r	% Accept the new state.
+    Eold = Enew;
+    if (display > 0)
+      fprintf(1, 'Finished step %4d  Threshold: %g\n', n, a);
+    end
+  else			% Reject the new state
+    if n > 0
+      nreject = nreject + 1;
+    end
+    x = xold;	% Reset position 
+    if (display > 0)
+      fprintf(1, '  Sample rejected %4d.  Threshold: %g\n', n, a);
+    end
+  end
+  if n > 0
+    samples(n,:) = x;			% Store sample.
+    if en_save 
+      energies(n) = Eold;		% Store energy.
+    end
+  end
+  n = n + 1;
+end
+
+if (display > 0)
+  fprintf(1, '\nFraction of samples rejected:  %g\n', ...
+          nreject/(nsamples));
+end
+
+if diagnostics
+  diagn.pos = diagn_pos;
+  diagn.acc = diagn_acc;
+end
+
+% Return complete state of the sampler.
+function state = get_state(f)
+
+state.randstate = rand('state');
+state.randnstate = randn('state');
+return
+
+% Set state of sampler, either from full state, or with an integer
+function set_state(f, x)
+
+if isnumeric(x)
+  rand('state', x);
+  randn('state', x);
+else
+  if ~isstruct(x)
+    error('Second argument to metrop must be number or state structure');
+  end
+  if (~isfield(x, 'randstate') | ~isfield(x, 'randnstate'))
+    error('Second argument to metrop must contain correct fields')
+  end
+  rand('state', x.randstate);
+  randn('state', x.randnstate);
+end
+return