Schwierigkeiten beim Erreichen der Konvergenz mit der mathematischen NLopt-Optimierung für ein physikalisches ProblemC#

Ein Treffpunkt für C#-Programmierer
Guest
 Schwierigkeiten beim Erreichen der Konvergenz mit der mathematischen NLopt-Optimierung für ein physikalisches Problem

Post by Guest »

Ich programmiere einen Physiksimulator zur Simulation des statischen Verhaltens von im Wasser schwimmenden Objekten (hauptsächlich Schiffe). Die Objektposition wird durch die Eintauchtiefe beschrieben (

Code: Select all

draft
) und zwei Winkel (

Code: Select all

heel
und trimmen). Es wirken immer mindestens zwei Kräfte auf das Objekt ein – Gewicht und Auftrieb, es können aber auch mehr sein. Kraft wird als Größe, Ursprung und Vektor beschrieben. Der Simulator muss die Kräfte so ausgleichen, dass die Nettoaufwärtskraft und die Drehmomente (für Krängung und Trimmung) nahezu Null sind.
Dies ist im Grunde ein mathematisches Optimierungsproblem, daher verwende ich die NLopt-Bibliothek (insbesondere NLoptNet, da es sich um ein C#-Projekt handelt). Es gibt drei Steuerparameter (Tiefgang, Krängung und Trimm) und drei zu minimierende Ziele (

Code: Select all

netUpwardForce
, ferseMoment und trimMoment). Die Änderung des Werts eines Parameters wirkt sich auf alle drei Ziele aus, jedoch auf eines immer stärker als auf andere (z. B. wirkt sich eine Änderung der Ferse viel stärker auf HeelMoment aus als auf andere Ziele). Leider erlaubt NLopt nicht mehrere Ziele, daher müssen diese normalisiert und zu einem kombiniert werden.
Hier ist der Code:

Code: Select all

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)
}
Das Problem, das ich habe, ist, dass der NLoptSolver das Ziel nicht minimieren kann (die Werte für Tiefgang, Ferse und Trimm finden, die dazu führen). Nettoaufwärtskraft und Fersen-/Trimmmomente nahe Null). Für einen bestimmten Test, den ich durchführe, ist dies das Diagramm von 50 Versuchen, die der NLoptSolver durchführt, wobei die Punktzahl (von OptimizeFunc zurückgegebener Wert) sowie Draft, Heel und dargestellt werden trim verwendete Werte.
Image
< /p>
Auch wenn der Löser glaubt, ein lokales Minimum gefunden zu haben, weiß ich durch manuelles Anpassen der Werte für Tiefgang, Ferse und Trimm, dass die tatsächlich beste Lösung Tiefgang = 0,202 ist, Heel = 0, Trim = -0.32, was zu einem Score = 0.001 führt (und es könnte noch weiter verfeinert werden, aber ich habe dort aufgehört). Wie Sie der Grafik entnehmen können, erreicht der Löser unterdessen nur einen Wert von 0,013, was nicht einmal nahe kommt. Ich habe zusätzliche Tests durchgeführt, um den gesamten Optimierungsbereich abzubilden, und bestätigt, dass es außer diesem keine weiteren Mindestwerte gibt. Ich habe auch versucht, die Grenzen sehr nahe an diesem bekannten Minimum einzuschränken, aber der Löser kann es immer noch nicht finden.
Ich vermute, dass das Problem an HeelingMoment und TrimmingMoment reagieren sehr empfindlich darauf, dass NetUpwardForce nicht Null ist, daher habe ich versucht, Gewichtungsfaktoren hinzuzufügen, damit der Optimierer zuerst die Minimierung von NetUpwardForce priorisiert, aber das hilft nicht weiter. Ich habe auch versucht, die Optimierung für HeelingMoment und TrimmingMoment zu verwerfen und stattdessen den Optimierer so einzustellen, dass die horizontalen Abstände zwischen den Auftriebs- und Gewichtskraftzentren minimiert werden, aber auch das hat nicht geholfen. Ich habe auch versucht, netUpForComp, HeelMomComp und trimMomComp auf höhere Potenzen zu erhöhen, und das hat ein wenig geholfen, löst das Problem aber immer noch nicht.
Kann jemand, der Erfahrung mit mathematischer Optimierung hat, vorschlagen, was an meinem Ansatz falsch sein könnte? Ist es die Art und Weise, wie ich die Gesamtsumme in OptimizeFunc berechne? Oder sollte ich anstelle von BOBYQA einen anderen Algorithmus verwenden? Ich habe mehrere ausprobiert, aber keines hat zu besseren Ergebnissen geführt.
BEARBEITEN: Zusätzliches Detail: Wenn ich die richtigen Lösungsparameter übergebe (

Code: Select all

draft = 0.202
, Heel = 0, trim = -0.32) als anfängliche Startwerte für Nlopt, dann greift es auf diese Lösung zu und akzeptiert sie nach einigen Zyklen als gültig. Dies ist jedoch nicht der Fall, wenn mit Nullwerten begonnen wird, obwohl diese relativ sehr nahe an den korrekten Lösungswerten liegen.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post