Числовой якобиан для ipopt (cyipopt) с использованием numdifftools

Я использую ipopt (через cyipopt) для задачи оптимизации, но в рамках моей задачи оптимизации у меня нет аналитической формулировки моих ограничений. Можно ли использовать числовое определение ограничений через numdifftools для обратного вызова Якобиана? Или есть другой модуль Python, который лучше подходит для этого?

Я также не уверен в синтаксисе, который я должен использовать для использования numdifftools в качестве моего обратного вызова для вычисления якобиана. Ниже показан мой фрагмент кода для решения Hock Schittkowski #40 с использованием числового якобиана через numdifftools.

# -*- coding: utf-8 -*-
"""
cyipot: Python wrapper for the Ipopt optimization package, written in Cython.

"""
#
# Test the "ipopt" Python interface on the Hock & Schittkowski test problem 
#40
#

from __future__ import print_function, unicode_literals

import numpy as np
import scipy.sparse as sps
import ipopt
import numdifftools as nd

def explode():
    raise ValueError('bum')

class hs040(object):
    def __init__(self):
        self.counter = 0

    def objective(self, x):
        #
        # The callback for calculating the objective
        #
        self.counter += 1
        if self.counter > 100:
            explode()
        return -x[0]*x[1]*x[2]*x[3]

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

    def constraints(self, x):
        #
        # The callback for calculating the constraints
        #
        return np.array([x[0] ** 3.0 + x[1] ** 2.0,
                     x[0] ** 2.0 * x[3] - x[2],
                     x[3] ** 2.0 - x[1]])

    def jacobian(self, x):
        #
        # The callback for calculating the Jacobian
        #
        return nd.Jacobian(self.constraints(x))

    def intermediate(
        self,
        alg_mod,
        iter_count,
        obj_value,
        inf_pr,
        inf_du,
        mu,
        d_norm,
        regularization_size,
        alpha_du,
        alpha_pr,
        ls_trials
        ):

        #
        # Example for the use of the intermediate callback.
        #
        print("Objective value at iteration #%d is - %g" % (iter_count, obj_value))

def main():
    x0 = [0.8, 0.8, 0.8, 0.8]
    cl = [1.0, 0.0, 0.0]
    cu = [1.0, 0.0, 0.0]

    nlp = ipopt.problem(n=len(x0), m = len(cl), problem_obj=hs040(), cl=cl, cu=cu)

    #
    # Set solver options
    #
    nlp.addOption(b'mu_strategy', b'adaptive')
    nlp.addOption(b'linear_solver', b'ma57')
    nlp.addOption(b'tol', 1e-7)

    #
    # Scale the problem (Just for demonstration purposes)
    #
    nlp.setProblemScaling(
        obj_scaling=2,
        x_scaling=[1, 1, 1, 1]
    )
    nlp.addOption(b'nlp_scaling_method', b'user-scaling')

#
# Solve the problem
#
x, info = nlp.solve(x0)

print("Solution of the primal variables: x=%s\n" % repr(x))

print("Solution of the dual variables: lambda=%s\n" % repr(info['mult_g']))

print("Objective=%s\n" % repr(info['obj_val']))


if __name__ == '__main__':
main()

Этот фрагмент кода возвращает следующую ошибку:

TypeError: float() argument must be a string or a number
Exception TypeError: 'float() argument must be a string or a number' in 'cyipopt.jacobian_cb' ignored

что, я думаю, означает, что якобиан не оценивается.

0 ответов

Другие вопросы по тегам