IpOpt отказывается решать неограниченную проблему

Я новичок в IpOpt, и я пытаюсь решить с его помощью простую задачу неограниченной оптимизации. Моя проблема - это просто квадратичная функция f(x) = (5x - 3)^2.

Я создал простой класс для этой проблемы:

#include <cstdio>

#include "IpIpoptApplication.hpp"
#include "IpTNLP.hpp"

using namespace Ipopt;
class MyProblem : public Ipopt::TNLP
{
public:
    const int nVars = 1;
    virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
                              Index& nnz_h_lag, IndexStyleEnum& index_style)
    {
        n = nVars;
        m = 0;
        nnz_jac_g = 0;
        nnz_h_lag = 1;
        index_style = IndexStyleEnum::C_STYLE;
        return true;
    }

    virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
                                 Index m, Number* g_l, Number* g_u)
    {
        return true;
    }

    virtual bool get_starting_point(Index n, bool init_x, Number* x,
                                    bool init_z, Number* z_L, Number* z_U,
                                    Index m, bool init_lambda,
                                    Number* lambda)
    {
        std::cout << "get_starting_point" << std::endl;

        if (init_x){
            x[0] = 0.0;
        }
        return true;
    }

    virtual bool eval_f(Index n, const Number* x, bool new_x,
                        Number& obj_value)
    {
        const Number residual = (5 * x[0] - 3);
        obj_value = residual * residual;
        std::cout << "obj_value " << obj_value << std::endl;
        return true;
    }

    virtual bool eval_grad_f(Index n, const Number* x, bool new_x,
                             Number* grad_f)
    {
        const Number residual = (5 * x[0] - 3);
        grad_f[0] = 2 * 10 * residual;
        std::cout << "grad_f " << grad_f[0] << std::endl;
        return true;
    }

    virtual bool eval_g(Index n, const Number* x, bool new_x,
                        Index m, Number* g)
    {
        std::cout << "eval_g was called m = " << m << " *g " << g << std::endl;
        return true;
    }

    virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
                            Index m, Index nele_jac, Index* iRow,
                            Index *jCol, Number* values)
    {
        std::cout << "eval_jac_g was called" << std::endl;
        return true;
    }

    virtual void finalize_solution(SolverReturn status,
                                   Index n, const Number* x, const Number* z_L, const Number* z_U,
                                   Index m, const Number* g, const Number* lambda,
                                   Number obj_value,
                                   const IpoptData* ip_data,
                                   IpoptCalculatedQuantities* ip_cq)
    {
        std::cout << "X final " << x[0] << std::endl;
    }
};

int main()
{    
    SmartPtr<TNLP> mynlp = new MyProblem();
    SmartPtr<IpoptApplication> app = new IpoptApplication();

    app->Initialize();
    ApplicationReturnStatus status = app->OptimizeTNLP(mynlp);
    if (status == Solve_Succeeded) {
      printf("\n\n*** The problem solved!\n");
    }
    else {
      printf("\n\n*** The problem FAILED!\n");
    }


    return 0;
}

Я установил m = 0; и nnz_jac_g = 0;, чтобы показать, что у меня нет ограничений

IpOpt дает мне следующий вывод:

******************************************************************************
This program contains Ipopt, a library for large-scale nonlinear optimization.
 Ipopt is released as open source code under the Eclipse Public License (EPL).
         For more information visit http://projects.coin-or.org/Ipopt
******************************************************************************

This is Ipopt version 3.12.11, running with linear solver mumps.
NOTE: Other linear solvers might be more efficient (see Ipopt documentation).

eval_g was called m=0 *g 0x5559e0661fd0
obj_value 9
X final 0
All variables are fixed and constraint violation 0.000000e+00
   is below tolerance 1.000000e-08. Declaring success.

EXIT: Optimal Solution Found.


*** The problem solved!

Но, очевидно, решение проблемы должно быть чем-то вроде x = 3/5.

Что не так с моим проблемным классом?

Насколько я могу судить, IpOpt не вызывал метод get_starting_point, что выглядит довольно странно.

Моя версия IpOpt - 3.12.11, gcc - 7.2.0-8ubuntu3.2. Я могу предоставить больше информации, но понятия не имею, что еще я могу показать. Исходный код должен быть достаточно красивым

PS извини за плохой английский

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
496
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы должны определить границы переменных.

virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
                             Index m, Number* g_l, Number* g_u)
{
    *x_l = -1e19; //nlp_lower_bound_inf
    *x_u = 1e19; //nlp_upper_bound_inf
    return true;
}

Ваши переменные случайным образом (потому что другие компиляторы, вероятно, предоставляют разные значения для неопределенных границ) заморожены нулевыми границами.

Есть еще одна ошибка. Вы должны либо определить eval_h, либо указать схему гессианской аппроксимации.

Спасибо за ответ! Небольшой вопрос - мой m должен быть 0, есть ли в x_u и x_l элементы?

Dark_Daiver 30.10.2018 17:39
x_u и x_l - это границы переменных, которые в вашем случае имеют размер n = 1, и вы должны заполнить их как минимум максимально возможными значениями. g_u и g_l - это границы ограничений, размер которых равен m = 0, и их не следует трогать в вашем случае.
Askold Ilvento 30.10.2018 17:47

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