# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

import numpy as np
from scipy.optimize import minimize

# # Optimize multivariable function using constrained optimization
# Based on: https://www.youtube.com/watch?v=cXHvC_FGx24

# Let's minimize:
#
# $$min \ x_1 x_4 (x_1 + x_2 + x_3) + x_3$$
#
# with the following constraints:
#
# * $x_1 x_2 x_3 x_4 \geq 40$
#
#
# * $x_1^2 + x_2^2 + x_3^2 + x_4^2 = 40$
#
#
# * $1 \leq x_1,\ x_2,\ x_3,\ x_4 \leq 5 $
#
#
# Let's define our initial values as 
#
# $$X_0 = (1, 5, 5, 1)$$

# Define init vals
X = np.array([1, 5, 5, 1])


# Define objective function
def objective(x):
    return x[0] * x[3] * (x[0] + x[1] + x[2]) + x[2]


# Sanity check
objective(X)


# +
# Define constraint 1 (inequality)
def constr_1(x):
    return x[0] * x[1] * x[2] * x[3] - 25

# Define constraint 2 (equality)
def constr_2(x):
    return sum(x**2) - 40 


# -

# Sanity check
constr_2(X)

# Setup bounds for variables
bound = (1, 5)
bounds = tuple([bound]*4)

# +
# Specify additional information on constraints
con_1 = {'type': 'ineq', 
         'fun' : constr_1
        }

con_2 = {'type': 'eq', 
         'fun' : constr_2
        }

cons = [con_1, con_2]
# -

# **NOTE**: Inequality `'ineq'` constraints always take form of `x >= n`
#
# https://stackoverflow.com/questions/42303470/scipy-optimize-inequality-constraint-which-side-of-the-inequality-is-considere
#
# https://docs.scipy.org/doc/scipy-0.18.1/reference/tutorial/optimize.html

 # Define a solution
solution = minimize(objective, 
                    X,
                    method = 'SLSQP',
                    bounds = bounds,
                    constraints = cons)

# Examine solution
print(solution)

objective(solution.x)



StarcoderdataJupyterScriptsDedupFiltered