view general/algo/iterate.m @ 4:e44f49929e56

Adding reorganised general toolbox, now in several subdirectories.
author samer
date Sat, 12 Jan 2013 19:21:22 +0000
parents
children 03694e5c8365
line wrap: on
line source
function x0=iterate(varargin)
% iterate - Simulate recursive iteration of a function
%
% iterate :: 
%    (A=>(A | empty)) ~'function to iterate, can return [] to terminate',
%    A                ~'initial state',
%    options iterate_timed_options
% -> A                ~'final state'.
%
% iterate :: 
%    cell {
%       (A->(A | empty)) ~'function to iterate, can return [] to terminate',
%       A                ~'initial state'
%    }                   ~'iterated system as a cell array',
%    options iterate_timed_options
% -> A                ~'final state'.
%
% iterate_timed_options = {
%       its     :: natural /inf ~'Iteration limit';
%       quiet   :: bool    /1   ~'controls console display';
%       drawnow :: bool  /1   ~'controls graphics updating';
%       pre     :: A=>void      ~'something to do before each iteration';
%       post    :: A=>void      ~'something to do after each iteration';
%       save    :: natural /0   ~'iterations between state saving (0=off)';
%       id      :: string  /'iterstate@' ~'name of mat file to save to';
%       recover :: bool  /0   ~'recover from saved state'
%    }.
%
%	Plus the usual OPTPAUSE options.
%
% NOTE: old termination by throwing an exception is no longer supported.
% The function must return an empty array to force termination.

if iscell(varargin{1})
	[f,x]=varargin{1}{:};
	options=varargin(2:end);
else
	f=varargin{1};
	x=varargin{2};
	options=varargin(3:end);
end

opts=prefs('its',inf,'quiet',1,'save',0,'recover',0,'id','iterstate@',options{:});
pauserfn=pauser(opts);
post=isfield(opts,'post');
pre=isfield(opts,'pre');

i=0; 
if opts.recover
	if exist([opts.id,'.mat'],'file')
		fprintf('Attempting to recover from saved state %s.mat\n',opts.id);
		load(opts.id);
		fprintf('Continuing from iteration %d\n',i);
	else
		fprintf('Recovery file %s.mat does not exist.\n',opts.id);
	end
end

if ~post && ~pre && opts.quiet && opts.save==0
	while ~isempty(x) && i<opts.its,
		i=i+1;
		x0=x; x=f(x0); 
		pauserfn();
	end
else
	if opts.save>0
		fprintf('Will save every %d iterations to %s.mat\n',opts.save,opts.id);
	end

	% how cunning is this...
	if isfinite(opts.its), itformat=sprintf('%%%dd. ',ceil(log10(opts.its)));
	else itformat='%d. '; end


	while ~isempty(x) && i<opts.its,
		i=i+1;
		if ~opts.quiet, fprintf(itformat,i); end
		if pre, opts.pre(x); end
		x0=x; x=feval(f,x0); 
		if post, opts.post(x); end

		% save state every opts.save iterations
		if mod(i,opts.save)==0, 
			fprintf('\nsaving at %d.\n',i);
			save(opts.id,'x','i'); 
		end
		pauserfn();
	end
	if opts.save>0, 
		fprintf('Deleting recovery file %s.mat\n',opts.id);
		delete([opts.id '.mat']); 
	end
end
if ~isempty(x), x0=x; end