Skip to Content

SHGO

Overview

The SHGO function performs global optimization using the Simplicial Homology Global Optimization algorithm by wrapping scipy.optimize.shgo. It systematically samples the search space with low-discrepancy sequences, refines candidate simplices, and guarantees convergence to the global minimum under mild conditions. This example function is provided as-is without any representation of accuracy.

Usage

To evaluate the optimizer in Excel:

=SHGO(func_expr, bounds, [n], [iters], [sampling_method])
  • func_expr (string, required): Objective expression referencing variables through x[i].
  • bounds (2D list, required): Each row is [min, max] defining the allowable range for a variable.
  • n (int, optional, default=100): Number of initial sampling points.
  • iters (int, optional, default=1): Number of refinement iterations.
  • sampling_method (string (enum), optional, default="simplicial"): Sampling scheme. Valid options: simplicial, sobol, halton.

The function returns a single-row 2D list containing the optimal variables with the final objective value, or an error message string if validation fails.

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)
cos(x)Cosine function (radians)cos(x)
tan(x)Tangent function (radians)tan(x)
asin(x) or arcsin(x)Arc sine function (radians)asin(x) or arcsin(x)
acos(x) or arccos(x)Arc cosine function (radians)acos(x) or arccos(x)
atan(x) or arctan(x)Arc tangent function (radians)atan(x) or arctan(x)
sinh(x)Hyperbolic sinesinh(x)
cosh(x)Hyperbolic cosinecosh(x)
tanh(x)Hyperbolic tangenttanh(x)
exp(x)Exponential function (exe^x)exp(x)
log(x) or ln(x)Natural logarithm (base ee)log(x) or ln(x)
log10(x)Base-10 logarithmlog10(x)
sqrt(x)Square rootsqrt(x)
abs(x)Absolute valueabs(x)
pow(x, y)Power function (x raised to power y)pow(x, 2)
piMathematical constant π (≈3.14159)x * pi
eMathematical constant e (≈2.71828)e**x
infPositive infinityx + inf (rarely used)

Important Notes:

  • All trigonometric functions use radians, not degrees
  • Use ** (double asterisk) or ^ (caret) for exponentiation. Both are automatically converted to Python’s ** operator. Examples: x[0]**2, x[0]^2, e**x, e^x all work equivalently
  • For multi-variable functions, use indexed variable notation: x[0], x[1], etc.
  • Examples: "(x[0]-1)**2 + (x[1]+2)^2", "sin(x[0]) + cos(x[1])", "exp(-x[0]**2 - x[1]^2)"

Expression Examples

Common mathematical expressions and their func_expr notation for multi-variable functions:

  • f(x0,x1)=(x01)2+(x1+2)2f(x_0, x_1) = (x_0 - 1)^2 + (x_1 + 2)^2"(x[0]-1)**2 + (x[1]+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)=sin(x0)+cos(x1)f(x_0, x_1) = \sin(x_0) + \cos(x_1)"sin(x[0]) + cos(x[1])"
  • f(x0,x1)=ex02x12f(x_0, x_1) = e^{-x_0^2 - x_1^2}"exp(-x[0]**2 - x[1]**2)" or "e^(-x[0]^2 - x[1]^2)"
  • f(x0,x1,x2)=(x01)2+(x10.5)2+(x2+1)2f(x_0, x_1, x_2) = (x_0-1)^2 + (x_1-0.5)^2 + (x_2+1)^2"(x[0]-1)**2 + (x[1]-0.5)**2 + (x[2]+1)**2"

Examples

Example 1: Basic Quadratic with All Parameters

Inputs:

func_exprboundsniterssampling_method
(x[0]-1)**2 + (x[1]+2)**2-551203sobol
-55

Excel formula:

=SHGO("(x[0]-1)**2 + (x[1]+2)**2", {-5,5;-5,5}, 120, 3, "sobol")

Expected output:

x₁x₂Objective
1.000-2.0000.000

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

Example 2: Sobol Sampling with Refinement

Inputs:

func_exprboundssampling_methodniters
(x[0]-2)**2 + (x[1]-1)**2-66sobol502
-66

Excel formula:

=SHGO("(x[0]-2)**2 + (x[1]-1)**2", {-6,6;-6,6}, 50, 2, "sobol")

Expected output:

x₁x₂Objective
2.0001.0000.000

Example 3: Three-Variable Optimization

Inputs:

func_exprboundsn
(x[0]-1)**2 + (x[1]-0.5)**2 + (x[2]+1)**2-4480
-44
-44

Excel formula:

=SHGO("(x[0]-1)**2 + (x[1]-0.5)**2 + (x[2]+1)**2", {-4,4;-4,4;-4,4}, 80)

