5

我有以下过程,旨在检测无向图中的循环,该图中采用边(单边)和边集(边集)。还有两个参数,left_set(用于存储要传递给递归的必要边)和 cyclic(它是一个布尔值,最终确定图是否是循环的。

由于某种原因,检测在第一次递归之后不起作用。这是带有解释详细信息的注释的代码:

我在 MYSQL 中实现了以下功能(以避免混淆):

-concat_set():如果是空集,则返回两个集的连接,以说明放错位置的 ','

-remove_first():从集合中移除第一个成员

-get_left_node()/get_right_node:返回边的节点,边之间的分隔符是':',所以边看起来像这样'12:15'

CREATE PROCEDURE `is_cyclic`(
IN `singleedge` VARCHAR(15), 
IN `edgeset` VARCHAR(1024), 
IN 'left_set' VARCHAR(512), 
OUT `cyclic` BOOLEAN)

BEGIN
DECLARE se_left VARCHAR(5);
DECLARE es_left VARCHAR(5);
DECLARE se_right VARCHAR(5);
DECLARE es_right VARCHAR(5);
Call get_left_node(singleedge, se_left);
Call get_left_node(SUBSTRING_INDEX(edgeset, ',', 1), es_left);
Call get_right_node(singleedge, se_right);
Call get_right_node(SUBSTRING_INDEX(edgeset, ',', 1), es_right);



--is edgeset emptY?
    IF LENGTH(edgeset)= 0 AND LENGTH(left_set) = 0 THEN
        BEGIN

            SET cyclic= false;

        END;    

--are singeeledge and first edge in edgeset the same?        
    ELSEIF ((se_left = es_left
        OR se_left= es_right)
        AND( se_right = es_left
        OR se_right = es_right)) THEN
                    BEGIN
            set cyclic= true;
                        END;


--do singleedge and first edge in edgeset share any vertices?       
    ELSEIF se_left = es_left 
        OR se_left= es_right
        OR se_right = es_left
        OR se_right = es_right
        THEN
        --check for all possiblities
            BEGIN

                --if left vertex of singleedge and left vertex of current edge in front of edgeset are the same               
                IF se_left=es_left THEN
                                    BEGIN
                                    --test if the edge of combined uncommon vertices (forming concat(se_right,':',es_right)) exists in the remaining edgeset concatanated with the left_set
                                    CALL is_cyclic(concat(se_right,':',es_right),concat_set(left_set,remove_first(edgeset)), '', cyclic);
                                    --if the recursion returns cyclic=false, then remove the considered edge from edgeset and continue trying to match the original singleedge with the rest of edgeset
                                     IF cyclic=false THEN
                                        CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
                                      END IF;
                                     END;
                ELSEIF se_left= es_right THEN
                                    BEGIN
                                    CALL is_cyclic(concat(se_right,':',es_left), concat_set(left_set, remove_first(edgeset)), '', cyclic);
                                    IF cyclic=false THEN
                                        CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
                                     END IF;
                                     END;
                ELSEIF se_right=es_left THEN
                                    BEGIN
                                    CALL is_cyclic(concat(se_left,':',es_right), concat_set(left_set, remove_first(edgeset)), '', cyclic);
                                    IF cyclic=false THEN
                                        CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
                                    END IF;
                                    END;
                ELSE
                                    BEGIN
                                    CALL is_cyclic(concat(se_left,':',es_left), concat_set(left_set, remove_first(edgeset)), '', cyclic);
                                    IF cyclic=false THEN
                                        CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
                                    END IF;  
                                      END;
                                END IF;


            END;    


        ELSE
            BEGIN
                --if the current edge being considered from the edgeset does not contain any vertex in common with singleedge, set it aside into left_set and call is_cyclic recurisvely with the edge removed
                SET left_set = concat_set(left_set, SUBSTRING_INDEX(edgeset, ',', 1));
                CALL is_cyclic(singleedge, remove_first(edgeset), left_set, cyclic);
                END;

    END IF;
END
4

1 回答 1

3

尝试重置这个mysql变量:max_sp_recursion_depth,thread_stack

SET SESSION max_sp_recursion_depth = 10;
SET SESSION thread_stack = 250000;

执行上述命令后,调用您的程序。串行执行这两个语句。根据您的要求增加thread_stack变量的大小。

于 2012-12-05T04:50:12.827 回答