Минимизировать многопараметрическую функцию - PullRequest
1 голос
/ 18 апреля 2019

У меня есть две квадрик поверхности в трехмерном пространстве.

  • круговой гиперболоид одного листа
    • , описанный xt, yt, zt, rt
  • описанный круговой параболоид
    • по xs, ys, zs, rs

Я хотел бы минимизировать расстояние между двумя объектами.Функция distance() принимает 4 переменные - альфа, бета, zt и zs.Цель состоит в том, чтобы найти такие значения этих 4 переменных, чтобы функция возвращала минимально возможное значение.

Рассмотрим приведенный ниже код.

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')

Код дает мне следующую ошибку.

TypeError: distance () отсутствует 3 обязательных позиционных аргумента: 'beta', 'zt' и 'zs'

Вся документация Я нашелиспользует только одномерные (одна переменная) функции (например, функцию Розенброка), несмотря на то, что он минимизирует «многомерные скалярные функции».

Как заставить мой код находить оптимальные значения для 4 параметров, чтобы минимизировать значениефункция?

Ответы [ 2 ]

2 голосов
/ 18 апреля 2019

Похоже, вы хотите изменить все четыре аргумента. Вы передаете их начальные значения как x0, массив из 4 элементов. Вот что minimize перейдет на distance. Вот изменение в distance, которое должно с этим работать:

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

Предложение args будет меняться alpha и будет содержать остальные 3 константы. Это не похоже на то, что вы хотите. Вы уже используете A, B, C в качестве глобальных констант.

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 выглядит как результат, к которому вы можете получить доступ res['x'].

Большинство пунктов в этом res словаре объясняются по адресу:

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.OptimizeResult.html#scipy.optimize.OptimizeResult

final_simplex - специальный вывод для этого метода минимизации.

0 голосов
/ 18 апреля 2019
res = minimize(distance,
           x0[0],
           args=(*x0[1:],),
           method='nelder-mead')

Я думаю, это то, что вы хотите.

...