Biomod/2011/Caltech/DeoxyriboNucleicAwesome/Simulation: Difference between revisions
(Updating documentation to current revision of simulation.) |
(Updating code to current revision) |
||
Line 35: | Line 35: | ||
==MATLAB Code== | ==MATLAB Code== | ||
At the core of the simulation is a function which runs runs one random walk on an origami of specified size. It can run in both a cargo-bearing (one-cargo one-goal) and a purely random-walk mode. The former has cargo positions corresponding to our particular origami pre-programmed and starting with multiple (specified by user) walkers at random locations on the origami, and terminates when all of the cargos have been "sorted" to the goal location (the x axis). The latter runs one walker starting at a specified location, and terminates when that walker reaches the specified irreversible track location. The function returns a log of all walkers positions over time, a log reporting when cargos were picked up and dropped off, | At the core of the simulation is a function which runs runs one random walk on an origami of specified size. It can run in both a cargo-bearing (one-cargo one-goal) and a purely random-walk mode. The former has cargo positions corresponding to our particular origami pre-programmed and starting with multiple (specified by user) walkers at random locations on the origami, and terminates when all of the cargos have been "sorted" to the goal location (the x axis). The latter runs one walker starting at a specified location, and terminates when that walker reaches the specified irreversible track location. The function returns a log of all walkers positions over time, a log reporting when cargos were picked up and dropped off, a count of the number of steps the simulation took, and if desired, a move of the random walk. This function is utilized by separate cargo-bearing and random-walk data collection programs that call the function many times over a range of parameters. | ||
The function code (saved as randomWalkFunction.m): | The function code (saved as randomWalkFunction.m): | ||
Line 46: | Line 46: | ||
padding-left: 10px; | padding-left: 10px; | ||
background-color: #FEF7EA;"><code><syntaxhighlight lang="matlab"> | background-color: #FEF7EA;"><code><syntaxhighlight lang="matlab"> | ||
function [log, cargoLog, steps] = | function [log, cargoLog, steps, M] = randomWalkFunctionGeneric(... | ||
length, layoutMode, startPos, numWalkers, cargoBearing, error,... | |||
record, spaceWalkOnly, departThreshold, arriveThreshold) | |||
% | %Random walking / cargo sorting simulation for more general form | ||
% | %track layouts. More flexible in terms of layout but ultimately | ||
% | %probably a touch slower. | ||
% | %Gregory Izatt & Caltech BIOMOD 2011 | ||
% | %20110713: Init revision | ||
% | %20110714: Continuing init revision. | ||
% | %20110715: Continuing debugging of init revision. | ||
% | %20110718: Debugging issue where walkers n>=2 have occasional | ||
% unexplained jaints to 0,0 in the log | |||
%20110719: Adding full movie capture capability, mostly working on | |||
% rendering origami during movie production | |||
%20110816: Adding support for spacewalking and random | |||
% walker appearance / departure | |||
%20110817: Adding support for ability to do /just/ a spacewalk | |||
% for diagnostic / control purposes | |||
%Defines layouts: | |||
% | %Layouts: | ||
% | %1 = Standard | ||
%2 = Mini-playground | |||
% | %3 = 1D random walk / cargo sort | ||
% | %4 = Wide & long random walk | ||
% | |||
% | %In layout specification: | ||
% | %0 = nothing | ||
%1 = track 1 | |||
%10 = walker on track 1 | |||
%2 = track 2 | |||
%20 = walker on track 2 | |||
%3 = cargo | |||
%4 = cargo goal | |||
%40 = filled cargo goal | |||
%5 = walker goal | |||
%50 = filled walker goal | |||
%Specification arrays are in origami coodinates as | |||
%defined on the BIOMOD wiki's simulation page. | |||
%Walking will assume that system, so make sure | |||
%they're right! | |||
%Also, make sure you start with an odd row (a high one) | |||
% or the movement will be messed up. | |||
if layoutMode == 1 | |||
layout = ... | |||
[[1, 1, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 1, 1, 2, 2] | |||
[2, 2, 1, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 1, 1] | |||
[1, 1, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 0, 2] | |||
[2, 2, 3, 1, 2, 2, 1, 0, 3, 2, 1, 1, 2, 2, 3, 1] | |||
[1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2] | |||
[2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1] | |||
[1, 4, 2, 4, 1, 4, 2, 2, 1, 4, 2, 4, 1, 4, 2, 4] | |||
[2, 4, 1, 4, 2, 4, 1, 1, 2, 4, 1, 4, 2, 4, 1, 4]]; | |||
elseif layoutMode == 2 | |||
layout = ... | |||
[[0, 1, 0, 2, 1, 1, 0, 2] | |||
[0, 2, 3, 1, 2, 2, 3, 1] | |||
[0, 1, 2, 2, 1, 1, 2, 2] | |||
[0, 2, 1, 0, 3, 2, 1, 1] | |||
[0, 1, 2, 2, 1, 1, 2, 2] | |||
[0, 2, 1, 1, 2, 2, 1, 1] | |||
[0, 4, 2, 2, 1, 4, 2, 4] | |||
[0, 4, 1, 1, 2, 4, 1, 4]]; | |||
elseif layoutMode == 3 | |||
layout = ... | |||
[[0, 2, 0] | |||
[0, 1, 0] | |||
[3, 2, 0] | |||
[0, 1, 3] | |||
[0, 2, 0] | |||
[0, 1, 0] | |||
[3, 2, 0] | |||
[0, 1, 0] | |||
[0, 2, 0] | |||
[1, 4, 0] | |||
[2, 4, 0]]; | |||
elseif layoutMode == 4 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0] | |||
[0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 410 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 416 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 422 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 457 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 434 | |||
layout = ... | |||
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 5] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 1] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] | |||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; | |||
elseif layoutMode == 5 | |||
layout = ... | |||
[[1, 1, 2, 2, 1, 1, 0, 2, 1, 1, 0, 2, 1, 1, 5, 2] | |||
[2, 2, 1, 1, 2, 2, 0, 1, 2, 2, 0, 1, 2, 2, 1, 1] | |||
[1, 1, 0, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 0, 2] | |||
[2, 2, 0, 1, 2, 2, 1, 0, 0, 2, 1, 1, 2, 2, 0, 1] | |||
[1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2] | |||
[2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1] | |||
[1, 0, 2, 0, 1, 0, 2, 2, 1, 0, 2, 0, 1, 0, 2, 0] | |||
[2, 0, 1, 0, 2, 0, 1, 1, 2, 0, 1, 0, 2, 0, 1, 0]]; | |||
end | |||
%Get the orientation right: | |||
layoutSize = size(layout); | |||
layout = flipud(layout); | |||
startPos(1) = layoutSize(1) - startPos(1) + 1; | |||
layout = transpose(layout); | |||
startPos = [startPos(2), startPos(1)]; | |||
layoutSize = [layoutSize(2), layoutSize(1)]; | |||
%Initialize some logging variables we'll need: | |||
steps = 0; | |||
log = zeros(length, 2*numWalkers + 1); | log = zeros(length, 2*numWalkers + 1); | ||
cargoLog = []; | cargoLog = []; | ||
%Walkers: | %Movement rules: | ||
evenPoss = [0, 1 ; 0, -1; 1, 0; -1, 0; 1, -1; -1, -1]; %For even columns | |||
oddPoss = [0, 1 ; 0, -1; 1, 0; -1, 0; 1, 1; -1, 1]; %For odd columns | |||
%Walkers positioning: | |||
% Set position randomly if we're doing cargo bearing simulation, | % Set position randomly if we're doing cargo bearing simulation, | ||
% or set to supplied startPos if not. | % or set to supplied startPos if not. | ||
Line 100: | Line 227: | ||
done = 0; | done = 0; | ||
while done ~= 1 | while done ~= 1 | ||
currentPos(i, :) = [randi( | currentPos(i, :) = [randi(layoutSize(1), 1), ... | ||
done = | randi(layoutSize(2), 1)]; | ||
done = (layout(currentPos(i, 1), currentPos(i, 2)) == 1 || ... | |||
layout(currentPos(i, 1), currentPos(i, 2)) == 2); | |||
end | end | ||
layout(currentPos(i, 1), currentPos(i, 2)) = ... | |||
layout(currentPos(i, 1), currentPos(i, 2)) * 10; | |||
end | end | ||
else | else | ||
numWalkers = 1; %Want to make sure this is one for this case | numWalkers = 1; %Want to make sure this is one for this case | ||
currentPos = startPos; | currentPos = startPos; | ||
if | if currentPos(1) < 1 || currentPos(1) > layoutSize(1) || ... | ||
currentPos(2) < 1 || currentPos(2) > layoutSize(2) || ... | |||
(layout(currentPos(1), currentPos(2)) ~= 1 && ... | |||
layout(currentPos(1), currentPos(2)) ~= 2) | |||
'Invalid start position.'; | 'Invalid start position.'; | ||
layout | |||
currentPos | |||
cargoLog = []; | cargoLog = []; | ||
steps = -1; | steps = -1; | ||
M = []; | |||
return | return | ||
end | end | ||
layout(currentPos(1), currentPos(2)) = ... | |||
layout(currentPos(1), currentPos(2)) * 10; | |||
end | end | ||
%Something to keep track of which walkers is carrying cargos: | |||
hasCargo = zeros(numWalkers); | |||
%Error: If there's a valid error rate, go omit some positions: | %Error: If there's a valid error rate, go omit some positions: | ||
if error > 0 | if error > 0 | ||
for | for y=1:layoutSize(2) | ||
for | for x=1:layoutSize(1) | ||
%Only omit if it's not already blocked by something | %Only omit if it's not already blocked by something | ||
if rand <= error | |||
layout(x, y) = 0; | |||
end | end | ||
end | end | ||
Line 132: | Line 270: | ||
%Convenience: | %Convenience: | ||
if cargoBearing == 1 | |||
numCargoPos = 0; | |||
for y=1:layoutSize(2) | |||
for x=1:layoutSize(1) | |||
if layout(x, y) == 3 | |||
numCargoPos = numCargoPos + 1; | |||
end | |||
end | |||
end | |||
end | |||
if record == 0 | |||
M = []; | |||
else | |||
aviobj = avifile('RR2.avi'); | |||
end | |||
%Indicator for premature completion | |||
done = 0; | |||
%Main loop: | %Main loop: | ||
for i=1:length | for i=1:length | ||
for walker=1:numWalkers | for walker=1:numWalkers | ||
%Add current pos to log: | |||
%Add current pos to log | |||
log(steps + 1, 2*walker-1:2*walker) = currentPos(walker, :); | log(steps + 1, 2*walker-1:2*walker) = currentPos(walker, :); | ||
%Update pos to randomly | %Update pos to randomly chosen neighbor, based on motion rules | ||
temp = randi(6, 1); | |||
if ~spaceWalkOnly | |||
if (mod(currentPos(walker, 1), 2) == 0) | |||
newPos = currentPos(walker, :) + evenPoss(temp, :); | |||
else | |||
newPos = currentPos(walker, :) + oddPoss(temp, :); | |||
end | |||
temp = randi( | |||
if (mod(currentPos(walker, 1),2) == 0) | |||
newPos = currentPos(walker, :) + | |||
else | else | ||
newPos = currentPos(walker | newPos = currentPos(walker, :); | ||
end | end | ||
%If this is out of defined boundaries, don't do anything: | |||
if ~(newPos(1) > layoutSize(1) || newPos(1) < 1 || ... | |||
newPos(2) > layoutSize(2) || newPos(2) < 1) | |||
%Now react based on what kind of spot the new position is: | |||
oldPosIdent = layout(currentPos(walker, 1), ... | |||
currentPos(walker, 2)) / 10; | |||
newPosIdent = layout(newPos(1), newPos(2)); | |||
%Can't move from one track to the same kind of track: | |||
if newPosIdent == oldPosIdent | |||
%'Cant step to same kind of track' | |||
%Hitting cargos: pick up cargo if possible. | |||
elseif newPosIdent == 3 && cargoBearing | |||
if hasCargo(walker) == 0 | |||
hasCargo(walker) = 1; | |||
layout(newPos(1), newPos(2)) = 0; | |||
cargoLog = [cargoLog; walker, newPos, steps]; | |||
end | end | ||
if | %'Hit cargo planter' | ||
%Hitting goals: drop a cargo if possible. | |||
elseif newPosIdent == 4 && cargoBearing | |||
if hasCargo(walker) == 1 | |||
hasCargo(walker) = 0; | hasCargo(walker) = 0; | ||
cargoLog = [cargoLog; steps | layout(newPos(1), newPos(2)) = 40; | ||
cargoLog = [cargoLog; walker, newPos, steps]; | |||
done = done + 1/numCargoPos; | |||
end | end | ||
%'Hit goal' | |||
%Hitting walker goal: go there and trigger completion. | |||
elseif newPosIdent == 5 | |||
%'Hit walker goal' | |||
currentPos(walker, :) = newPos; | |||
layout(newPos(1), newPos(2)) = 50; | |||
done = 1; | |||
%Valid move, and we haven't been shot down yet? | |||
% Then actually move, and update layout to reflect that. | |||
elseif newPosIdent == 1 || newPosIdent == 2 | |||
%'Moving' | |||
layout(currentPos(walker, 1), currentPos(walker, 2)) = ... | |||
layout(currentPos(walker, 1), currentPos(walker, 2)) / 10; | |||
currentPos(walker, :) = newPos; | |||
layout(currentPos(walker, 1), currentPos(walker, 2)) = ... | |||
layout(currentPos(walker, 1), currentPos(walker, 2)) * 10; | |||
end | |||
end | |||
end | |||
%Finish up bookkeeping log and step count for this step | |||
log(steps + 1, 2*numWalkers + 1) = steps; | |||
steps = steps + 1; | |||
if record | |||
hold on; | |||
xlim([0, layoutSize(1) + 1]); | |||
ylim([0, layoutSize(2) + 1]); | |||
%Plot walkers: | |||
for walker=1:numWalkers | |||
tempPos = currentPos(walker, :); | |||
if mod(tempPos(1), 2) == 0 | |||
tempPos(2) = tempPos(2) - 0.5; | |||
end | end | ||
if hasCargo(walker) | |||
plot(tempPos(1), tempPos(2), ... | |||
'o', 'color', [0, 0.5, 0], 'MarkerSize', 15); | |||
end | end | ||
plot(tempPos(1), tempPos(2), 'o', ... | |||
'color', [0, 0, 0], 'MarkerSize', 25); | |||
end | end | ||
% | %Plot origami: | ||
for x=1:layoutSize(1) | |||
for | for y=1:layoutSize(2) | ||
if | %Plot with coloration specific to probe identity | ||
if layout(x, y) == 0 || ... | |||
layout(x, y) == 10 || ... | |||
layout(x, y) == 20 | |||
color = [1 1 1]; | |||
elseif layout(x, y) == 1 | |||
color = [1 0 0]; | |||
elseif layout(x, y) == 2 | |||
color = [0 0 1]; | |||
elseif layout(x, y) == 3 | |||
color = [0 .5 0]; | |||
elseif layout(x, y) == 4 | |||
color = [0 1 1]; | |||
elseif layout(x, y) == 5 | |||
color = [1 1 0]; | |||
elseif layout(x, y) == 40 | |||
color = [0 .5 0]; | |||
elseif layout(x, y) == 50 | |||
color = [.5 .5 .5]; | |||
end | |||
tempY = y; | |||
if mod(x, 2) == 0 | |||
tempY = tempY - 0.5; | |||
end | end | ||
plot(x, tempY, 's', 'Color', color, 'MarkerSize', 10); | |||
end | end | ||
end | end | ||
M(i) = getframe; | |||
% | aviobj = addframe(aviobj, M(i)); | ||
%If we | hold off; | ||
clf; | |||
end | |||
if | %If finished, done with everything | ||
if done >= 1 | |||
if record | |||
aviobj = close(aviobj); | |||
end | |||
log((steps + 1):length, :) = []; | |||
return | |||
end | |||
%If we're thinking about astronaut / orphaned walkers, do it here: | |||
%(astronaut walking isn't yet considered for cargobearing walks, | |||
%(but should be implemented in the future if it becomes an issue) | |||
if rand() > departThreshold && cargoBearing == 0 | |||
numWalkers = numWalkers + 1; | |||
log = [log(:, 1:end-1) zeros(length, 2) log(:, end)]; | |||
currentPos = [currentPos; [1, 1]]; | |||
landingDone = 0; | |||
while landingDone ~= 1 | |||
currentPos(end, :) = [randi(layoutSize(1), 1), ... | |||
randi(layoutSize(2), 1)]; | |||
if layout(currentPos(end, 1), currentPos(end, 2)) == 4 | |||
done = 1; | |||
end | end | ||
landingDone = (layout(currentPos(end, 1), ... | |||
currentPos(end, 2)) == 1 || ... | |||
layout(currentPos(end, 1), ... | |||
currentPos(end, 2)) == 2); | |||
end | end | ||
end | end | ||
if rand() > arriveThreshold && numWalkers > 0 && cargoBearing == 0 | |||
walkerToRemove = randi(numWalkers); | |||
numWalkers = numWalkers - 1; | |||
log(:, walkerToRemove*2-1:walkerToRemove*2) = []; | |||
currentPos(walkerToRemove, :) = []; | |||
end | end | ||
end | end | ||
if record | |||
aviobj = close(aviobj); | |||
end | |||
return | return | ||
</syntaxhighlight></code></div> | </syntaxhighlight></code></div> | ||
===Examining Errors in Origami=== | ===Examining Errors in Origami=== | ||
This code can be used to generate diagrams like those below, visualizing the mobility of the walker. One immediate question | This code can be used to generate diagrams like those below, visualizing the mobility of the walker. One immediate question is the vulnerability of this layout to errors in the laying of track. We investigate this by, when generating the track layout in the beginning of randomWalkFunction, introducing a small (specified by input) percent chance that any single probe will be omitted. Error rates at around 10% are bearable; error rates greater than that, however, are catastrophic, causing walkers to become permanently trapped in small sections of the track field. | ||
[[Image:FullGridErrors.png | center | 800 px | thumb | Node graphs showing walker mobility of origami. Each junction represents a track, and each edge represents a step a walker can take. The left diagram shows no error, whereas the other two show increasing error rates. We observe that 10% error rates decrease walker mobility, but tend not to trap the walker in any particular location; 20% error rates or greater, over several tests, tend to cause catastrophic loss of mobility, making the sorting task impossible.]] | [[Image:FullGridErrors.png | center | 800 px | thumb | Node graphs showing walker mobility of origami. Each junction represents a track, and each edge represents a step a walker can take. The left diagram shows no error, whereas the other two show increasing error rates. We observe that 10% error rates decrease walker mobility, but tend not to trap the walker in any particular location; 20% error rates or greater, over several tests, tend to cause catastrophic loss of mobility, making the sorting task impossible.]] | ||
Revision as of 15:31, 31 October 2011
Tuesday, March 19, 2024
|
SimulationsOverviewOur proposed sorting mechanism depends very heavily on a particular random-walking mechanism that has not been demonstrated in literature before. The verification of this mechanism is thus a vital step in our research. Verification of the random walk in one dimension is fairly straightforward: as discussed in SPEX experiments, a one-dimensional track is easy to construct, and will behave like a standard 1D random walk, showing an average translation on the order of [math]\displaystyle{ n^{\frac{1}{2}} }[/math] after n steps. Thus, we should expect the time it takes to get to some specific level of fluorescence to be proportional to the square of the number of steps we start the walker from the irreversible substrate. If we can, in an experiment, record the fluorescence over time when the walker is planted at different starting points and show that that fluorescence varies by this relationship, we'll have fairly certainly verified one-dimensional random walking. Our particular case of 2D random walking, however, is not as easily understood, especially considering the mobility restrictions (ability to move to only 4 of 6 surrounding locations at any particular time) of our particular walker. As a control for the verification of 2D random walking, though, we still need to get an idea how long the random walk should take, and how that time will change as we start the walker at different points on the origami. We opt to do this by simulating the system with a set of movement rules derived from our design. We also use the same basic simulation (with a few alterations and extra features) to simulate our entire sorting system in a one-cargo, one-goal scenario, to give us some rudimentary numbers on how long sorting should take, with one vs multiple walkers. Basic parameters and assumptions:
MATLAB CodeAt the core of the simulation is a function which runs runs one random walk on an origami of specified size. It can run in both a cargo-bearing (one-cargo one-goal) and a purely random-walk mode. The former has cargo positions corresponding to our particular origami pre-programmed and starting with multiple (specified by user) walkers at random locations on the origami, and terminates when all of the cargos have been "sorted" to the goal location (the x axis). The latter runs one walker starting at a specified location, and terminates when that walker reaches the specified irreversible track location. The function returns a log of all walkers positions over time, a log reporting when cargos were picked up and dropped off, a count of the number of steps the simulation took, and if desired, a move of the random walk. This function is utilized by separate cargo-bearing and random-walk data collection programs that call the function many times over a range of parameters. The function code (saved as randomWalkFunction.m): Toggle Code Examining Errors in OrigamiThis code can be used to generate diagrams like those below, visualizing the mobility of the walker. One immediate question is the vulnerability of this layout to errors in the laying of track. We investigate this by, when generating the track layout in the beginning of randomWalkFunction, introducing a small (specified by input) percent chance that any single probe will be omitted. Error rates at around 10% are bearable; error rates greater than that, however, are catastrophic, causing walkers to become permanently trapped in small sections of the track field. Random-Walk SimulationThe data we need from this simulator is a rough projection of the fluorescence response from our test of 2D random walking, which should change based on the starting location of the walker. Because this fluorescence is changed by a fluorophore-quencher interaction upon a walker reaching its irreversible track, in the case where we plant all of the walkers on the same starting track, the time it takes [math]\displaystyle{ (fluorescence_{initial} - fluorescence_{current}) }[/math] in the sample to reach some standard value should be proportional to the average time it takes the walkers to reach the irreversible substrate. As this 'total steps elapsed' value is one of the outputs of our simulation function, we can generate a map of these average walk durations by running a large number of simulations at each point on the origami and averaging the results: Toggle Code ResultsResults of the bulk data collection at right show that the average random-walk duration, and thus the time for [math]\displaystyle{ (fluorescence_{initial} - fluorescence_{current}) }[/math] to reach some standard level, increases with distance, though it changes less significantly the farther out one gets. Also important to note is that the "effective distance" (in terms of steps) along the short axis of our platform is a significantly less than the same physical distance along the long axis. This difference is due to our arrangement of track A and B: as can be seen in the left half of the diagram at the end of the #Overview section, alternating tracks A and B create a straight vertical highway for the walker to follow. Horizontal movement, in contrast, cannot be accomplished by purely straight-line movement -- it requires a back-and-forth weave that makes motion in that direction slower. The disparity in "effective distances" between the vertical and horizontal dimensions is something, in particular, that we should test for; however, a simple series of tests running random walks at a variety of points across the surface, and the comparison of the resulting fluorescence data to the control provided by this simulation should be sufficient to prove that our walker can, indeed, perform a 2D random walk. Cargo Sorting SimulationThis simulation investigates both the overall tractability of our sorting problem, and the degree to which it can be parallelized via the addition of multiple walkers onto a single origami. It runs by making repeated calls to randomWalkFunction in its cargo-bearing mode, testing the number of steps it takes to sort all five cargos to respective goals over a range of number of cooperating walkers: Toggle Code ResultsWhile a single walker takes over a thousand steps to complete the sorting challenge, the addition of even a single walker vastly decreases the completion time, and additional walkers decrease it further, until a critical point is reached where the walkers are more getting in the way than helping with the sorting process. This is visible in the positive slope visible in the diagram at right that starts at around the 20 walker point.
|