0001 function checkgradient(problem, x, d)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 if ~canGetCost(problem)
0036
0037
0038 if ~canGetPartialGradient(problem)
0039 error('getCost:checkgradient', 'It seems no cost was provided.');
0040 else
0041 error('getCost:stochastic', ['It seems no cost was provided.\n' ...
0042 'If you intend to use a stochastic solver, you still\n' ...
0043 'need to define problem.cost to use checkgradient.']);
0044 end
0045 end
0046 if ~canGetGradient(problem)
0047 warning('manopt:checkgradient:nograd', ...
0048 'It seems no gradient was provided.');
0049 end
0050
0051 x_isprovided = exist('x', 'var') && ~isempty(x);
0052 d_isprovided = exist('d', 'var') && ~isempty(d);
0053
0054 if ~x_isprovided && d_isprovided
0055 error('If d is provided, x must be too, since d is tangent at x.');
0056 end
0057
0058
0059 if ~x_isprovided
0060 x = problem.M.rand();
0061 end
0062 if ~d_isprovided
0063 d = problem.M.randvec(x);
0064 end
0065
0066
0067
0068
0069
0070 checkdiff(problem, x, d, true);
0071 title(sprintf(['Gradient check.\nThe slope of the continuous line ' ...
0072 'should match that of the dashed\n(reference) line ' ...
0073 'over at least a few orders of magnitude for h.']));
0074 xlabel('h');
0075 ylabel('Approximation error');
0076
0077
0078 if isfield(problem.M, 'tangent')
0079 storedb = StoreDB();
0080 key = storedb.getNewKey();
0081 grad = getGradient(problem, x, storedb, key);
0082 pgrad = problem.M.tangent(x, grad);
0083 residual = problem.M.lincomb(x, 1, grad, -1, pgrad);
0084 err = problem.M.norm(x, residual);
0085 fprintf('The residual should be 0, or very close. Residual: %g.\n', err);
0086 fprintf('If it is far from 0, then the gradient is not in the tangent space.\n');
0087 fprintf('In certain cases (e.g., hyperbolicfactory), the tangency test is inconclusive.\n');
0088 else
0089 fprintf(['Unfortunately, Manopt was unable to verify that the '...
0090 'gradient is indeed a tangent vector.\nPlease verify ' ...
0091 'this manually or implement the ''tangent'' function ' ...
0092 'in your manifold structure.']);
0093 end
0094
0095 end