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

Vektoren anpassen

 

Gast



Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 22.01.2012, 21:18     Titel: Vektoren anpassen
  Antworten mit Zitat      
Hallo zusammen, ich habe folgendes Problem und komme leider nicht auf Lösung, ich hoffe ihr könnt mir weiterghelfen, wahrscheinlich ist es auch gar nicht so schwer:-)

also ich habe einen Vektor derart: A = [0 0 1 2 3 0 0 1 2 0]

jetzt möchte ich ihn derart verändern sodass am Ende folgendes herauskommt:

A = [ 0 0 3 3 3 0 0 2 2 0] d.h dass für einen Bereich welcher ungleichnull ist alle Werte in diesem Bereich den des höchsten Wertes annehmen!

ich habe alles mögliche probiert aber leider ist nie was draus geworden:(

vielen Dank schon mal im Vorraus!!


Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 18.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 23.01.2012, 01:45     Titel:
  Antworten mit Zitat      
Hi,

Kann man vermutlich auch einfacher machen, aber es funktioniert Very Happy
Vor allem das Erzeugen von B find ich sehr unelegant.
Vielleicht schaut hier noch ein Experte rein und kann das schöner lösen, würde mich interessieren.


Code:
A       = [0 0 1 2 3 0 0 1 2 0];
logA    = A > 0;
B       = [];

for i=1:length(A)-1
    if A(i)==0 && A(i+1)~=0         % Anfang eines Bereichs
        anfang  = i+1;
        B(i)    = 0;
       
        if i==length(A)-1
           B(i+1)   = A(length(A));
        end
    elseif A(i)~=0 && A(i+1)==0     % Ende eines Bereichs
        ende    = i;
        maximum = max(A(anfang:ende));
        help    = logA(anfang:ende) * maximum;
        B(anfang:(ende-1)) = [];
        B       = [B, help];
       
        if i==length(A)-1
            B(i+1)  = 0;
        end
    else
        B(i)    = 0;
       
        if i==length(A)-1
            B(i+1)  = 0;
        end
    end
end


Gruß,
Seb

edit:
Das war meine erste Idee: Ich wollte den relevanten Bereich des logischen Vektors von A mit dem Maximum des Bereichs multiplizieren. Weiß jedoch nicht, wie ich das dann zum Ausgabevektor B zusammengefrickelt bekomme.
Code:
A       = [0 0 1 2 3 0 0 1 2 0];
logA    = A > 0;
B        =logA;

for i=1:length(A)-1
    if A(i)==0 && A(i+1)~=0         % Anfang eines Bereichs
        anfang  = i+1;
       
        if i==length(A)-1
           B(i+1)   = A(length(A));
        end
    elseif A(i)~=0 && A(i+1)==0     % Ende eines Bereichs
        ende    = i;
        maximum = max(A(anfang:ende));
       
        help= B(anfang:ende) * maximum
        B = ????                         % hier scheiter ich (s.o.)
    end
end
Private Nachricht senden Benutzer-Profile anzeigen
 
Gast



Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 23.01.2012, 12:00     Titel:
  Antworten mit Zitat      
Super vielen Dank!starker code:-)
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 23.01.2012, 12:20     Titel:
  Antworten mit Zitat      
Hallo

Code:

A         =  [0 0 1 2 3 0 0 1 2 0];
s_pos     =  strfind([0 A>0 0],[0 1]);
e_pos     =  strfind([0 A>0 0],[1 0]);
max_val   = arrayfun(@(s,e)max(A(s:e)),s_pos,e_pos-1);
A         =  zeros(size(A));

A(s_pos)  = max_val;
A(e_pos)  = -max_val;
A         = cumsum(A);
 
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 18.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 24.01.2012, 11:01     Titel:
  Antworten mit Zitat      
Hab ich mir schon gedacht, dass das mal wieder vektoriell deutlich eleganter zu lösen ist. Das ist mein größtes Problem, ich löse zu viel mit Schleifen etc weil ich mal 2 Veranstaltungen C++ hatte.

Bin zwar mit meinem MATLAB-Buch erst halb durch, aber bisher kam noch nichts dazu. Wie kommt man auf solche Funktionen wir strfind oder cumsum? Macht das einfach die Erfahrung oder sollte man zu Anfang immer nach einer möglicherweise vorhandenen Funktion suchen? Wie ist da eure Herangehensweise (gewesen)?

Grüße,
Seb
Private Nachricht senden Benutzer-Profile anzeigen
 
denny
Supporter

Supporter



Beiträge: 3.853
Anmeldedatum: 14.02.08
Wohnort: Ulm
Version: R2012b
     Beitrag Verfasst am: 24.01.2012, 15:10     Titel:
  Antworten mit Zitat      
