Verfasst am: 12.05.2014, 10:40
Titel: Vektor randomisieren ohne Zahlenwiederholung
Hallo,
ich programmiere derzeit ein Experiment für meine Masterarbeit.
Ich möchte dabei u.a. eine Sequenz erstellen, mit der ich die Position eines Items bestimme. Ich brauche dafür einen Vektor mit insgesamt 528 Stellen (Anzahl der Trials). Es gibt 16 mögliche Positionen. Jede Position soll gleich häufig vorkommen (also insgesamt jede 33 mal).
Die Schwierigkeit besteht für mich darin, dass eine Position nicht unmittelbar 2 mal hintereinander auftauchen soll.
Wenn ich mein Problem als Analogie ausdrücken müsste, hätte ich also 16 Urnen mit jeweils 33 Kugeln darin. Ich möchte aus allen Urnen zufällig so lange ziehen bis alle Urnen leer sind, nur nicht zwei mal hintereinander aus derselben.
Ich stöße hier leider an meine Grenzen. Ich hoffe, dass jemand eine Idee hat um mein Problem zu lösen.
Vielen Dank!
selber verzweifelter Gast
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 12.05.2014, 11:07
Titel: Lösung
Hallo, ich konnte mein Problem grad selbst lösen.
Beim Herumstöbern bin ich auf den Befehl reshape gestoßen und dann kam eins zum anderen. Ich will nur kurz meine Lösung präsentieren:
deine eigene Lösung erfüllt leider nicht deine Anforderungen. Das sind nicht wirklich Zufallspositionen, da da in 16er-Blöcken immer alle Positionen 1-16 angenommen werden. Das heißt beispielsweise, dass ich Position 16 schon exakt weiß, wenn ich die ersten 15 Positionen ausgesucht habe. Sowas wie 1,2,1,2,1,2,3,1,4,5,3,2,6,2,1 kann bei dir nicht vorkommen...
Eine richtig gute Lösung weiß ich auch nicht, ich habe mich aber von deinem Urnenmodell inspirieren lassen, das sollte funktionieren, ist aber sicher nicht die schnellste/eleganteste Lösung:
Code:
% Die Urnen
Urns = cell(1, 16);
for u = 1:16
Urns{u} = ones(1, 33)*u;
end
pos = NaN(1, 528);
u = randsample(1:16,1,true,cellfun(@length, Urns));
pos(1) = u;
Urns{u} = Urns{u}(1:end-1);
for t = 2:528
valid_draw = false;
while ~valid_draw
weights = cellfun(@length, Urns);
% kann vermutlich auch mal nicht terminieren, wenn am Ende nur noch % eine einzige Urne Kugeln hat. ifsum(weights~=0) == 1% nur noch eine Urne hat Kugeln if t<528% nur beim letzten Durchgang erlaubt error('kann nicht mehr terminieren') end end
% zufaellig Urne waehlen
u = randsample(1:16, 1, true, weights);
if pos(t-1) ~= u
pos(t) = u;
Urns{u} = Urns{u}(1:end-1);
valid_draw = true;
end end end
Edit:
Das oben passt eigentlich auch nicht, da du die Urnen ja nicht gewichtet nach dem Anzahl ihrer Kugeln, die sie noch beinhalten, ziehen willst. Andernfalls (also mit randi() statt randperm()) wird es aber sogar sehr oft nicht terminieren... Da muss ein anderer Weg her.
Zuletzt bearbeitet von Nras am 12.05.2014, 11:30, insgesamt einmal bearbeitet
selber verzweifelter Gast
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 12.05.2014, 11:30
Titel:
Argh, du hast da vollkommen recht! Das habe ich übersehen. Es ist immer gut, wenn einen jemand darauf aufmerksam macht bevor es zu spät ist. Danke!
Ich werde deine Version mal testen. Vielen Dank dafür.
N = 100; % paar Testläufe
nachbarn_ungleich = NaN(1,N);
jede_pos_33_mal = NaN(1,N);
for n = 1:N
pos = repmat(1:16,1,33); % alle zu verteilenden positionen
pos = pos(randperm(528)); % startversuch
condition = any(diff(pos)==0); % das muss erfüllt sein
while condition == false % indizes der positionen, die neu gezogen werden sollen
old_idx = find(diff(pos)==0);
% mit new_idx soll getauscht werden
new_idx = randperm(528);
new_idx = new_idx(1:length(old_idx));
% pruefen, ob bedingung nun erfuellt ist
condition = any(diff(pos)==0);
end
nachbarn_ungleich(n) = any(diff(pos)==0); % keine nebeneinander
jede_pos_33_mal(n) = all(histc(pos,unique(pos)) == ones(1, 16)*33);
end disp(sum(nachbarn_ungleich)/N*100) disp(sum(jede_pos_33_mal)/N*100)
Die äußere For-Schleife war nur testweise, um sicher zu gehen, dass kein Unsinn passiert.
Viele Grüße,
Nras
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.