本文介绍了在无限循环程序stucks但有一个条件终止它:MATLAB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm building a program that fills a hollow cube with many small cubes. Then, makes a connected path through random cubes. The path is found step by step by looking at the direct neighbors of each cube and select anyone of them as the next step. To illustrate, The following picture shows the path that consists of cubes (red cubes),

要建立我就开始形成了一些立方体的路径,用红颜色的它,发现它的邻居立方体(6邻居,因为我们有6个面),选择其中任何一个随机,有色选择之一,红色,然后找到它的邻居重复相同的处理。此方法是很好的,但是如果一个邻居立方体已经是红色(已经属于轨迹),它不会认识到,并且它可以重新选择。为了解决这个我做了以下,

To build the path I started form some cube, colored it with red, found its neighbor cubes (6 neighbors because we have 6 faces), selected any of them randomly, colored the selected one with red, then find its neighbors by repeating the same process. This method is good, but if a neighbor cube is already red (already belongs to the path) it won't recognize that and it can select it again. To solve this I did the following,

1 - 我做了所谓的访问数组,我储存的所有访问多维数据集的索引。

1- I made an array called visited, and I stored the index of any visited cube in it.

2 - 我保存当前多维数据集的另一个数组叫了邻居的并与访问技术相比它,我删除了所有通用元素,然后把一个从剩余的元素中随机数的

2- I stored the neighbors of the current cube in another array called a and compared it with the visited one, and I deleted any common elements, then took a random number from the elements remaining in a.

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

3- Sometimes all of the neighbors can be visited, so a will become empty. In this case, I looked for any of the current cube's, selected any of them randomly, checked for its neighbors, stored them in the neighbors array (a) and compared that with the visited cubes array. This will keep repeating (while loop) if the neighbors array is not empty. But in my case, the program gets stuck in the while loop. Also, sometime it doesn't get stuck, but the number of cubes in the path becomes less than the specified one.

我获得了code,它建立的主要立方体,用小方块填满它,并通过伯耆在previous问题(Filing在MATLAB 小立方体),一个立方体的整个体积为我补充说,建立使用邻居路径的机制。这里是code,

I have obtained the code that builds the main cube, fills it with small cubes, and gets the neighbors by Hoki in a previous question (Filing the entire volume of a cube with small cubes in MATLAB) I just added the mechanism that builds the path using the neighbors. Here is the code,

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

建筑在code的路径上面的线开始在我初始化走访立方体阵列(参观= [])。

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

Can anyone please tell me why the program gets stuck in the while loop?

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

I've added some code to Hoki's code to make the path continue even if the neighbors are visited. It will select any not visited cube and move to it if it will not make the path disconnected. The code is now working vey well as required. Here is the modified part,

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

在code以上运作良好。 伯耆提供了很大的帮助,非常感谢伯耆

The code above is working well. Hoki provided a great help, thanks a lot Hoki.

感谢你。

推荐答案

这里有一个方法来实现随机路径。我explicited的退出条件。如果你想,你可以添加更多的退出条件或重新组合它们,但其作用机理大致相同。的重要步骤摘录:

Here's a way to implement the random path. I've explicited the exit conditions. You can add more exit conditions if you want or regroup them, but the mechanism is roughly the same. An extract of the important steps:

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) ) ;

然后添加了检查退出条件和多维数据集的着色你想要的方式。

Then you add the checking for exit conditions and the coloring of the cubes the way you want.

的基本逻辑推进的路径:

The basic logic to advance the path:

  • 获取邻居列表。 available_next = getNeighbourIndex(path_visited(ptIndex));
  • 检查,如果他们中的一些人已经访问过。 [〜,〜,IB] =相交(path_visited,available_next);
  • 删除已经从可用列表访问。 available_next(IB)= [];
  • 选择(随机)的剩余可用之一。 path_visited(ptIndex)= available_next(兰迪([1 nAvail],1));
  • Get the list of neighbours. available_next = getNeighbourIndex( path_visited(ptIndex) ) ;
  • check if some of them were already visited. [~,~,ib]=intersect(path_visited,available_next);
  • remove already visited from the "Available" list. available_next(ib) = [] ;
  • choose (randomly) one of the remaining available. path_visited(ptIndex) = available_next( randi([1 nAvail],1) ) ;

有关退出条件的逻辑:

  • 路径元素的最大数量已经达到了(如果您决定设置路径的最大长度的)。 如果ptIndex&GT; = maxPathLength
  • 在没有更多的可用的邻居(即所有可用的邻居都已经被访问)。 如果numel(available_next)== 0
  • Max number of path element has been reached (if you decide to set a maximum length of path). if ptIndex >= maxPathLength
  • No more "Available" neighbour (i.e. all available neighbour have already been visited). if numel(available_next) == 0

全部code(毕竟多维数据集生成):

%% // 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个元素而不停止:


On a cube with 8 elements on the side (so 512 cubes total), if you set maxPathLength to 100, the path visits 100 elements without stopping:

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

If you do not set the max length (or just set it to the max number of cube or even more), then the path generation goes on until the cube get "stuck" (e.g. until it arrives in a place where all the neighbours have already been visited):

编辑:

逻辑的变化,让你可以选择3个选项之间的路径生成方式:

A variation of the logic which allow you to choose the path generation mode between 3 options:

  • 打开 :没有约束,一个立方体可以随时重新(路径终止只有当达到元素的最大数)
  • :多维数据集只可重新如果没有其他的自由行程可以发现
  • 从来没有 :多维数据集在无法回访(路径即告终止,如果卡住)

在code不是从最初的一个不同的,但不是仅仅修改I preFER给下面的完整修改code,所以你可以看到如何在不同的功能实现。

The code is not that different from the initial one but instead of just modifying I prefer to give the full modified code below, so you can see how the different functionalities are implemented.

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

这篇关于在无限循环程序stucks但有一个条件终止它:MATLAB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 23:06