Expected output:

x₁x₂x₃Objective
1.0000.500-1.0000.000

Example 4: Halton Sampling Strategy

Inputs:

func_exprboundssampling_methodniters
x[0]**2 + 2*x[1]**2-33halton603
-33

Excel formula:

=SHGO("x[0]**2 + 2*x[1]**2", {-3,3;-3,3}, 60, 3, "halton")

Expected output:

x₁x₂Objective
0.0000.0000.000

Python Code

import math import re from typing import List import numpy as np from scipy.optimize import shgo as scipy_shgo def shgo( func_expr: str, bounds: List[List[float]], n: int = 100, iters: int = 1, sampling_method: str = 'simplicial', ): """Find global minimum using Simplicial Homology Global Optimization. This function wraps scipy.optimize.shgo. For more information, see: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.shgo.html Args: func_expr: Objective expression using x[i] for variable access. bounds: 2D list of [min, max] pairs specifying variable limits. n: Number of initial sampling points. Defaults to 100. iters: Number of refinement iterations. Defaults to 1. sampling_method: Sampling strategy ('simplicial', 'sobol', 'halton'). Defaults to 'simplicial'. Returns: [[x1, x2, ..., objective]] on success, or an error message string. This example function is provided as-is without any representation of accuracy. """ if not isinstance(func_expr, str): return "Invalid input: func_expr must be a string." if func_expr.strip() == "": return "Invalid input: func_expr must be a non-empty string." func_expr = re.sub(r'\^', '**', func_expr) if "x" not in func_expr: return "Invalid input: func_expr must reference variable x (e.g., x[0])." if not isinstance(bounds, list) or len(bounds) == 0: return "Invalid input: bounds must be a 2D list of [min, max] pairs." processed_bounds = [] for idx, bound in enumerate(bounds): if not isinstance(bound, list) or len(bound) != 2: return "Invalid input: each bound must be a [min, max] pair." try: lower = float(bound[0]) upper = float(bound[1]) except (TypeError, ValueError): return "Invalid input: bounds must contain numeric values." if lower > upper: return f"Invalid input: lower bound must not exceed upper bound for variable index {idx}." processed_bounds.append((lower, upper)) dimension = len(processed_bounds) try: n = int(n) iters = int(iters) except (TypeError, ValueError): return "Invalid input: n and iters must be integers." if n <= 0: return "Invalid input: n must be positive." if iters <= 0: return "Invalid input: iters must be positive." valid_methods = {'simplicial', 'sobol', 'halton'} if sampling_method not in valid_methods: return f"Invalid input: sampling_method must be one of: {', '.join(sorted(valid_methods))}" safe_globals = { "math": math, "np": np, "numpy": np, "__builtins__": {}, } safe_globals.update({ name: getattr(math, name) for name in dir(math) if not name.startswith("_") }) safe_globals.update({ "sin": np.sin, "cos": np.cos, "tan": np.tan, "asin": np.arcsin, "arcsin": np.arcsin, "acos": np.arccos, "arccos": np.arccos, "atan": np.arctan, "arctan": np.arctan, "sinh": np.sinh, "cosh": np.cosh, "tanh": np.tanh, "exp": np.exp, "log": np.log, "ln": np.log, "log10": np.log10, "sqrt": np.sqrt, "abs": np.abs, "pow": np.power, "pi": math.pi, "e": math.e, }) x0_vector = [np.mean([b[0], b[1]]) for b in processed_bounds] try: initial_eval = eval(func_expr, safe_globals, {"x": x0_vector}) float(initial_eval) except Exception as exc: return f"Error: Invalid expression at initial guess: {exc}" def objective(x_vector): try: local_x = [float(val) for val in np.atleast_1d(x_vector)] result = eval(func_expr, safe_globals, {"x": local_x}) numeric_value = float(result) except Exception as exc: raise ValueError(f"Error evaluating func_expr: {exc}") if not math.isfinite(numeric_value): raise ValueError("Objective evaluation produced NaN or infinity.") return numeric_value try: result = scipy_shgo( objective, bounds=processed_bounds, n=n, iters=iters, sampling_method=sampling_method, ) except ValueError as exc: return f"Error during SHGO: {exc}" except Exception as exc: return f"Error during SHGO: {exc}" if not result.success: return f"Error during SHGO: {result.message}" if result.x is None or result.fun is None: return "Error during SHGO: missing solution data." try: solution_vector = [float(val) for val in np.atleast_1d(result.x)] except (TypeError, ValueError): return "Error during SHGO: could not convert solution to floats." objective_value = float(result.fun) return [solution_vector + [objective_value]]

Example Workbook

Link to Workbook 

Last updated on