Трудности достижения сходимости с помощью математической оптимизации NLopt для физической задачи.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Трудности достижения сходимости с помощью математической оптимизации NLopt для физической задачи.

Сообщение Anonymous »

Я пишу физический симулятор для моделирования статического поведения объектов, плавающих в воде (в основном кораблей). Положение объекта описывается глубиной погружения () и два угла ( и обрезать). На объект всегда действуют как минимум 2 силы — вес и плавучесть, но их может быть и больше. Сила описывается как величина, начало координат и вектор. Симулятор должен сбалансировать силы так, чтобы результирующая восходящая сила и поворотные моменты (для крена и дифферента) были близки к нулю.
Это по сути, это задача математической оптимизации, поэтому я использую библиотеку NLopt (в частности, NLoptNet, поскольку это проект C#). Существует три параметра управления (осадка, крен и дифферент) и три цели, которые необходимо минимизировать (

Код: Выделить всё

netUpwardForce
, heelMoment и TrimMoment). Изменение значения одного параметра влияет на все три цели, но одна всегда больше, чем другие (например, изменение heel влияет на heelMoment гораздо сильнее, чем другие цели). К сожалению, NLopt не позволяет использовать несколько целей, поэтому их приходится нормализовать и объединить в одну.
Вот код:

Код: Выделить всё

double OptimizeFunc(double[] parameters) //parameters: Draft, heel and trim
{
Model.SetPosition(parameters[0], parameters[1], parameters[2]);

List forces = new(){ Model.GetBuoyantForce(), Model.GetWeightForce() };

StabilityData stabilityData = StabilityCalculator.Calculate(forces); //calculates net upward force, heeling moment and trimming moment

double netUpForceComp = Math.Abs(stabilityData.NetUpwardForce / Model.GetMaximumTheoreticalBuoyancyForce());
double heelMomComp    = Math.Abs(stabilityData.HeelingMoment  / Model.GetMaximumTheoreticalHeelingMoment());
double trimMomComp    = Math.Abs(stabilityData.TrimmingMoment / Model.GetMaximumTheoreticalTrimmingMoment()));

double total = netUpForComp + heelMomComp + trimMomComp;

return total;
}

var parameters = { 0, 0, 0 } ;

using (solver = new NLoptSolver(NLoptAlgorithm.LN_BOBYQA, (uint)parameters.Count))
{
solver.SetLowerBounds(new double[] {0, -180 , -90});
solver.SetUpperBounds(new double[] {Model.GetModelHeight(), 180 , 90});
solver.SetMinObjective(OptimizeFunc);

var nLoptResult = solver.Optimize(new double[] {0, 0 , 0}, out var finalScore);

Debug.Print(finalScore)
}
Проблема, с которой я столкнулся, заключается в том, что NLoptSolver не может минимизировать цель (найти значения уклона, крена и обрезки, которые приводят к почти нулевая чистая восходящая сила и моменты крена/дифферента). Для конкретного теста, который я провожу, это график 50 попыток, который делает NLoptSolver, на котором отображается оценка (значение, возвращаемое OptimizeFunc), а также уклон, пятка и обрезать использованные значения.
Изображение

Несмотря на то, что решатель думает, что нашел локальный минимум, путем ручной настройки значений уклона, крена и обрезки я знаю, что на самом деле лучшее решение – черновик = 0,202, пятка = 0, обрезка = -0,32, что дает оценку = 0,001 (и это можно было бы еще уточнить, но я остановился на этом). Между тем, как видно из графика, решателю удается достичь только оценки = 0,013, что даже близко не близко. Я провел дополнительные тесты, чтобы отобразить все пространство оптимизации, и подтвердил, что других минимумов, кроме этого, нет. Я также пытался ограничить границы очень близко к этому известному минимуму, но решатель все равно не смог его найти.
Я подозреваю, что проблема в том, что HeelingMoment и TrimmingMoment очень чувствительны к тому, что NetUpwardForce не равен нулю, поэтому я попробовал добавить весовые коэффициенты, чтобы оптимизатор сначала отдавал приоритет минимизации NetUpwardForce, но это не помогает. Я также пытался отказаться от оптимизации HeelingMoment и TrimmingMoment и вместо этого настроить оптимизатор на минимизацию горизонтальных расстояний между центрами сил плавучести и веса, но это тоже не помогло. Я также пытался повысить степень netUpForComp, heelMomComp и TriMomComp, и это немного помогло, но проблему все равно не решило.
Может ли кто-нибудь, имеющий опыт математической оптимизации, подсказать, что может быть не так с моим подходом? Это способ вычисления суммы в OptimizeFunc? Или мне следует использовать другой алгоритм вместо BOBYQA? Я попробовал несколько, но ни один из них не дал лучших результатов.
РЕДАКТИРОВАТЬ: дополнительная информация: если я передам правильные параметры решения (

Код: Выделить всё

draft = 0.202
, heel = 0, Trim = -0,32) в качестве начальных начальных значений для Nlopt, затем он фиксируется на этом решении и принимает его как допустимое после нескольких циклов. Но этого не происходит при старте с нулевых значений, даже если они относительно очень близки к правильным значениям решения.

Подробнее здесь: https://stackoverflow.com/questions/793 ... n-for-a-ph
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»