function x = simple_mlp_optimGDh(initX, uFunc, uPar, ...
				 stepsize, maxIter, fgoal, gnsgoal)
% A "Gradient Descent plus a small Heuristic" method for training an MLP.
% This is not directly from the schoolbooks, but works so far for simple 
% stuff..
%
% uFunc = "user function", in our case MLP evaluator, but could be anything
% uPar  = "user parameters", in our case training data, but could be
%         anything

% Idea: Negative gradient is a descent direction. Jump at most
% stepsize, but guarantee descent by dividing step if necessary.
% Makes the step size adaptive; maybe not the best way, though :)
% OK, I did add a little bit of memory of the previous direction, as in
% "momentum", so in theory it might not descend after all.. but in practice 
% this seems to work and seems to be faster than plain GD.

iterOK = 1;

x = initX; 
step = stepsize;
[f, grad] = uFunc(x, uPar);

stat = 'i';
for iter=1:maxIter
  
  gns = sum(grad .^ 2);
  
  if f <= fgoal, break, end;
  if gns <= gnsgoal, break, end;
  
  x2 = x - step * grad;
  [f2, grad2] = uFunc(x2, uPar);

  if f2>f
    step = step / 2;
    stepsize = stepsize * 0.8;  % 20 percent away if was too big.
    stat = 's';
  else
    iterOK = iterOK+1;
    x = x2; f=f2; grad = 0.2*grad + grad2; % A tiny bit of memory ..
    stepsize = stepsize * 1.01; % One percent interest for the stepsize
    step = stepsize;
    stat = 'h';
  end
  %disp(sprintf('%d/%d%s: f=%.17f  gns=%.17f  sz=%.17f', ...
  %     iter, maxIter, stat, f, gns, stepsize));
end
%disp(sprintf('%d/%d: f=%.17f  gns=%.17f', iter, maxIter, f, gns));
