WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Optimierung, fmincon beschleunigen

 

Lockyy
Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2016, 12:43     Titel: Optimierung, fmincon beschleunigen
  Antworten mit Zitat      
Hallo Leute,

ich optimiere gerade mit fmincon und würde meinen Solver gerne verbessern und beschleunigen.

Mal kurz das (vereinfachte)Problem umrissen:
Die gesuchten X-Werte sind Veränderungen in der Leistungen und liegen zwischen -XY und +XY. (rauf- und runterfahren).

Als Nebenbedingung sollen an manchen Stellen rauf und an manchen Stellen runtergefahren werden um andere Werte Y einzuhalten. Diese Nebenbedingungen sind über eine Sensitivitätsmatrix S verknüpft. Hier kann der Wert von X aber je nach dem positiv oder negativ sein.
S*X < Y

Meine Zielfunktion sind die Absolutwerte von X, da so wenig wie möglich verändert werden soll aber dies negativ oder positiv sein kann. Deswegen verwende ich fmincon. Vorher konnte ich es noch linear machen mit einer Fallunterscheidung. Das geht jetzt aber nicht mehr.
Fmincon funktioniert, ist aber verglichen mit einem linearen Problem natürlich langsamer.
Ich habe bereits den Algorithmus auf "sqp" gestellt, das bringt schon ein bisschen was. Gibt es da noch andere Möglichkeiten?

Gleichfalls bricht er öfters ab (obwohl die Nebenbedingungen nicht erfüllt sind), da die Schrittweite unter X-Tol liegt.

fmincon stopped because the size of the current step is less than
the selected value of the step size tolerance but constraints are not
satisfied to within the selected value of the constraint tolerance.

Eigentlich müssen die X-Toleranzen gar nicht so groß sein, aber sonst bricht er mir vorher schon ab. Kann ich das verhindern?

Ich weiß, dass das Thema "richtige Einstellungen" bei einem Optimierer extrem wichtig sind. Vielleicht kann mir da jemand den ein oder anderen Tipp geben.


PS: Ach ja und mir geht es wirklich um allgemeinere Sachen innerhalb dieses Themas, das aktuelle Skript verändert sich gerade laufend und ist sehr lang und komplexer.
Private Nachricht senden Benutzer-Profile anzeigen


Friidayy
Forum-Century

Forum-Century


Beiträge: 225
Anmeldedatum: 17.12.13
Wohnort: ---
Version: R2012b
     Beitrag Verfasst am: 02.02.2016, 16:04     Titel:
  Antworten mit Zitat      
Hallo Lockyy,

ich habe mich auch länger mit der Beschleunigung von Matlab Code beschäftigt. Neben einigen Anpassungen direkt im Code, also z.B. durch Preallocation, ... brachte mir das konvertieren der Zielfunktion in ein Mex-File den größten Beschleunigungsboost. Mit "Coder" konvertiest du deine Zielfunktion in ein Mex-File und ruft das dann anstelle der Matlab-Funktion auf, z.b.
minFunc(x,y) --> minFunc_mex(x,y)

Wie das genau abzulaufen hat, wird in dem Video ganz gut erklärt
https://www.youtube.com/watch?v=IZJ-IlI3QR0

Gruß
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2016, 17:54     Titel:
  Antworten mit Zitat      
Hallo Friidayy,

bisher wird meine Funktion einfach im Code definiert.

fun = @(x) sum(abs(x(1:100)))

Aber ich versuche das morgen mal, wenn du meinst, dass es was bringt. Im Moment rechnet er gerade mal wieder eine ziemliche Weile...
Private Nachricht senden Benutzer-Profile anzeigen
 
Friidayy
Forum-Century

Forum-Century


Beiträge: 225
Anmeldedatum: 17.12.13
Wohnort: ---
Version: R2012b
     Beitrag Verfasst am: 02.02.2016, 20:10     Titel:
  Antworten mit Zitat      
Mich wundert, dass es bei dir so lange dauert, da die Funktion ja rel. easy ausschaut.

Vllt. liegt es an der Unstetigkeit von abs, probier mal

