Skip to content
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
Cannot retrieve contributors at this time
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:
% Original author: Nicolas Boumal, Dec. 17, 2014.
% Contributors:
% Change log:
% Jan 2, 2021 (NB):
% Passing S to thestatsfun explicitly for compatibility with Octave 6.
if (nargin == 1) && isstruct(inp1)
S = inp1;
elseif (nargin == 2)
S = struct(inp1, inp2);
error('statsfunhelper takes 1 or 2 inputs. If 1 input, it must be a structure.');
statsfun = @(problem, x, stats, store) thestatsfun(S, problem, x, stats, store);
function stats = thestatsfun(S, 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);
error('The functions passed to statsfunhelper must take 1 to 4 inputs.');