[Matlab] combinaties met unieke verhouding in nieuwe matrix

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Kid Jansen
  • Registratie: Oktober 2005
  • Niet online
Ik heb een matrix P met alle mogelijke 4-bit RGB combinaties. Wat ik wil is dat wanneer een combinatie een unieke verhouding heeft (greatest common divider = 1) die combinatie wordt toegevoegd als nieuwe rij aan de onderkant van matrix Q.

Om dat te bereiken heb ik de onderstaande code geschreven, maar het stuk vanaf regel 9 werkt niet: ik krijg geen matrix Q. Wat doe ik fout?
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
N = 4;
R = 0:1:2^N-1;
R = transpose(R);
G = R;
B = R;
P = allcomb(R,G,B);
[m,n] = size(P);
i = 1;
    while i <= m
        i = i+1;
        if gcd(P(i,1),gcd(P(i,2),P(i,3))) == 1
            Q(end,:) = P(i,:);
    end

De functie allcomb heb ik overigens van het Mathworks File Exchange gedownload.

offtopic:
Dit topic is overigens een vervolgvraag op Netto kleurdiepte berekenen

[ Voor 3% gewijzigd door Kid Jansen op 06-02-2014 14:29 ]


Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Er is zoveel mis met je code dat ik me ernstig afvraag of je zelf al hebt gedebugd. Maargoed:

- de end van je if mist
- je gebruikt Q(end, : ) ipv Q(end+1, : )
- Q bestaat niet
- je loop gaat out of bounds en slaat het eerste element over

En dit had je allemaal prima zelf op basis van de errors kunnen oplossen:

error: invalid dimension inquiry of a non-existent value
error: invalid empty index list

en dit is wat octave zegt -- matlab zelf is waarschijnlijk duidelijker

Verder: waarom gebruik je een matrix als je vervolgens het probleem niet vectorized oplost? Gebruik dan gewoon drie loopjes in elkaar...

spoiler:
je kunt namelijk ook de bool arreay gcd(P(:,1), P(:,2), P(:,3)) == 1 gebruiken

[ Voor 9% gewijzigd door ValHallASW op 06-02-2014 14:59 ]


Acties:
  • 0 Henk 'm!

  • Kid Jansen
  • Registratie: Oktober 2005
  • Niet online
Matlab gaf zelf helemaal geen melding bij mij met die code, maar heb aan de hand van de punten die je geeft de code aangepast naar het volgende:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
N = 4;
R = 0:1:2^N-1;
R = transpose(R);
G = R;
B = R;
P = allcomb(R,G,B);
Q = [];
[m,n] = size(P);
i = 1;
    while i <= m
        if gcd(P(i,1),gcd(P(i,2),P(i,3))) == 1
            Q(end+1,:) = P(i,:);
    end
        i = i+1;
    end

Dat werkt wel. Is dat vectorized oplossen nog sneller? Als dat niet het geval is laat ik het namelijk maar zo, want m'n Matlab kennis is behoorlijk mager.

Acties:
  • 0 Henk 'm!

  • ValHallASW
  • Registratie: Februari 2003
  • Niet online
Kid Jansen schreef op donderdag 06 februari 2014 @ 16:56:
Matlab gaf zelf helemaal geen melding bij mij met die code,
Raar. Nouja, als de open-source kloon beter is dan kan je die maar beter gebruiken ;-) https://www.gnu.org/software/octave/
Dat werkt wel. Is dat vectorized oplossen nog sneller?
Ja, met name voor grotere oplossingen. De vectorized versie schaalt ongeveer als (2^N)^2.5, terwijl de loop schaalt als (2^N)^3.5. Voor N=6 is het niet zo'n issue (240s vs 0.9s), maar voor grotere result sets wordt het verschil alleen maar groter.

Afbeeldingslocatie: http://i.imgur.com/w47Jwqt.png

Acties:
  • 0 Henk 'm!

  • Kid Jansen
  • Registratie: Oktober 2005
  • Niet online
Op zich is dat niet zo'n probleem, want hoger dan 6 bit heb ik toch niet zo veel aan. Ik heb inmiddels de volledige code af (zit nog een stuk achter) die de data scatter plot. Met 6 bit moet Matlab al 217.021 cirkeltjes tekenen, met 7 bit zijn dit er 1.742.299 (zie ook Soultaker in "Netto kleurdiepte berekenen")