在无限循环程序stucks尽管存在终止它的条件:MATLAB(Program stucks in i

2019-09-30 09:24发布

我建设,填补了许多小方块中空立方体的程序。 然后,使通过随机立方体连接的路径。 路径是通过查看每个立方体的直接邻居发现一步一步的选择它们中的任何一个作为下一个步骤。 为了说明,下面的图片显示的是由立方体的路径(红色立方体),

要构建路径,我开始形成一些立方体,用红颜色的它,发现它的邻居立方体(6个邻居,因为我们有6个面),选择其中的任何随机,有色选定一个带有红色,然后重复同样的发现它的邻居处理。 这是一个好方法,但如果邻居立方体已经是红色的(已经属于路径)也不会承认,它可以重新选择。 为了解决这个问题,我做了如下,

1-我由称为访问阵列,并且我中储存的所有访问的立方体的索引。

2-我所存储的当前的立方体的邻居另一个数组称为比较它与访问之一,我删除的任何共同的元件,然后把残留在一个元件的随机数。

3-有时候,所有的邻居都可以访问, 因此将成为空。 在这种情况下,我找了所有当前多维数据集的中,选择其中的任何随机,检查它的邻居,将它们存储邻居阵列( )相比,随着访问的立方体阵列。 这将不断重复(while循环),如果邻居数组不为空。 但在我的情况下,程序陷在while循环。 此外,有时它不会被卡住,但立方体的路径数小于指定的一个。

我已经获得的构建主要的立方体,用小方块填满它的代码,并获得由伯耆邻居前一个问题( 备案与MATLAB小立方体立方体的整个体积 ),我刚添加的构建路径机制使用邻居。 下面是代码,

%%
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

在代码构建路径的上方从其中我初始化访问立方体阵列(受访= [])的行开始。

谁能告诉我,为什么程序卡在while循环?

编辑:我已经添加了一些代码来伯耆的代码 ,以使路径即使走访邻居继续。 它会选择任何没有访问过的立方体,并移动到它,如果它不会使断开的路径。 该代码是现在的工作合租以及所需。 下面是修改的部分,

%% // 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)

上面的代码运行良好。 伯耆提供了很大的帮助,非常感谢伯耆

谢谢。

Answer 1:

下面是实现随机路径的方式。 我explicited的退出条件。 如果你愿意,你可以添加更多的退出条件或重新组合它们,但其作用机理是大致相同的。 的重要步骤的摘录:

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_next(ib) = [] ;
  • 选择(随机)剩余的可用之一。 path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;

对于退出条件的逻辑:

  • 路径元素的最大数量已达到( 如果您决定设置路径的最大长度 )。 if ptIndex >= maxPathLength
  • 没有更多的“可用”的邻居(即所有可用的邻居都已经被访问)。 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个元素没有停止:

如果您没有设置最大长度(或只是将其设置为立方体甚至更多的最大数量),那么路径生成的推移,直到立方“被困”(例如,直到它到达一个地方,所有的邻居都已被访问):


编辑:

这允许选择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个立方体/侧用一个例子maxPathLength=1000



文章来源: Program stucks in infinite loop although there is a condition to terminate it: MATLAB