Octave
fminunc
optimization
output function
algorithm

Output function for fminunc in Octave

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When fminunc is running, you sometimes want visibility into the optimization process instead of waiting for the final answer. An output function gives you that hook: it can log intermediate values, collect diagnostics, or stop the solver early when your own convergence rule is met.

What the Output Function Does

fminunc solves unconstrained minimization problems. In Octave, you typically configure it through an options structure created with optimset, and one of those options is OutputFcn.

The output function is called by the optimizer during the run. In practice, you use it to:

  • inspect the current point
  • print iteration progress
  • collect values for later plotting
  • stop early if a custom condition is met

The common callback shape is:

octave
function stop = my_output_function(x, optimValues, state)
  stop = false;
end

Returning true stops the optimization.

A Minimal Example

Suppose we want to minimize a simple quadratic function while printing progress.

octave
1function y = objective(x)
2  y = (x(1) - 3)^2 + (x(2) + 1)^2;
3end
4
5function stop = my_output_function(x, optimValues, state)
6  stop = false;
7  printf("state=%s, x=(%.4f, %.4f)\n", state, x(1), x(2));
8end
9
10x0 = [0; 0];
11options = optimset("OutputFcn", @my_output_function);
12[x, fval, info, output] = fminunc(@objective, x0, options);
13
14disp(x)
15disp(fval)

This example keeps the output function simple and safe. It prints the current parameter vector each time the optimizer invokes the callback.

Using the Callback for Early Stopping

The more interesting use case is early termination. For example, if the objective value becomes small enough for your application, you may want to stop instead of waiting for the default convergence criteria.

octave
1function y = objective(x)
2  y = (x(1) - 2)^2 + 0.5 * (x(2) - 5)^2;
3end
4
5function stop = stop_when_close(x, optimValues, state)
6  stop = false;
7
8  if strcmp(state, "iter")
9    if isfield(optimValues, "fval") && optimValues.fval < 1e-6
10      stop = true;
11    end
12  end
13end
14
15x0 = [10; -3];
16options = optimset("OutputFcn", @stop_when_close);
17[x, fval] = fminunc(@objective, x0, options);
18
19disp(x)
20disp(fval)

This pattern is useful when the default solver termination is mathematically correct but operationally more work than you need.

Collecting Data for Plots

Another practical pattern is storing the history of visited points or objective values so you can visualize convergence later. One simple way is to write to a global variable or a nested function state, though that should be done carefully to avoid confusing scope issues.

octave
1global history;
2history = [];
3
4function y = objective(x)
5  y = (x(1) - 1)^2 + (x(2) - 4)^2;
6end
7
8function stop = save_history(x, optimValues, state)
9  global history;
10  stop = false;
11
12  if strcmp(state, "iter")
13    history(end + 1, :) = x(:)';
14  end
15end
16
17options = optimset("OutputFcn", @save_history);
18[x, fval] = fminunc(@objective, [8; 8], options);
19
20disp(history)

That gives you iteration data you can inspect or plot afterward.

Common Pitfalls

The most common mistake is writing an output function that changes variables the optimizer depends on in unpredictable ways. The callback should observe or request termination, not secretly mutate solver internals.

Another issue is assuming the callback runs only once per iteration with exactly the same fields every time. Different solver states may expose different information, so defensive checks such as isfield are a good habit.

A third pitfall is printing too much data for large problems. Heavy console output can slow optimization noticeably and make logs unreadable.

Finally, do not forget that returning a true stop flag ends the run early. That can be useful, but it also means the final result may reflect your custom stopping rule rather than the optimizer's default convergence test.

Summary

  • Set OutputFcn through optimset to observe fminunc while it runs.
  • The callback can log progress, save history, or stop early.
  • Keep the callback lightweight and return true only when you really want to terminate.
  • Check callback state and available fields defensively.
  • Use the hook for diagnostics and control, not as a substitute for a well-posed objective function.

Course illustration
Course illustration

All Rights Reserved.