Skip to Content

MINIMIZE

Overview

The MINIMIZE function finds a local minimum of a multivariate objective by wrapping scipy.optimize.minimize. Given a function f(x)f(x), the solver iteratively explores the search space using gradient-based or gradient-free algorithms while respecting optional bound constraints. This enables optimization of engineering, finance, or operations models directly in Excel without building bespoke macros. This example function is provided as-is without any representation of accuracy.

Usage

To evaluate the function in Excel:

=MINIMIZE(func_expr, x_zero, [bounds], [minimize_method])
  • func_expr (string, required): Objective expression written in terms of x (e.g., "(1 - x[0])**2 + x[1]**2").
  • x_zero (2D list of float, required): Initial guess for each decision variable.
  • bounds (2D list of float or None, optional): List of [lower, upper] bounds for each variable. Use None for an unbounded side.
  • minimize_method (string (enum), optional): Name of a solver supported by scipy.optimize.minimize. Valid options: L-BFGS-B, BFGS, CG, Powell, Nelder-Mead, TNC, SLSQP, Dogleg, Trust-NCG.

The function returns a single-row 2D list containing the optimal variables followed by the objective value, or an error message string if validation fails or the optimization does not converge.

Function Expressions

The func_expr parameter accepts mathematical expressions using any of the following functions and constants. All functions are case-sensitive.

Function/ConstantDescriptionExample
sin(x)Sine function (radians)sin(x[0])
cos(x)Cosine function (radians)cos(x[1])
tan(x)Tangent function (radians)tan(x[0])
asin(x) or arcsin(x)Arc sine function (radians)asin(x[0])
acos(x) or arccos(x)Arc cosine function (radians)acos(x[1])
atan(x) or arctan(x)Arc tangent function (radians)atan(x[0])
sinh(x)Hyperbolic sinesinh(x[0])
cosh(x)Hyperbolic cosinecosh(x[1])
tanh(x)Hyperbolic tangenttanh(x[0])
exp(x)Exponential function (exe^x)exp(x[0])
log(x) or ln(x)Natural logarithm (base ee)log(x[0])
log10(x)Base-10 logarithmlog10(x[0])
sqrt(x)Square rootsqrt(x[0])
abs(x)Absolute valueabs(x[0] - x[1])
pow(x, y)Power function (x raised to power y)pow(x[0], 2)
piMathematical constant π (≈3.14159)x[0] * pi
eMathematical constant e (≈2.71828)e**x[0]

Important Notes:

  • All trigonometric functions use radians, not degrees
  • Use ** (double asterisk) or ^ (caret) for exponentiation. Both work equivalently.
  • For multi-variable functions, use indexed variable notation: x[0], x[1], etc.

Expression Examples

Common mathematical expressions and their func_expr notation:

  • f(x0,x1)=(1x0)2+100(x1x02)2f(x_0, x_1) = (1-x_0)^2 + 100(x_1-x_0^2)^2"(1-x[0])**2 + 100*(x[1]-x[0]**2)**2"
  • f(x0,x1)=x02+x12f(x_0, x_1) = x_0^2 + x_1^2"x[0]**2 + x[1]**2" or "x[0]^2 + x[1]^2"
  • f(x0,x1)=(x01)2+(x12)2f(x_0, x_1) = (x_0-1)^2 + (x_1-2)^2"(x[0]-1)**2 + (x[1]-2)**2"
  • f(x0,x1)=sin(x0)+cos(x1)f(x_0, x_1) = \sin(x_0) + \cos(x_1)"sin(x[0]) + cos(x[1])"

Examples

Example 1: Rosenbrock Function with All Parameters

Inputs:

func_exprx_zeroboundsmethod
(1 - x[0])*2 + 100(x[1] - x[0]**2)**2-12-22L-BFGS-B
-22

Excel formula:

=MINIMIZE("(1 - x[0])**2 + 100*(x[1] - x[0]**2)**2", {-1,2}, {-2,2;-2,2}, "L-BFGS-B")

Expected output:

x₁x₂Objective
1.0001.0000.000

This example demonstrates using non-default values for all optional parameters.

Example 2: Quadratic Bowl with Bounds

Inputs:

func_exprx_zerobounds
(x[0]-3)**2 + (x[1]-4)**2 + 71100
1010

Excel formula:

=MINIMIZE("(x[0]-3)**2 + (x[1]-4)**2 + 7", {1,1}, {0,10;0,10})

Expected output:

x₁x₂Objective
3.0004.0007.000

Example 3: Rosenbrock with BFGS Method

Inputs:

func_exprx_zeromethod
(1 - x[0])*2 + 100(x[1] - x[0]**2)**2-12BFGS

Excel formula:

=MINIMIZE("(1 - x[0])**2 + 100*(x[1] - x[0]**2)**2", {-1,2}, , "BFGS")

Expected output:

x₁x₂Objective
1.0001.0000.000

Example 4: Quadratic with L-BFGS-B and Bounds

Inputs:

func_exprx_zeroboundsmethod
(x[0]-3)**2 + (x[1]-4)**2 + 71100L-BFGS-B
1010

Excel formula:

=MINIMIZE("(x[0]-3)**2 + (x[1]-4)**2 + 7", {1,1}, {0,10;0,10}, "L-BFGS-B")

Expected output:

x₁x₂Objective
3.0004.0007.000

Python Code

