I have two quadric surfaces in 3-dimensional space.
I would like to minimize the distance between the two objects. Function distance()
takes 4 variables - alpha, beta, zt and zs. The goal is to find such values of these 4 variables that the function returns the minimal possible value.
Consider the code below.
import numpy as np
from scipy.optimize import minimize
A = 1; B = 1; C = 1; D = 1; Z = 0;
def distance(alpha,beta,zt,zs):
"""distance between points in 2 quadric surfaces in 3D space"""
rt = (A/B) * np.sqrt(B**2 + (zt-C)**2)
xt = rt * np.cos(alpha)
yt = rt * np.sin(alpha)
rs = D * np.sqrt(zs-Z)
xs = rs * np.cos(beta)
ys = rs * np.sin(beta)
return (xt-xs)**2 + (yt-ys)**2 + (zt-zs)**2
x0 = np.array([0, 0, 0, 0])
res = minimize(distance,
x0,
method='nelder-mead')
The code gives me the following error.
TypeError: distance() missing 3 required positional arguments: 'beta', 'zt', and 'zs'
All documentation I have found uses only univariate (one variable) functions (like the Rosenbrock function) despite it saying it minimizes "multivariate scalar functions".
How do I make my code find the optimal values for the 4 parameters to minimize the value of a function?
Looks like you want to vary all four arguments. You pass their initial values as x0
, a 4 element array. That's what minimize
will pass to distance
. Here's a change to distance
that should work with that:
def distance(x):
"""distance between points in 2 quadric surfaces in 3D space"""
alpha,beta,zt,zs = x # unpack x into these 4 variables
rt = (A/B) * np.sqrt(B**2 + (zt-C)**2)
xt = rt * np.cos(alpha)
yt = rt * np.sin(alpha)
rs = D * np.sqrt(zs-Z)
xs = rs * np.cos(beta)
ys = rs * np.sin(beta)
return (xt-xs)**2 + (yt-ys)**2 + (zt-zs)**2
The args
suggestion would vary alpha
and hold the other 3 constant. That doesn't sound like what you want. You already use A
, B
, C
as global constants.
1115:~/mypy$ python3 stack55751317.py
final_simplex: (array([[-1.21456543, -1.21455458, 0.99997997, 0.99997757],
[-1.21457508, -1.21458998, 0.9999941 , 1.00000714],
[-1.21461728, -1.21460427, 1.00002695, 1.00001266],
[-1.21456081, -1.2145312 , 0.99996329, 0.99996864],
[-1.2146315 , -1.21462741, 1.00002628, 1.00004968]]), array([2.49380001e-10, 4.04824635e-10, 4.13486388e-10, 1.15131206e-09,
1.18130671e-09]))
fun: 2.4938000073954824e-10
message: 'Optimization terminated successfully.'
nfev: 295
nit: 172
status: 0
success: True
x: array([-1.21456543, -1.21455458, 0.99997997, 0.99997757])
x
looks like the result, which you can access with res['x']
.
Most of the items in this res
dictionary are explained at:
final_simplex
is a special output for this minimization method.