Add first implementation of the steepest descent method.
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 18 Mar 2013 02:21:31 +0000 (22:21 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 18 Mar 2013 02:21:31 +0000 (22:21 -0400)
optimization/steepest_descent.m [new file with mode: 0644]

diff --git a/optimization/steepest_descent.m b/optimization/steepest_descent.m
new file mode 100644 (file)
index 0000000..32aad71
--- /dev/null
@@ -0,0 +1,68 @@
+function [x, k] = steepest_descent(g, x0, step_size, tolerance, max_iterations)
+  %
+  % An implementation of the steepest-descent algorithm, with the
+  % search direction d_{k} = -\nabla f(x_{k}).
+  %
+  % We should terminate when either,
+  %
+  %   a) The 2-norm of the gradient at x_{k} is greater than
+  %   ``tolerance``.
+  %
+  %   b) We have performed ``max_iterations`` iterations.
+  %
+  % INPUT:
+  %
+  %   * ``g`` - the gradient of the function ``f`` we're minimizing.
+  %
+  %   * ``x0`` - the starting point for the search.
+  %
+  %   * ``step_size`` - a function of x which returns the optimal step
+  %     size alpha_{k}. This will generally require more information
+  %     than just x; for example it might need the function ``f`` or the
+  %     gradient ``g``. However, our caller has this information so it
+  %     should be incorporated into the step size algorithm that we
+  %     receive.
+  %
+  %   * ``tolerance`` - the stopping tolerance. We stop when the norm
+  %   of the gradient falls below this value.
+  %
+  %   * ``max_iterations`` - a safety net; we return x_{k}
+  %   unconditionally if we exceed this number of iterations.
+  %
+  % OUTPUT:
+  %
+  %   * ``x`` - the solution at the final value of x_{k}.
+  %
+  %   * ``k`` - the value of k when we stop; i.e. the number of
+  %   iterations.
+
+  % The initial gradient at x_{0} is not supplied, so we compute it
+  % here and begin the loop at k=1.
+  x = x0;
+  g_k = g(x);
+
+  if (norm(g_k) < tolerance)
+    % If x_0 is close enough to a solution, there's nothing for us to
+    % do! We use g_k (the gradient of f at x_k) instead of d_k because
+    % their 2-norms will be the same, and g_k is already stored.
+    return;
+  end
+
+  for k = [1 : max_iterations]
+    % Loop until either of our stopping conditions are met. If the
+    % loop finishes, we have implicitly met the second stopping
+    % condition (number of iterations).
+    d_k = -g_k;
+    alpha_k = step_size(x);
+    x = x + (alpha_k * d_k);
+    g_k = g(x);
+
+    if (norm(g_k) < tolerance)
+      return;
+    end
+  end
+
+  % If we make it to the end of the loop, that means we've executed the
+  % maximum allowed iterations. The caller should be able to examine the
+  % return value ``k`` to determine what happened.
+end