程序陷入无限循环,尽管有一个条件可以终止它:MATLAB
Program stucks in infinite loop although there is a condition to terminate it: MATLAB
我正在构建一个用许多小立方体填充空心立方体的程序。然后,通过随机立方体创建一条连接路径。通过查看每个立方体的直接邻居和 select 中的任何一个作为下一步,逐步找到路径。为了说明,下图显示了由立方体(红色立方体)组成的路径,
为了构建路径,我从一些立方体开始,用红色着色,找到它的相邻立方体(6 个相邻立方体,因为我们有 6 个面),select随机编辑它们中的任何一个,给 select 用红色编辑一个,然后通过重复相同的过程找到它的邻居。这个方法很好,但是如果一个相邻的立方体已经是红色的(已经属于路径)它不会识别它并且它可以再次select它。为了解决这个问题,我做了以下操作,
1- 我创建了一个名为 visited 的数组,并在其中存储了任何已访问的多维数据集的索引。
2- 我将当前立方体的邻居存储在另一个名为 a 的数组中,并将其与访问的数组进行比较,然后我删除所有公共元素,然后从 a.
中剩余的元素中取一个随机数
3-有时所有的邻居都可以访问,所以a会变成空的。在这种情况下,我查找了当前立方体中的任何一个,select随机编辑了其中的任何一个,检查了它的邻居,将它们存储在邻居数组中(a) 并将其与访问的立方体数组进行比较。如果 neighbors 数组不为空,这将不断重复(while 循环)。但就我而言,程序陷入了 while 循环。还有,有时不会卡住,但路径中的立方体数量变得少于指定的数量。
我在上一个问题中获得了构建主立方体的代码,用小立方体填充它,并通过 Hoki 获得邻居 () 我刚刚添加了使用邻居构建路径的机制。这是代码,
%%
clf; figure(1); format compact
h(1) = axes('Position',[0.2 0.2 0.6 0.6]);
%These are the different 8 vertices of the cube, each is defined by its 3 x y z coordinates:
vert = [ 1 1 -1; -1 1 -1; -1 1 1; 1 1 1; -1 -1 1; 1 -1 1; 1 -1 -1; -1 -1 -1];
%These are the 6 faces of the cube, each is defined by connecting 4 of the available vertices:
fac = [1 2 3 4; 4 3 5 6; 6 7 8 5; 1 2 8 7; 6 7 1 4; 2 3 5 8];
%// How many small cube do we want
MainCubeSide = 2 ; %// dimension of the side of the main cube
nCubeOnSide = 5 ; %// number of small cube in one "row/column" of the main cube
nCubesTotal = nCubeOnSide^3 ; %// total number of small cube
% define the Main container cube
MainCube.Vertices = vert *(2/MainCubeSide) ; %// because the cube as defined above has already a side=2
disp (2/ MainCubeSide);
MainCube.Faces = fac ;
MainCube.FaceColor = 'w' ;
hMainCube = patch(MainCube); %// patch function for the first big cube. MainCube can be seen as an object that contains all the infor that the patch function needs.
axis([-1, 1, -1, 1, -1, 1]);
axis equal;
hold on; %wait we didn't finish yet.
material metal;
alpha('color');
alphamap('rampdown');
view(138,24)
%view(3);
%% // generate all the coordinates of each cube first
dstep = MainCubeSide / nCubeOnSide ; %// step size for small cube vertices, this will determine the edge length for the small cube that best fits the required small cubes per edge.
vElem = bsxfun(@plus, vert / nCubeOnSide , -( MainCubeSide/2 - dstep/2)*[1 1 1] ) ; %// elementary cube vertices. Because the small cube was defined in the center of the big cube, to push it to one side we only need to move it by half the size of the main cube (minus half the size of a small cube)
%%
hold on;
coords = zeros( size(vElem,1),size(vElem,2), nCubesTotal ) ; %// To store the coordinates (8 rows * 3 columns) in every of the nCubesTotal slices.
colors = zeros( nCubesTotal , 3 ) ; %// To store the RBG colours for every small cube.
hcube = zeros( nCubesTotal , 1 ) ; %// To store the handles of the patch objects
iNeighbour = zeros( nCubesTotal , 6 ) ; %// To save the index of the neighbours
idc = permute( reshape(1:nCubesTotal,nCubeOnSide,nCubeOnSide,nCubeOnSide) , [3 2 1] ) ;
%// For each cube ...
iCube = 0 ;
for iline=1:nCubeOnSide %// Lines
for icol=1:nCubeOnSide %// Columns
for ih=1:nCubeOnSide %// Slice (height)* all for loops have the smame length, because the total number of cubes = mCubeOnSide^3
iCube = iCube + 1 ;
%// Take the base corner coordinates and add an offset to each coordinate
coords(:,:,iCube) = bsxfun(@plus, vElem , dstep*[(iline-1) (icol-1) (ih-1)]); %the fist one will not have offset, iline-1=0.
%// Save the colour
colors(iCube,:) = rand(1,3) ;
%// Draw the cube and store its info in the cube handler hcube.
hcube(iCube) = patch('Faces', fac, 'Vertices', coords(:,:,iCube), 'FaceColor', colors(iCube,:) ) ; %Remember each slice of coords contains the vertices of one of the small cubes, that's why it corresponds to vertices here.
drawnow %// just for intermediate display, you can comment these 2 lines
pause(0.05) %// just for intermediate display, you can comment these 2 lines
%// save adjacent cubes indices
ixAdj = [iline-1 iline+1 icol-1 icol+1 ih-1 ih+1] ; %// indices of adjacent cubes
idxFalse = (ixAdj<1) | (ixAdj>nCubeOnSide) ; %// detect cube which would be "out" of the main cube
ixAdj(idxFalse) = 1 ; %// just to not get an "indexing" error at this stage
iNeighbour(iCube,:) = [idc(ixAdj(1),icol,ih) idc(ixAdj(2),icol,ih) ...
idc(iline,ixAdj(3),ih) idc(iline,ixAdj(4),ih) ...
idc(iline,icol,ixAdj(5)) idc(iline,icol,ixAdj(6)) ] ;
iNeighbour(iCube,idxFalse) = NaN ;
end
end
end
getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
set(hcube,'Visible','off') %// turn off all small cubes
cubeOfInterest = 32 ; %// select one cube
%// display the main cube of interest, and it's neighbours in transparency
set(hcube(cubeOfInterest),'Visible','on','FaceColor','r','FaceAlpha',1)
%set(hcube(getNeighbourIndex(CubeOfInterest)),'Visible','on','FaceColor','g','FaceAlpha',.05)
visited= []; %to hold the indices of the visited cubes.
for i=1:124
visited (i) = cubeOfInterest; %the first visited cube is the cube of interest.
a= (getNeighbourIndex(cubeOfInterest)); %get all the neighbors\ indices and store them in an array so we can select randomly from them.
disp (a);
looping=true;
while looping==true %To avoid visiting any previously visited cube.
disp ('program is looping') %just to know if the program is stuck in an infinite loop.
inds = find(ismember(a, visited)); %store the indices of the common elements if found.
a(inds)= []; %delete the indices of the common elements.
if (isempty (a)==1)
temp = randsample((getNeighbourIndex(cubeOfInterest)), 1);
a= getNeighbourIndex(temp);
disp (a)
else
looping=false ;
end
end
x = randsample(a, 1);
set(hcube(x),'Visible','on','FaceColor','r','FaceAlpha',1)
cubeOfInterest= x;
end
在上面的代码中构建路径从我初始化访问的多维数据集数组 (visited = []) 的行开始。
谁能告诉我为什么程序会卡在 while 循环中?
编辑:我在 Hoki 的代码 中添加了一些代码,即使访问了邻居也能使路径继续。它将 select 任何未访问的多维数据集并移动到它,如果它不会使路径断开连接。该代码现在按要求运行良好。这里是修改的部分,
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 125 ; %// maximum length of path
maxPathLength= maxPathLength+1;
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)this to be checked in case 2 as well.
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
availableAll =[1:125];
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
%//path_terminated = true ;
%//here I want to make the modification.
looping=true; %//To keep looping until we find the correct next move.
counter=0; %//to iterate through the cubes which are not visisted.
while looping==true
counter= counter+1;
jump= availableAll (counter); %//select the first available cube and check if it is suitable or not
if (~isempty (intersect(getNeighbourIndex(jump), path_visited))) %// if the selcted cube has a visited neighbor, it means it is suitable. The path will stay connected.
%good we found it.
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = jump ; %//add the selected cube to the path.
availableAll (availableAll==jump)= []; %//remove the selected cube from the list of available cubes.
looping= false; %//stop looping.
end
%continue
end
else
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
availableAll (availableAll==path_visited(ptIndex))= []; %//remove the selected cube from the list of available cubes.
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
%// choose one neighbour randomly among the available ones
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
上面的代码运行良好。 Hoki提供了很大的帮助,非常感谢Hoki.
谢谢。
这是一种实现随机路径的方法。我已经明确了退出条件。您可以根据需要添加更多退出条件或重新组合它们,但机制大致相同。重要步骤摘录:
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
然后您可以按照自己的方式添加退出条件检查和立方体着色。
推进路径的基本逻辑:
- 获取邻居列表。
available_next = getNeighbourIndex( path_visited(ptIndex) ) ;
- 检查其中一些是否已经被访问过。
[~,~,ib]=intersect(path_visited,available_next);
- 从 "Available" 列表中删除已经访问过的。
available_next(ib) = [] ;
- (随机)选择剩余可用的一个。
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
退出条件逻辑:
- 已达到路径元素的最大数量(如果您决定设置路径的最大长度)。
if ptIndex >= maxPathLength
- 不再有 "Available" 个邻居(即所有可用的邻居都已被访问过)。
if numel(available_next) == 0
完整代码(所有立方体生成后):
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 100 ; %// maximum length of path
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
%// choose one neighbour randomly among the available ones
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
在侧面有 8
个元素的立方体上(总共 512 个立方体),如果将 maxPathLength
设置为 100,则路径会不停地访问 100 个元素:
如果您没有设置最大长度(或者只是将其设置为立方体的最大数量或更多),那么路径生成将继续直到立方体得到 "stuck"(例如,直到它到达一个所有邻居都已经访问过的地方):
编辑:
允许您在 3 个选项之间选择路径生成模式的逻辑变体:
open
:没有约束,可以随时重新访问多维数据集(路径仅在达到最大元素数时终止)。
stuck
: 如果找不到其他自由路径,则只能重新访问多维数据集
never
: 无法重新访问立方体(如果卡住,路径将终止)。
代码与最初的代码没有太大区别,但我更愿意在下面给出完整的修改代码,而不是仅仅修改代码,这样您就可以看到不同的功能是如何实现的。
%% // Set options
cube_revisit_options = {'open','stuck','never'} ;
%// "open" : No constraint, a cube can be revisited anytime (path
%// terminates only when max number of element is reached).
%// "stuck" : A cube may only be revisited if no other free path can be found
%// "never" : A cube cannot be revisited (the path terminates if stuck).
cube_revisit_mode = 'stuck' ;
cube_path_history = true ; %// set to false to display ALL path history, otherwise only "nHist" points displayed
nHist = 30 ; %// number of cubes in the history "trail"
alphatrail = linspace(0.1,0.9,nHist) ; %// decreasing transparency values for the trail
cmaptrail = cool(nHist) ; %// colormap for the trail
% cmaptrail = winter(nHist) ; %// other nice colormaps you can try
% cmaptrail = flipud(hot(nHist)) ;
%% // go for it
set(hcube,'Visible','off')
rng(2) %// set that if you want reproducible results, otherwise comment it
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 1000 ; %// maximum length of path
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
while ~path_terminated
%// exit loop if we reached the max number of elements
if ptIndex >= maxPathLength
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
all_neighbours = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
available_next = setdiff(all_neighbours,path_visited,'stable') ; %// find only "unvisited" cubes
nAvail = numel(available_next) ; %// number of actually available neighbour
switch cube_revisit_mode
case 'open'
%// any neighbour can be selected
available_next = all_neighbours ;
case 'stuck'
%// visited neighbour can only be selected if no other choice
if nAvail == 0
fprintf(2,'Got stuck cube %d at iteration %d. Escaping ...\n',path_visited(ptIndex),ptIndex);
available_next = all_neighbours ;
end
case 'never'
%// visited neighbour CANNOT be selected - Exit loop if no neighbour available
if nAvail == 0
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
end
nAvail = numel(available_next) ; %// recalculate in case we just changed it above
%// choose one neighbour randomly among the available ones
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
%// recolor
if cube_path_history
%// draw only "N" history cube, in a different color and with decreasing transparency
idxTrace = max(1,size(path_visited,2)-nHist):size(path_visited,2)-1 ;
set(hcube( path_visited(1:max(idxTrace(1)-1,1) ) ) ,'Visible','off') %// disable very old cubes
for ic=1:length(idxTrace)
set(hcube( path_visited(idxTrace(ic)) ) ,'Visible','on','FaceColor',cmaptrail(ic,:),'FaceAlpha',alphatrail(ic)) %// shade old cubes
end
else
%// draw ALL history cube, same color and transparency
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.1) %// shade old cubes uniformly
end
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
drawnow %// just for intermediate display, you can comment these 2 lines
pause(0.010) %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
10 cubes/side 的示例 maxPathLength=1000
:
我正在构建一个用许多小立方体填充空心立方体的程序。然后,通过随机立方体创建一条连接路径。通过查看每个立方体的直接邻居和 select 中的任何一个作为下一步,逐步找到路径。为了说明,下图显示了由立方体(红色立方体)组成的路径,
为了构建路径,我从一些立方体开始,用红色着色,找到它的相邻立方体(6 个相邻立方体,因为我们有 6 个面),select随机编辑它们中的任何一个,给 select 用红色编辑一个,然后通过重复相同的过程找到它的邻居。这个方法很好,但是如果一个相邻的立方体已经是红色的(已经属于路径)它不会识别它并且它可以再次select它。为了解决这个问题,我做了以下操作,
1- 我创建了一个名为 visited 的数组,并在其中存储了任何已访问的多维数据集的索引。
2- 我将当前立方体的邻居存储在另一个名为 a 的数组中,并将其与访问的数组进行比较,然后我删除所有公共元素,然后从 a.
中剩余的元素中取一个随机数3-有时所有的邻居都可以访问,所以a会变成空的。在这种情况下,我查找了当前立方体中的任何一个,select随机编辑了其中的任何一个,检查了它的邻居,将它们存储在邻居数组中(a) 并将其与访问的立方体数组进行比较。如果 neighbors 数组不为空,这将不断重复(while 循环)。但就我而言,程序陷入了 while 循环。还有,有时不会卡住,但路径中的立方体数量变得少于指定的数量。
我在上一个问题中获得了构建主立方体的代码,用小立方体填充它,并通过 Hoki 获得邻居 (
%%
clf; figure(1); format compact
h(1) = axes('Position',[0.2 0.2 0.6 0.6]);
%These are the different 8 vertices of the cube, each is defined by its 3 x y z coordinates:
vert = [ 1 1 -1; -1 1 -1; -1 1 1; 1 1 1; -1 -1 1; 1 -1 1; 1 -1 -1; -1 -1 -1];
%These are the 6 faces of the cube, each is defined by connecting 4 of the available vertices:
fac = [1 2 3 4; 4 3 5 6; 6 7 8 5; 1 2 8 7; 6 7 1 4; 2 3 5 8];
%// How many small cube do we want
MainCubeSide = 2 ; %// dimension of the side of the main cube
nCubeOnSide = 5 ; %// number of small cube in one "row/column" of the main cube
nCubesTotal = nCubeOnSide^3 ; %// total number of small cube
% define the Main container cube
MainCube.Vertices = vert *(2/MainCubeSide) ; %// because the cube as defined above has already a side=2
disp (2/ MainCubeSide);
MainCube.Faces = fac ;
MainCube.FaceColor = 'w' ;
hMainCube = patch(MainCube); %// patch function for the first big cube. MainCube can be seen as an object that contains all the infor that the patch function needs.
axis([-1, 1, -1, 1, -1, 1]);
axis equal;
hold on; %wait we didn't finish yet.
material metal;
alpha('color');
alphamap('rampdown');
view(138,24)
%view(3);
%% // generate all the coordinates of each cube first
dstep = MainCubeSide / nCubeOnSide ; %// step size for small cube vertices, this will determine the edge length for the small cube that best fits the required small cubes per edge.
vElem = bsxfun(@plus, vert / nCubeOnSide , -( MainCubeSide/2 - dstep/2)*[1 1 1] ) ; %// elementary cube vertices. Because the small cube was defined in the center of the big cube, to push it to one side we only need to move it by half the size of the main cube (minus half the size of a small cube)
%%
hold on;
coords = zeros( size(vElem,1),size(vElem,2), nCubesTotal ) ; %// To store the coordinates (8 rows * 3 columns) in every of the nCubesTotal slices.
colors = zeros( nCubesTotal , 3 ) ; %// To store the RBG colours for every small cube.
hcube = zeros( nCubesTotal , 1 ) ; %// To store the handles of the patch objects
iNeighbour = zeros( nCubesTotal , 6 ) ; %// To save the index of the neighbours
idc = permute( reshape(1:nCubesTotal,nCubeOnSide,nCubeOnSide,nCubeOnSide) , [3 2 1] ) ;
%// For each cube ...
iCube = 0 ;
for iline=1:nCubeOnSide %// Lines
for icol=1:nCubeOnSide %// Columns
for ih=1:nCubeOnSide %// Slice (height)* all for loops have the smame length, because the total number of cubes = mCubeOnSide^3
iCube = iCube + 1 ;
%// Take the base corner coordinates and add an offset to each coordinate
coords(:,:,iCube) = bsxfun(@plus, vElem , dstep*[(iline-1) (icol-1) (ih-1)]); %the fist one will not have offset, iline-1=0.
%// Save the colour
colors(iCube,:) = rand(1,3) ;
%// Draw the cube and store its info in the cube handler hcube.
hcube(iCube) = patch('Faces', fac, 'Vertices', coords(:,:,iCube), 'FaceColor', colors(iCube,:) ) ; %Remember each slice of coords contains the vertices of one of the small cubes, that's why it corresponds to vertices here.
drawnow %// just for intermediate display, you can comment these 2 lines
pause(0.05) %// just for intermediate display, you can comment these 2 lines
%// save adjacent cubes indices
ixAdj = [iline-1 iline+1 icol-1 icol+1 ih-1 ih+1] ; %// indices of adjacent cubes
idxFalse = (ixAdj<1) | (ixAdj>nCubeOnSide) ; %// detect cube which would be "out" of the main cube
ixAdj(idxFalse) = 1 ; %// just to not get an "indexing" error at this stage
iNeighbour(iCube,:) = [idc(ixAdj(1),icol,ih) idc(ixAdj(2),icol,ih) ...
idc(iline,ixAdj(3),ih) idc(iline,ixAdj(4),ih) ...
idc(iline,icol,ixAdj(5)) idc(iline,icol,ixAdj(6)) ] ;
iNeighbour(iCube,idxFalse) = NaN ;
end
end
end
getNeighbourIndex = @(idx) iNeighbour(idx,~isnan(iNeighbour(idx,:))) ;
set(hcube,'Visible','off') %// turn off all small cubes
cubeOfInterest = 32 ; %// select one cube
%// display the main cube of interest, and it's neighbours in transparency
set(hcube(cubeOfInterest),'Visible','on','FaceColor','r','FaceAlpha',1)
%set(hcube(getNeighbourIndex(CubeOfInterest)),'Visible','on','FaceColor','g','FaceAlpha',.05)
visited= []; %to hold the indices of the visited cubes.
for i=1:124
visited (i) = cubeOfInterest; %the first visited cube is the cube of interest.
a= (getNeighbourIndex(cubeOfInterest)); %get all the neighbors\ indices and store them in an array so we can select randomly from them.
disp (a);
looping=true;
while looping==true %To avoid visiting any previously visited cube.
disp ('program is looping') %just to know if the program is stuck in an infinite loop.
inds = find(ismember(a, visited)); %store the indices of the common elements if found.
a(inds)= []; %delete the indices of the common elements.
if (isempty (a)==1)
temp = randsample((getNeighbourIndex(cubeOfInterest)), 1);
a= getNeighbourIndex(temp);
disp (a)
else
looping=false ;
end
end
x = randsample(a, 1);
set(hcube(x),'Visible','on','FaceColor','r','FaceAlpha',1)
cubeOfInterest= x;
end
在上面的代码中构建路径从我初始化访问的多维数据集数组 (visited = []) 的行开始。
谁能告诉我为什么程序会卡在 while 循环中?
编辑:我在 Hoki 的代码 中添加了一些代码,即使访问了邻居也能使路径继续。它将 select 任何未访问的多维数据集并移动到它,如果它不会使路径断开连接。该代码现在按要求运行良好。这里是修改的部分,
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 125 ; %// maximum length of path
maxPathLength= maxPathLength+1;
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)this to be checked in case 2 as well.
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
availableAll =[1:125];
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
%//path_terminated = true ;
%//here I want to make the modification.
looping=true; %//To keep looping until we find the correct next move.
counter=0; %//to iterate through the cubes which are not visisted.
while looping==true
counter= counter+1;
jump= availableAll (counter); %//select the first available cube and check if it is suitable or not
if (~isempty (intersect(getNeighbourIndex(jump), path_visited))) %// if the selcted cube has a visited neighbor, it means it is suitable. The path will stay connected.
%good we found it.
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = jump ; %//add the selected cube to the path.
availableAll (availableAll==jump)= []; %//remove the selected cube from the list of available cubes.
looping= false; %//stop looping.
end
%continue
end
else
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
availableAll (availableAll==path_visited(ptIndex))= []; %//remove the selected cube from the list of available cubes.
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
%// choose one neighbour randomly among the available ones
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
上面的代码运行良好。 Hoki提供了很大的帮助,非常感谢Hoki.
谢谢。
这是一种实现随机路径的方法。我已经明确了退出条件。您可以根据需要添加更多退出条件或重新组合它们,但机制大致相同。重要步骤摘录:
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
然后您可以按照自己的方式添加退出条件检查和立方体着色。
推进路径的基本逻辑:
- 获取邻居列表。
available_next = getNeighbourIndex( path_visited(ptIndex) ) ;
- 检查其中一些是否已经被访问过。
[~,~,ib]=intersect(path_visited,available_next);
- 从 "Available" 列表中删除已经访问过的。
available_next(ib) = [] ;
- (随机)选择剩余可用的一个。
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
退出条件逻辑:
- 已达到路径元素的最大数量(如果您决定设置路径的最大长度)。
if ptIndex >= maxPathLength
- 不再有 "Available" 个邻居(即所有可用的邻居都已被访问过)。
if numel(available_next) == 0
完整代码(所有立方体生成后):
%% // Random path
rng(1) %// set that if you want reproducible results, otherwise comment it
set(hcube,'Visible','off')
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 100 ; %// maximum length of path
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
while ~path_terminated
available_next = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
[~,~,ib] = intersect(path_visited,available_next) ; %// check if we already went through some
if ~isempty(ib)
available_next(ib) = [] ; %// remove visited cube from "available" list
end
nAvail = numel(available_next) ; %// number of actually available neighbour
if nAvail == 0 %// Exit loop if no neighbour available
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
if ptIndex >= maxPathLength %// exit loop if we reached the max number of elements
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
%// choose one neighbour randomly among the available ones
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.2) %// shade old cubes
pause(0.05) %// just for intermediate display, you can comment these 2 lines
drawnow %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
在侧面有 8
个元素的立方体上(总共 512 个立方体),如果将 maxPathLength
设置为 100,则路径会不停地访问 100 个元素:
如果您没有设置最大长度(或者只是将其设置为立方体的最大数量或更多),那么路径生成将继续直到立方体得到 "stuck"(例如,直到它到达一个所有邻居都已经访问过的地方):
编辑:
允许您在 3 个选项之间选择路径生成模式的逻辑变体:
open
:没有约束,可以随时重新访问多维数据集(路径仅在达到最大元素数时终止)。stuck
: 如果找不到其他自由路径,则只能重新访问多维数据集never
: 无法重新访问立方体(如果卡住,路径将终止)。
代码与最初的代码没有太大区别,但我更愿意在下面给出完整的修改代码,而不是仅仅修改代码,这样您就可以看到不同的功能是如何实现的。
%% // Set options
cube_revisit_options = {'open','stuck','never'} ;
%// "open" : No constraint, a cube can be revisited anytime (path
%// terminates only when max number of element is reached).
%// "stuck" : A cube may only be revisited if no other free path can be found
%// "never" : A cube cannot be revisited (the path terminates if stuck).
cube_revisit_mode = 'stuck' ;
cube_path_history = true ; %// set to false to display ALL path history, otherwise only "nHist" points displayed
nHist = 30 ; %// number of cubes in the history "trail"
alphatrail = linspace(0.1,0.9,nHist) ; %// decreasing transparency values for the trail
cmaptrail = cool(nHist) ; %// colormap for the trail
% cmaptrail = winter(nHist) ; %// other nice colormaps you can try
% cmaptrail = flipud(hot(nHist)) ;
%% // go for it
set(hcube,'Visible','off')
rng(2) %// set that if you want reproducible results, otherwise comment it
startCubeIndex = randi([1 numel(hcube)],1) ; %// random starting cube
%// startCubeIndex = 1 ; %// or fixed one
maxPathLength = 1000 ; %// maximum length of path
path_terminated = false ; %// condition to get out of loop
path_visited = [] ; %// store the generated path (visited cubes)
ptIndex = 1 ;
path_visited(1) = startCubeIndex ;
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1)
while ~path_terminated
%// exit loop if we reached the max number of elements
if ptIndex >= maxPathLength
msgTerm = 'Path terminated. Reached max number of elements.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
all_neighbours = getNeighbourIndex( path_visited(ptIndex) ) ; %// get all the neighbours
available_next = setdiff(all_neighbours,path_visited,'stable') ; %// find only "unvisited" cubes
nAvail = numel(available_next) ; %// number of actually available neighbour
switch cube_revisit_mode
case 'open'
%// any neighbour can be selected
available_next = all_neighbours ;
case 'stuck'
%// visited neighbour can only be selected if no other choice
if nAvail == 0
fprintf(2,'Got stuck cube %d at iteration %d. Escaping ...\n',path_visited(ptIndex),ptIndex);
available_next = all_neighbours ;
end
case 'never'
%// visited neighbour CANNOT be selected - Exit loop if no neighbour available
if nAvail == 0
msgTerm = 'Path blocked. No other neighbour available.' ; %// Reason for terminating path
path_terminated = true ;
continue
end
end
nAvail = numel(available_next) ; %// recalculate in case we just changed it above
%// choose one neighbour randomly among the available ones
ptIndex = ptIndex+1 ;
path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;
%// recolor
if cube_path_history
%// draw only "N" history cube, in a different color and with decreasing transparency
idxTrace = max(1,size(path_visited,2)-nHist):size(path_visited,2)-1 ;
set(hcube( path_visited(1:max(idxTrace(1)-1,1) ) ) ,'Visible','off') %// disable very old cubes
for ic=1:length(idxTrace)
set(hcube( path_visited(idxTrace(ic)) ) ,'Visible','on','FaceColor',cmaptrail(ic,:),'FaceAlpha',alphatrail(ic)) %// shade old cubes
end
else
%// draw ALL history cube, same color and transparency
set(hcube( path_visited(1:ptIndex-1) ) ,'Visible','on','FaceColor','g','FaceAlpha',.1) %// shade old cubes uniformly
end
set(hcube( path_visited(ptIndex) ) ,'Visible','on','FaceColor','r','FaceAlpha',1) %// highlight new cube
drawnow %// just for intermediate display, you can comment these 2 lines
pause(0.010) %// just for intermediate display, you can comment these 2 lines
end
disp(msgTerm)
10 cubes/side 的示例 maxPathLength=1000
: