Skip to main content
1 of 8
DCM
  • 778
  • 3
  • 9

This isn't really an answer, but I thought I'd post the (python3) code below to illustrate the point I made in the comments.

"""
A short script for comparing Nelder-Mead and BFGS on a 'tricky'
objective function.
"""

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[1])
wavelength = float(sys.argv[2])

# 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)
DCM
  • 778
  • 3
  • 9