Das schnappt man sich irgendwo dann auf.

STRFIND habe ich zuerst nur mit Strings angewendet, dann habe ich Beispiele in Forum mit Logischen Arrays gesehen.

CUMSUM habe ich zu selten angewendet. Aus Jan's Bespielen habe ich zu CUMSUM viel gelernt.
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 18.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 24.01.2012, 18:25     Titel:
  Antworten mit Zitat      
denny hat Folgendes geschrieben:
Das schnappt man sich irgendwo dann auf.

Das beruhigt, kenn durch den Thread ja jetzt 2 neue Funktionen Very Happy

Was meinst du mit Jans Beispielen?
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 25.01.2012, 00:21     Titel:
  Antworten mit Zitat      
Hallo Seban,

Ich habe in diesem Forum ein paar Lösungen mit CUMSUM gepostet, die Suchfunktion sollte sie finden können.

Trotzdem lockt mich eine Schleifen-Lösung hier:
Code:
function A = forBlockMax(A)
iB = 0;
for iA = 1:numel(A)
  if A(iA) ~= 0
    if iB == 0
      iB = iA;
    end
  elseif iB ~= 0
    A(iB:iA-1) = max(A(iB:iA-1));
    iB = 0;
  end
end

if iB ~= 0
  A(iB:end) = max(A(iB:end));
end
 

Falls die Werte innerhalb der Blöcke sortiert sind, das größte Element also wie im Beispiel der Orginal-Frage hinten steht, vereinfacht sich das zu:
Code:
A(iB:iA-1) = A(iA-1);


Ein Vergleich mit der ebenfalls hübschen vektorisierten Methode von denny:
Code:
AA = floor(rand(1, 1e5)*4);
A = AA;
tic; A = vectorizedBlockMax(A); toc;
% 0.254484 seconds.

A = AA;
tic; A = forBlockMax(A); toc;
% 0.136412 seconds

Die Schleife hat hier den Vorteil, dass sie nur die kleinen Blöcke als temporären Speicher benötigt und das etwas bequeme ARRAYFUN vermeidet.

Anmerkung: Dennys Code hängt eine Null an den orginal-Vektor an, falls das letzte Element nicht Null ist. Das müsste man also noch explizit abfragen.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 25.01.2012, 00:58     Titel:
  Antworten mit Zitat      
Hallo,

Es geht aber auch noch schneller:
Code:
function A = forBlockMax2(A)
% Gleitendes Maximum, Reset bei 0, vorwärts:
B = 0;
for iA = 1:numel(A)
   if A(iA) > B
      B = A(iA);
   elseif A(iA) > 0
      A(iA) = B;
   else
      B = 0;
   end
end

% Und nochmal rückwärts:
B = 0;
for iA = numel(A):-1:1
   if A(iA) > B
      B = A(iA);
   elseif A(iA) > 0
      A(iA) = B;
   else
      B = 0;
   end
end

Das benötigt für die Testdaten der Größe 1e5 nur noch 0.013 sec, ist also 10 mal schneller als mein erster Versuch mit eine Schleife. Wieso?
Matlab's JIT-Accelerator profitiert davon, dass keine externe Funktion (max!) mehr aufgerufen wird. Zudem werden in jeder Iteration nur noch 4 DOUBLEs benötigt, nämlich iA, A(iA), B und 0. Diese passen aber in die Prozessor-Register, während "A(iB:iA-1) = max(A(iB:iA-1))" mehr Speicher benötigt. Das sind zwar nur einige Dutzend Bytes, aber der Cache des Prozessors wird dabei stärker belastet.

Zeitmessungen mit Core2Duo 2.3GHz, Win7, Matlab 2009a/64.

Der Code ist sehr elementar. C-ähnlich Konstrukte müssen in Matlab also nicht unbedingt langsam sein. Die Berücksichtigung der Funktionsweise des Prozessors hilft auf jeden Fall Laufzeit zu sparen: Ein größer/kleiner-Vergleich ist sehr billig, ebenso die Standard-Arithmetik +-*/. Der Zugriff auf den Speicher ist dagegen krötig langsam, vorallem wenn es den 2nd oder auch 3rd Level-Cache übersteigt.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
Seban
Forum-Meister

Forum-Meister


Beiträge: 600
Anmeldedatum: 18.01.12
Wohnort: ---
Version: ab R2014b
     Beitrag Verfasst am: 25.01.2012, 18:41     Titel:
  Antworten mit Zitat      
Jan S hat Folgendes geschrieben:
Ich habe in diesem Forum ein paar Lösungen mit CUMSUM gepostet, die Suchfunktion sollte sie finden können.

Ah ok. Danke! Werd ich mal nach stöbern.
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



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.