Verfasst am: 17.01.2013, 15:38
Titel: Variablennamen in einer Schleife verschiedeneWerte zu weisen
Hallo,
hab schon den ganzen Tag an verschiedenen Problemen rumgetüftelt, so dass ich gerade nicht mehr weiterkomme (bin leer)...vielleicht könnt ihr mir helfen:
in der j-Schleife die Werte - in diesem Fall - 1 und (danach) 2 zu gewiesen werden (in j passiert normalerweise mehr)!
Und bevor der nächsten Variable andere Werte zu gewiesen werden, werden alle wieder auf eins gestellt!
Möchte also, dass in der j-Schleife folgendes gilt:
R1=1; R2=1; R3=1;
R1=2; R2=1; R3=1;
R1=1; R2=1; R3=1;
R1=1; R2=2; R3=1;
R1=1; R2=1; R3=1;
R1=1; R2=1; R3=2;
(Die Variablennamen werden in der j-SChleife an ein Simunlink-Modell übergeben!)
Verfasst am: 17.01.2013, 17:04
Titel: Re: Variablennamen in einer Schleife verschiedeneWerte zu we
Hallo Waldemar,
Variablen R1, R2, R3, ... zu erzeugen ist prinzipiell eine sehr schlechte Idee. Es ist deutlich effizienter und besser zu debuggen, wenn Du einen Index als Index verwendest, anstatt ihn im Namen der Variablen zu verstecken, wo er zum Schreibn und Lesen erst umständlich herausgepfriemelt werden muss.
Besser: Entweder "R = zeros(1, 3)" oder ein anderes Array, falls alle R's den gleichen Typ und die gleiche Dimension haben, oder andernfalls: "R = cell(1, 3)".
Siehe dazu hunderte Themen in diesem Forum zum Stichwort "eval".
bei deinem Vorschlag komme ich doch auch in das Problem, etwas, was bislang rechts des Gleichheitszeichens steht, nicht auf die linke Seite zu bekommen!!!
Zunächst: Ich verstehe nicht so ganz, was du erreichen möchtest.
Sollen R1 bis R3 Variablen sein, denen du entweder 1 oder 2 zuordnest?
Du erstellst ein cell mit 6 Variablen und dazu 6 Werten. In der for-Schleife änderst du dann aber nicht die 6 Werte, sondern machst iwas mit den 6 Variablen, was ich nicht verstehe; Stichwort char. Du legst damit eine weitere Variable char an (was übrigens ein Matlab-Befehl ist und sich somit nicht gerade anbietet). Und plötzlich gibt es auch noch Qi. Ich bin verwirrt
---
Ich geh mal davon aus, du willst als Ziel so etwas haben:
Wie Jan bereits sagte, geht das einfacher, wenn du nicht 3 Variablen mit den Indizes im Namen erstellst, sondern ein Array, dessen Indizes du dann verwenden kannst, um die entsprechenden Werte anzusprechen.
R(1, 1) ist der Wert für dein R1, R(1, 2) ist dein R2, R(1, 3) ist dein R3
So erzeugst du dann dieses Array und veränderst in der Schleife bei jedem 2. Durchlauf ein Element von R:
Code:
j = 1;
for i = 1:1:6 ifmod(i, 2) == 1% i ist ungerade
R = ones(1, 3);
else
R(1, j) = 2;
j = j + 1;
end end
Wenn du aber wirklich R1, R2, R3 explizit erzeugen willst, um diese bspw. später als Output zu verwenden, kannst du das per Cell (oder per Struct, s.u.) machen:
Code:
R_orig = {'R1', 'R2', 'R3'; 1, 1, 1};
j = 1;
for i = 1:1:6 ifmod(i, 2) == 1% i ist ungerade
R = R_orig;
else
R{2, j} = 2;
j = j + 1;
end end
Im ersten Code-Bsp. haben wir den Vektor R vom Typ double 1x3. Dieser ist jetzt quasi in unserem Cell die Zeile 2. Beachte allerdings den Unterschied von R(2, 1) und R{2, 1}. In Zeile 1 haben wir die Bezeichnungen R1, R2, R3.
Jetzt mit einer Struktur:
Code:
R.namen = {'R1', 'R2', 'R3'};
j = 1;
for i = 1:1:6 ifmod(i, 2) == 1% i ist ungerade
R.werte = ones(1, 3);
else
R.werte(1, j) = 2;
j = j + 1;
end end
Jetzt haben wir wieder den Zahlenvektor aus Code-Bsp. 1 (R.werte), zusätzlich auch Bezeichnungen (R.names), auf die wir leichter zugreifen können als in einem Cell.
Zunächst mal empfehle ich, dass vollkommen sinnfreie aber ebenso weitverbreitete "clear all" wegzulassen. Es löscht auch alle geladenen Funktionen aus dem Speicher, was dann nützlich ist, wenn man während des Programm-Ablaufs alle M-Files geändert hat. Da das aber wohl kaum jemand jemals machen wird, bleibt mir die inflationäre Anwendung von "clear all" ein mystisches Rätsel. "clear variables" wäre sinnvoller, obwohl es immer noch recht brutal säubert.
Aber zurück zum eigentlichen Problem: Wie ich schon sagte, ist es ein schlechtes Programmdesign und ein typischer Anfänger-Fehler, für eine Zuweisung die linke Seite dynamisch zu erzeugen. Das ist zwar möglich, macht aber das Programm deutlich langsamer, heftig komplizierter und dadurch kaum debug- oder erweiterbar. Es führt ohne Not eine zusätzliche Abstraktions-Ebene ein.
Links vom "=" muss eine Variable stehen und kein String. Das sieht zwar im Source-Code irgendwie ähnlich aus, es sind ja beides Buchstabenketten. Aber die Strings sind von Quotes eingefasst, und die Variablennamen nicht.
Man macht sich also am besten erst gar nicht den Umstand, "R1", "R2", ... als Strings oder Variablen zu definieren, sondern benutzt gleich ein Array oder cell Array wie "R{1}", "R{2}", ...
Wenn man wirlich einen Variablen-Namen dynamisch produzieren muss, weil es deutlich übersichtlicher ist, verwendet man "dynamic fieldnames":
Donald E. Knuth, einer der größten Computer-Forscher überhaupt, propagierte das leicht zu merkende Motto:
Zitat:
KISS: Keep it simple stupid
D.h., man soll ein Programm so einfach formulieren wie irgend möglich. Dann hat man die geringesten Schwierigkeiten beim Programmieren, Debuggen und der Rechner auch den geringsten Aufwand beim Abarbeiten. Deshalb solte man vermeiden, Variablen in Variablen zu speichern, nur um ihnen Werte zuzuweisen.
Ist dies etwas klarer geworden?
Zusätzlich führe ich mal das ganze Skript auf:
(Die R1, R2, R3, Q1, Q2 und Q3 brauche ich nämlich im Simulink-Modell)
Code:
% M-File zum Starten der Modellsimulation um die optimalen % Elemente der Wichtungsmatrizen Q und R je Betriebspunkt zu ermitteln!
% Ziel ist, für jeden Betriebspunkt die Elemente der Wichtungsmatrizen EINZELN zu variieren und die dazugehörige Regelguete_Ges in Zusammenhang mit den aktuellen Werten der Wichtungsmatrizen abzuspeichern!
% Simulationsschrittweite
stepSize = 0.03; % 10 ms % Anstelle von 0.06!
% Simulationsdauer vordefinieren
simTime = 18;
% PT1-Zeitkonstante
T_PT1 = 2; % für AGRstat --> AGRdyn
% Laden der MAT-Files für die Streckenmodelle und Ableitungsmodelle load('modLOLIMOT_3In_CA50');
load('modLOLIMOT_3In_IMEP');
load('modLOLIMOT_3In_DPMAX');
load('modLOLIMOT_3In_HC');
load('modLOLIMOT_3In_NOX');
% BETRIEBSPUNKTE folgen aus den Messdaten, die zur Ermittlung der Regelstrecke (Ableitungs- und Streckenmodell) genutzt wurden! Andernfalls oder auch in Kombination damit können Betriebspunkte aus den Randbedingungen des Prüfstandes (siehe Konzeptentwurf) gewonnen werden!
Betriebspunkt=[6.70,2.50,58;
-8.30,2.30,397;]; % Im Orginalskript gibt es viel mehr Betriebspunkte! (Hier verkürzte Version).
% CA50, IMEP und NOx geben in den Sprüngen den Wert vor! % Schnittstellen zwischen Script und Model!!
% Jetzt möchte ich alle Elemente - zu variieren sind: R1, R2, R3, Q1, Q2 und Q3 - der Wichtungsmatrizen Q und R (Diagonalmatrix) einzeln und nacheinander ("einzeln und nacheinander"---> k-SCHLEIFE) in einem vordefinierten Bereich (j-SCHLEIFE) für jeden Betriebspunkt (i-SCHLEIFE) variieren und den resultierenden Wert der Regelgüte mit den aktuellen Werten der Elemente (R1, R2, R3, Q1, Q2, Q3) abspeichern!!! % Die aktuellen Werte der Elemente werden in: % Ins_Matrix(j,(i-1)*length_WUrspr+k)=Insgesamt; abgespeichert! % Die aktuelle Regelguete_ges wird in: % Regelguete_Ges_Matrix(j,(i-1)*length_WUrspr+k)=Regelguete_Ges; abgespeichert!
% R1, R2, R3, Q1, Q2 und Q3 sind weitere Schnittstellen zwischen dem Script und dem Model!!
% Modell öffnen und Simulation starten:
MDLsim = 'Regelung_DREIxDREI_hnBx_Vll_Bp_Nstll_nDr_LIN_NOx_OPT';
open(MDLsim);
set_param('Regelung_DREIxDREI_hnBx_Vll_Bp_Nstll_nDr_LIN_NOx_OPT','SimulationCommand','start');
% Matlab ist schneller, als das Simulink-Modell! Da ich allerdings in der weiteren Berechnung auf toWorkspace-Variablen (Regelguete_ges) zurückgreife, muss ich Matlab anhalten:
% Regelguete_ges.signals.values resultiert aus der Simulation!
Regelguete_Ges=max(Regelguete_ges.signals.values);
Regelguete_Ges_Matrix(j,(i-1)*length_WUrspr+k)=Regelguete_Ges;
- Wenn sich jemand mein Skript (unteres) anschaut, wo könnte ich Zeit sparen!?
- Wie suche ich in Matlab am besten nach vorprogrammierten Funktionen? Hätte da jemand ein Kochrezept für mich?
- Kennt jemand von euch eine Funktion, die optimale Eingangsgrößen berechnet? Konkreter Fall:
Also ich habe ein Simulink-Modell, dass ich durch R1, R2, R3, Q1, Q2 und Q3 (weitere Eingangsgrößen sind CA50, IMEP und NOx (sollen nicht optimiert werden)) beeinflussen kann. Als Ausgangsgröße habe ich 1 Größe (Regelguete_Ges). Die Eingangsgrößen R1, R2, R3, Q1, Q2 und Q3 sollen so optimiert werden, dass die Ausgangsgröße Regelguete_Ges MINIMAL wird!!! Dabei ist zu achten, dass diese Eingangsgrößen größer Null sind!
Gibt es eine Funktionen, die auch das Zusammenspiel zwischen Matlab und Simulink händeln kann?
Wäre super, wenn ihr paar Tipps geben könntet.
Jedenfalls bis hier schonmal ein großes Danke.
meine ürbigen Fragen konnte ich auf Grundlage einer Internet-Recherche beantworten! (Suche:" Simulink optimieren")
Gucken, ob ich es zusammen bekomme!
Jedenfalls vielen Dank für eure Hilfe!
MfG, Waldemar
_________________
Im "ich brauch Hilfe"-Status
Einstellungen und Berechtigungen
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
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.