Как передать параметры цели в cyipopt

#ipopt #cyipopt

Вопрос:

Я пытаюсь передать варианты НЛП, которые я решаю в cyipopt.

Эти параметры будут одинаково влиять на достижение цели на каждой итерации. Например, задача учебника состоит в том, чтобы свести к минимуму

x_1 * x_4 * (x_1 x_2 _3) x_3

с учетом некоторых ограничений (см. https://pythonhosted.org/ipopt/tutorial.html).

Я хотел бы решить связанную с этим проблему

масштаб * x_1 * x_4 * (x_1 x_2 _3) x_3

где масштаб-это параметр, который задается перед оптимизацией. Приведенный ниже код показывает, как настроить проблему в pyipopt, но масштаб жестко задан как 2. Как я могу установить его в качестве опции, чтобы его можно было гибко изменять?

 import ipopt
import numpy as np

class hs071(object):
    def __init__(self):
        pass

    def objective(self, x, scale):
        # The callback for calculating the objective
        scale = 2
        
        return scale * x[0] * x[3] * np.sum(x[0:3])   x[2]

    def gradient(self, x, scale):
        # The callback for calculating the gradient
        scale = 2
        
        return np.array([
                    scale * x[0] * x[3]   scale * x[3] * np.sum(x[0:3]),
                    scale * x[0] * x[3],
                    scale * x[0] * x[3]   1.0,
                    scale * x[0] * np.sum(x[0:3])
                    ])

    def constraints(self, x):
        # The callback for calculating the constraints
        return np.array((np.prod(x), np.dot(x, x)))

    def jacobian(self, x):
        # The callback for calculating the Jacobian
        return np.concatenate((np.prod(x) / x, 2*x))

x0 = [1.0, 5.0, 5.0, 1.0]

lb = [1.0, 1.0, 1.0, 1.0]
ub = [5.0, 5.0, 5.0, 5.0]

cl = [25.0, 40.0]
cu = [2.0e19, 40.0]

nlp = ipopt.problem(
            n=len(x0),
            m=len(cl),
            problem_obj=hs071(),
            lb=lb,
            ub=ub,
            cl=cl,
            cu=cu
            )

x, info = nlp.solve(x0)

 

NB: определение глобалов работает, но неаккуратно. Для этого должен быть более чистый способ, поскольку именно так вы добавляете данные в задачу оптимизации.

Ответ №1:

Добавьте их в сам класс:

 import ipopt
import numpy as np

class hs071(object):
    def __init__(self):
        pass

    def objective(self, x):
        # The callback for calculating the objective
        scale = self.scale
        
        return scale * x[0] * x[3] * np.sum(x[0:3])   x[2]

    def gradient(self, x):
        # The callback for calculating the gradient
        scale = self.scale
        
        return np.array([
                    scale * x[0] * x[3]   scale * x[3] * np.sum(x[0:3]),
                    scale * x[0] * x[3],
                    scale * x[0] * x[3]   1.0,
                    scale * x[0] * np.sum(x[0:3])
                    ])

    def constraints(self, x):
        # The callback for calculating the constraints
        return np.array((np.prod(x), np.dot(x, x)))

    def jacobian(self, x):
        # The callback for calculating the Jacobian
        return np.concatenate((np.prod(x) / x, 2*x))

x0 = [1.0, 5.0, 5.0, 1.0]

lb = [1.0, 1.0, 1.0, 1.0]
ub = [5.0, 5.0, 5.0, 5.0]

cl = [25.0, 40.0]
cu = [2.0e19, 40.0]

model = hs071()
model.scale = 2

nlp = ipopt.problem(
            n=len(x0),
            m=len(cl),
            problem_obj=model,
            lb=lb,
            ub=ub,
            cl=cl,
            cu=cu
            )

x, info = nlp.solve(x0)