import math from typing import List, Optional, Tuple, Union import numpy as np from scipy.optimize import minimize as scipy_minimize Number = Union[int, float] def minimize( func_expr: str, x_zero: List[List[Number]], bounds: Optional[List[List[Optional[Number]]]] = None, minimize_method: Optional[str] = None, ) -> Union[List[List[float]], str]: """Minimize a multivariate function using SciPy's ``minimize`` routine. Args: func_expr: Objective expression written in terms of ``x`` (for example, ``"x[0]**2 + x[1]**2"``). x_zero: 2D list providing the initial guess for each variable. bounds: Optional 2D list of ``[lower, upper]`` bounds per variable. Use ``None`` for an unbounded side. minimize_method: Optional string naming any solver supported by ``scipy.optimize.minimize``. Returns: Single-row 2D list containing the optimal variable values followed by the objective value, or an error message string if validation fails or the solver cannot complete. This example function is provided as-is without any representation of accuracy. """ def normalize_to_2d_list(value): if not isinstance(value, list): return [[value]] return value if not isinstance(func_expr, str) or func_expr.strip() == "": return "Invalid input: func_expr must be a non-empty string." if "x" not in func_expr: return "Invalid input: function expression must contain the variable 'x'." # Normalize x_zero in case Excel passes a scalar instead of a 2D list x_zero = normalize_to_2d_list(x_zero) if not isinstance(x_zero, list) or len(x_zero) == 0 or not isinstance(x_zero[0], list): return "Invalid input: x_zero must be a 2D list, e.g., [[0, 0]]." x0_row = x_zero[0] if len(x0_row) == 0: return "Invalid input: x_zero must contain at least one variable." try: x0_vector = np.asarray([float(value) for value in x0_row], dtype=float) except (TypeError, ValueError): return "Invalid input: x_zero must contain numeric values." variable_count = x0_vector.size processed_bounds: Optional[List[Tuple[Optional[float], Optional[float]]]] = None if bounds is not None: # Normalize bounds in case Excel passes a scalar instead of a 2D list bounds = normalize_to_2d_list(bounds) if not isinstance(bounds, list) or len(bounds) != variable_count: return "Invalid input: bounds must provide one [min, max] pair per variable." processed_bounds = [] for index, pair in enumerate(bounds): if not isinstance(pair, list) or len(pair) != 2: return "Invalid input: each bounds entry must be a [min, max] pair." lower_raw, upper_raw = pair try: lower_val = float(lower_raw) if lower_raw is not None else None upper_val = float(upper_raw) if upper_raw is not None else None except (TypeError, ValueError): return f"Invalid input: bounds for variable {index + 1} must be numeric or None." if lower_val is not None and not math.isfinite(lower_val): return f"Invalid input: bounds lower value for variable {index + 1} must be finite or None." if upper_val is not None and not math.isfinite(upper_val): return f"Invalid input: bounds upper value for variable {index + 1} must be finite or None." if lower_val is not None and upper_val is not None and lower_val > upper_val: return f"Invalid input: lower bound cannot exceed upper bound for variable {index + 1}." processed_bounds.append((lower_val, upper_val)) solver_method = None if minimize_method is not None: # Check if method is a scalar that needs to be handled as a 2D list if not isinstance(minimize_method, list): # If method is not a list, treat it as a scalar and handle appropriately if isinstance(minimize_method, str): solver_method = minimize_method else: # If it's not a string and not a list, normalize it as a 2D list minimize_method = [[minimize_method]] if isinstance(minimize_method, list): if len(minimize_method) == 0: solver_method = None elif isinstance(minimize_method[0], list) and len(minimize_method[0]) > 0: solver_method = str(minimize_method[0][0]) elif isinstance(minimize_method[0], str): solver_method = minimize_method[0] else: return "Invalid input: minimize_method must be a string, 2D list, or None." elif isinstance(minimize_method, str): solver_method = minimize_method else: return "Invalid input: minimize_method must be a string, 2D list, or None." safe_globals = { name: getattr(math, name) for name in dir(math) if not name.startswith("_") } safe_globals.update({ "np": np, "numpy": np, "sin": np.sin, "cos": np.cos, "tan": np.tan, "asin": np.arcsin, "acos": np.arccos, "atan": np.arctan, "sinh": np.sinh, "cosh": np.cosh, "tanh": np.tanh, "exp": np.exp, "log": np.log, "sqrt": np.sqrt, "abs": np.abs, "pow": np.power, }) # Objective wrapper that evaluates the expression for SciPy. def _objective(vector: np.ndarray) -> float: local_context = {"x": vector} try: value = eval(func_expr, safe_globals, local_context) except Exception: return float("inf") try: numeric_value = float(value) except (TypeError, ValueError): return float("inf") if not math.isfinite(numeric_value): return float("inf") return numeric_value # Pre-evaluate the objective at the initial guess to catch parse/eval errors early. try: initial_check = eval(func_expr, safe_globals, {"x": x0_vector}) except Exception as exc: return f"Error: Invalid model expression at initial guess: {exc}" try: initial_value = float(initial_check) except (TypeError, ValueError): return "Error: Invalid model expression: objective did not return a numeric value at initial guess." if not math.isfinite(initial_value): return "Error: Invalid model expression: objective returned a non-finite value at initial guess." minimize_kwargs = {} if processed_bounds is not None: minimize_kwargs["bounds"] = processed_bounds if solver_method is not None: minimize_kwargs["method"] = solver_method try: result = scipy_minimize(_objective, x0=x0_vector, **minimize_kwargs) except ValueError as exc: return f"minimize error: {exc}" except Exception as exc: return f"minimize error: {exc}" if not result.success or result.x is None or result.fun is None: message = result.message if hasattr(result, "message") else "Optimization failed." return f"minimize failed: {message}" if not math.isfinite(result.fun): return "minimize failed: objective value is not finite." try: solution = [float(value) for value in result.x] except (TypeError, ValueError): return "minimize failed: solution vector could not be converted to floats." return [solution + [float(result.fun)]]

Example Workbook

Link to Workbook 

Last updated on