I suppose one general situation where Nelder-Mead might perform better is when the objective function is 'simple' at the length scale of the initial simplex, but is very oscillatory at the 'microscopic' scale; in this sort of situation, Nelder-Mead won't 'see' the complicated local behaviour, whereas a derivative-based method could be confused and impeded by it. For a concrete example on the real line, I had a play at finding the global minimum of $x\longmapsto x^2 + \sin(1000 x)$ with different initial conditions. [![enter image description here][1]][1] Zooming in to look at what went wrong for BFGS: [![enter image description here][2]][2] Below is the Python 3 code used to generate the plots. ``` """ Script for illustrating one situation when derivative-based optimisation methods can get into trouble. """ import matplotlib.pyplot as plt import numpy as np import sys from scipy.optimize import minimize # Read inputs from command line amplitude = float(sys.argv[3]) # e.g. 1.0 wavelength = float(sys.argv[4]) # e.g. 1.0e-3 # Set up objective function and its derivative objective = lambda x: np.square(x) + amplitude * np.sin(x / wavelength) derivative = lambda x: 2 * x + (amplitude / wavelength) * np.cos(x / wavelength) # Set up a starting position and a large initial simplex starting_position = 100 initial_simplex_length = 10 initial_simplex = np.array([ [starting_position], [starting_position + initial_simplex_length] ]) # Minimise using NM results = {} results["Nelder-Mead"] = minimize( objective, starting_position, method="Nelder-Mead", options={ "initial_simplex": initial_simplex } ) # Minimise using BFGS results["BFGS"] = minimize( objective, starting_position, method="BFGS", jac=derivative ) # Initialise plot _, ax = plt.subplots() # Plot objective function xs = np.arange(-0.2 * starting_position, 1.2 * starting_position, 0.5 * wavelength) ax.plot(xs, objective(xs)) # Mark minima found by both methods for method, result in results.items(): ax.scatter( [np.squeeze(result.x)], [result.fun], label=method ) ax.legend() ax.set_title( f"Nelder-Mead vs BFGS on x^2 + {amplitude} sin(x / {wavelength})\n" f"with x0 = {starting_position}, initial_simplex = {np.squeeze(initial_simplex)}" ) plt.show() # Print results print(results) ``` [1]: https://i.sstatic.net/zFhif.png [2]: https://i.sstatic.net/4fMkn.png