Код: Выделить всё
draft
Код: Выделить всё
heel
Это по сути, это задача математической оптимизации, поэтому я использую библиотеку NLopt (в частности, NLoptNet, поскольку это проект C#). Существует три параметра управления (осадка, крен и дифферент) и три цели, которые необходимо минимизировать (
Код: Выделить всё
netUpwardForce
Вот код:
Код: Выделить всё
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)
}

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