Permalink
Fetching contributors…
Cannot retrieve contributors at this time
93 lines (86 sloc) 3.18 KB
function statsfun = statsfunhelper(inp1, inp2)
% Helper tool to create a statsfun for the options structure of solvers.
%
% function statsfun = statsfunhelper(name, fun)
% function statsfun = statsfunhelper(S)
%
% Usage with (name, fun):
%
% Input 1: name is a string which is a valid field name (no spaces, starts
% with a letter or an underscore, only alphanumeric characters and
% underscores).
%
% Input2: fun is a function handle with one output and 1 to 4 inputs, as
% follows (your choice):
%
% fun(x) or fun(problem, x) or
% fun(problem, x, stats) or fun(problem, x, stats, store)
%
% where the inputs are the ones that would be given to options.statsfun, as
% described in the help of the solver used. Typically, x is the point on
% the manifold at the current iterate, problem is the Manopt problem
% structure, stats is all the current statistics recorded for that iterate
% and store is the cache structure at the current iterate.
%
% When calling a Manopt solver with the options structure, such as for
% example with:
%
% [x, xcost, info] = steepestdescent(problem, [], options);
%
% you may set a field of the options structure as follows:
%
% options.statsfun = statsfunhelper('nameofthefield', fun);
%
% As a result, at each iteration, the stats structure will contain a field
% stats.nameofthefield with the value returned by the call to fun at that
% iterate. The stats structures are stored in the struct-array info.
% As an example, if the value returned by fun is a scalar, then
% [info.nameofthefield] is a vector containing all returned values.
%
%
% Usage with S:
%
% The input S is a structure. For each field of S, say S.field, the stats
% structure will be augmented with stats.field = fun(..), where fun is the
% function handle stored in S.field, and with the same conventions as
% above. This version allows to record more than one bit of information at
% each iteration. Example:
%
% metrics.nameofthefield = fun;
% metrics.othername = otherfun;
% options.statsfun = statsfunhelper(metrics);
%
% The different function handles (here, fun and otherfun) can take 1 to 4
% inputs too, and they do not have to take the same number of inputs.
% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, Dec. 17, 2014.
% Contributors:
% Change log:
if (nargin == 1) && isstruct(inp1)
S = inp1;
elseif (nargin == 2)
S = struct(inp1, inp2);
else
error('statsfunhelper takes 1 or 2 inputs. If 1 input, it must be a structure.');
end
function stats = thestatsfun(problem, x, stats, store)
names = fieldnames(S);
for it = 1 : length(names)
name = names{it};
fun = S.(name);
switch nargin(fun)
case 1
stats.(name) = fun(x);
case 2
stats.(name) = fun(problem, x);
case 3
stats.(name) = fun(problem, x, stats);
case 4
stats.(name) = fun(problem, x, stats, store);
otherwise
error('The functions passed to statsfunhelper must take 1 to 4 inputs.');
end
end
end
statsfun = @thestatsfun;
end