fun=@(x) sum((x(1:100).^2)

aus. F alls du das mit dem Mex-File ausprobieren willst, definierst du einfach folgende Funktion:

Code:
function y=myFunc(x)
y=sum((x(1:100).^2);
end


Gruß
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 03.02.2016, 15:33     Titel:
  Antworten mit Zitat      
Hey, also der Coder scheint bei mir nicht installiert zu sein. Das Quadrat bringt ein bisschen was aber noch nicht viel.

Der Code ist deutlich komplizierter als dargestellt.
Ich habe für 216 Stellen jeweils drei Beschränkungen, d.h. meine Sensitivität S ist eine große Matrix. Die x0-Werte liegen bei mir bei 0, da ich das genauer nicht sagen kann (ca. von -100 bis +100).
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.02.2016, 14:36     Titel:
  Antworten mit Zitat      
Ich kenne mich leider nicht so ganz aus, aber es gibt ja noch mehr Einstellungen. Hesse Matrix z.B. - kann man damit was reißen?
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 04.02.2016, 15:16     Titel:
  Antworten mit Zitat      
Hallo,

ein ausführbares Code-Beispiel wäre hilfreich.

Wie lange ist denn "lange"?
Müssen mehrere Optimierungen ausgeführt werden? Falls ja, kann vielleicht das Ergebnis einer Optimierung als Startwert für die nächste verwendet werden?

Zudem kann man auch mal andere Solver versuchen. Mit der von Friiday vorgeschlagenen angepassten Zielfunktion wäre das ein Fall für lsqlin .

Man kann auch mal, sofern die Global Optimization Toolbox vorhanden ist, patternsearch versuchen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.02.2016, 13:19     Titel:
  Antworten mit Zitat      
Ok, dann hier mal ein paar Codeschnipsel aber ich sage gleich: schön und übersichtlich ist das nicht Smile .

Ich habe mal den Workspace in eine Datei gepackt und hoffe, dass das geht. Ich habe mal die Grenzen noch auf 0 gesetzt, an der Stelle, ab der sich da definitiv nichts ändern kann (erste Hälfte).

Der gesuchte Vektor sind Änderungen in der Leistung, Opt.x. Diese sind möglichst klein zu halten.
Zu den Grenzen: AA*x < bA muss eingehalten werden, alles unter dem Grenzwert data.imax, AA ist die Sensitivitätsmatrix

Aeq: in dem Fall werden alle Änderungen addiert
beq: und die sollen einen bestimmten Wert ergeben (an der Stelle 0)

data.Ba, PVA, usw. sind die Leistungen an den Stellen für Biomasseanlagen, PV-Anlagen, usw.

fun: Die gesamte Veränderung soll möglichst klein sein. Vorher wurde schon was verändert, deswegen wird diese mit dazu gezählt (kann sich ja wieder aufheben).
die Zahlen vor der Summe ist die Priorität, welche Anlagen zuerst genommen werden sollen.
Und hier ist der Knackpunkt. Um ein möglichst genaues Ergebnis zu bekommen, muss ich die entweder seeehr unterschiedlich machen (z.B. 10er-Potenzen) oder die Toleranz sehr klein machen. Beides kostet extrem viel Zeit. Ich will natürlich ein möglichst genaues Ergebnis, z.B. die WaA (Wasserkraftanlagen) sollen nur im Notfall benutzt werden.
Was ist hier sinnvoller???


An der Stelle kommt jetzt mein Optimierungscode:
Code:

bA = data.imax - Aus(:,iter)-5;
Aeq = [zeros(1,data.EinsNr), ones(1,data.EinsNr)];
x0 = zeros(2*data.EinsNr, 1);
AA = [zeros(size(SMA)),SMA];

beq = Opt.dPsoll(iter-1);

fun = @(x)sum(((sum(Opt.PQ(data.EinsNr+data.BA(:,1)),2)+x(data.EinsNr+data.BA(:,1))).^2))...
   + 100*sum(((sum(Opt.PQ(data.EinsNr+data.PVA(:,1)),2)+x(data.EinsNr+data.PVA(:,1))).^2)) + 10*sum(((sum(Opt.PQ(data.EinsNr+data.WKA(:,1)),2)+x(data.EinsNr+data.WKA(:,1))).^2))...
   + 1000*sum(((sum(Opt.PQ(data.EinsNr+data.WaA(:,1)),2)+x(data.EinsNr+data.WaA(:,1))).^2)) + 2*sum(((sum(Opt.PQ(data.EinsNr+data.KWKA(:,1)),2)+x(data.EinsNr+data.KWKA(:,1))).^2));

options = optimoptions('fmincon','Display','iter','MaxFunEvals',100000,'MaxIter',1000,'Algorithm','sqp','TolX',1e-25,'TolCon',1e-2, 'TolFun',1e-2);
G.lb2 = G.lb-0.0001;
G.ub2 = G.ub;
G.lb2(1:data.EinsNr) = 0;
G.ub2(1:data.EinsNr) = 0;
[Opt.x] = fmincon(fun,x0,AA,bA,Aeq,beq,G.lb2,G.ub2,[],options);

 


Bisher ist es eben so, dass mir das Ergebnis zu ungenau ist. Wenn ich aber aber die Prioritäten oder die Genauigkeit zu stark einstelle, dauert die Berechnung sehr lange.

Ach ja, und TolX ist so hoch, weil er sonst manchmal mitten in der Berechnung abbricht. Hatte ich weiter oben ja schon geschrieben.

Workspace.mat
 Beschreibung:

Download
 Dateiname:  Workspace.mat
 Dateigröße:  166.96 KB
 Heruntergeladen:  367 mal
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.02.2016, 17:22     Titel:
  Antworten mit Zitat      
Kleiner Nachtrag:

Ich würde nach Möglichkeit doch den abs benutzen, da sich dann wenig Leistungen effektiv ändern. Bei ^2 ändern sich viele Leistungen ein bisschen...
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 05.02.2016, 17:58     Titel:
  Antworten mit Zitat      
Hallo,

zu 12:19
Die einzige Möglichkeit, einige Parameter zunächst konstant zu lassen, sehe ich in folgender Vorgehensweise:
x1 = fmincon(..., x0, ...) % erste Optimierung mit wenigen Parametern
x2 = fmincon(..., x1, ...) % Optimierung aller Parameter mit vorherigem Ergebnis als Startwert
Natürlich kann man das auch weiter schachteln.

zu 16:22
Problem bei abs: nicht differenzierbar, insofern ist fmincon bei um die 0 schwankenden Einträgen schlecht geeignet.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 08.02.2016, 12:36     Titel:
  Antworten mit Zitat      
Mit anderen Worten: Da kann man eigentlich gar nicht viel machen außer entweder eine andere Zielfunktion zu nehmen oder die Zeit eben einzuplanen!?
Na gut, danke mal trotzdem!
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 08.02.2016, 13:38     Titel:
  Antworten mit Zitat      
Hallo,

ich hatte ja schon mal gefragt:
Zitat:
Wie lange ist denn "lange"?
Müssen mehrere Optimierungen ausgeführt werden?


Wirklich weiterhelfen kann man wohl nur mit einem reproduzierbaren Beispiel.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 10.02.2016, 13:39     Titel:
  Antworten mit Zitat      
Ein Beispiel hatte ich ja gepostet. Ich habe jetzt für die Anfangswerte davor noch eine lineare Optimierung machen können und komme nun mit ausreichender Genauigkeit auf 10-80 s pro Optimierung. Ist ok...
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 10.02.2016, 14:52     Titel:
  Antworten mit Zitat      
Hallo,

mit Nullen rechnen ist alles andere als ideal. Vorschlag stattdessen:

Code:
fun2 = @(x) fun([zeros(data.EinsNr,1); x]);
idx = data.EinsNr+1:numel(x0);
[x2] = fmincon(fun2,x0(idx),AA(:,idx),bA,Aeq(:,idx),beq,G.lb2(idx),G.ub2(idx),[],options);


Natürlich sollte man fun2 "schön" schreiben.

Falls mehrere Optimierungen ausgeführt werden müssen, kann man bei ähnlichen Szenarien häufig das Ergebnis einer Optimierung als Startwert für die nächste verwenden.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Lockyy
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 27
Anmeldedatum: 26.11.15
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 10.02.2016, 16:28     Titel:
  Antworten mit Zitat      
Ja, das mit den Nullen habe ich an der Stelle auch rausgekickt. Der erste Teil fliegt raus. Hat allerdings zeitmäßig gar keinen sooo großen Vorteil gebracht.
Das Ergebnis als neuer Startwert wird schon gemacht.

Ich weiß aber auch echt nicht, ob man da jetzt noch viel rausholen kann von der Geschwindigkeit.
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.