使用PHP检测MySQL数据库中的周期

使用PHP检测MySQL数据库中的周期,php,mysql,graph,cycle,Php,Mysql,Graph,Cycle,我在MySQL中有一个表,有两个(重要)列,a和B,其值引用一个包。当且仅当包A对包B有要求时,表中有一行 我希望(1)用php生成一个图,然后(2)确定该图是否是非循环的(DAG),如果不是,则打印(3)图中的所有循环 所以3在理论上是很容易的,(约翰逊的算法:) (2) 可以通过(3)列出没有循环来完成,但我想知道是否有更快的算法 我不确定(1)-高效地从表中提取数据,并用php生成一个适合于实现(2)和(3)的图形。我应该怎样做 另外,我还有第二个表,也有两列,当且仅当a与B冲突时才有一

我在MySQL中有一个表,有两个(重要)列,a和B,其值引用一个包。当且仅当包A对包B有要求时,表中有一行

我希望(1)用php生成一个图,然后(2)确定该图是否是非循环的(DAG),如果不是,则打印(3)图中的所有循环

所以3在理论上是很容易的,(约翰逊的算法:)

(2) 可以通过(3)列出没有循环来完成,但我想知道是否有更快的算法

我不确定(1)-高效地从表中提取数据,并用php生成一个适合于实现(2)和(3)的图形。我应该怎样做


另外,我还有第二个表,也有两列,当且仅当a与B冲突时才有一行。我还想(4)查找案例(或验证没有案例),其中:
A需要B,B需要C,但A与C的冲突听起来像是“请帮我做作业”

在渲染图形方面——看看graphviz——这将生成各种图形。它解析PHP源代码以获取调用图

对不起,我已经够忙了,没有阅读你提供的参考资料(但在提供到你的源材料的链接方面做得很好),也没有研究出他们使用的算法,然后思考它是否是最优的


您可能想看看新的PHP垃圾收集器的源代码,它也做同样的事情。(实际上,你只需要在树上走一走——如果你来到一个你已经访问过的节点,那么你就有了一个循环)。

为了在搜索中找到这个主题的任何人的利益

(1)

(2)(3)

我最终使用了这个算法。基本上,通过删除叶节点,您要么留下一个(一组)循环,要么留下一个空图

$allReqs = $reqEdgeList;

$noDependanciesCycle = true;

$searching = true;
while ($searching) {
    if (empty($pkgList)) {
        $searching = false;
        echo "Req is a DAG\n<br />";
    } else {
        $foundleaf = false;
        $leaf = null;
        foreach ($pkgList as $key => $l) {
            $isLeaf = true;
            foreach ($reqEdgeList as $k => $edge) {
                if ($edge[0] == $l) {
                    $isLeaf = false;
                }
            }

            if ($isLeaf) {
                $foundleaf = true;
                $leaf = $l;
            }
        }
        if ($foundleaf) {
            $pkgList = array_diff($pkgList, array($leaf));
            foreach ($reqEdgeList as $key => $value) {
                if ($value[1] == $leaf) {
                    unset($reqEdgeList[$key]);
                }
            }
            $reqEdgeList = array_values($reqEdgeList);
        } else {
            $searching = false;
            echo "Req cycle detected\n<br />";
            $noDependanciesCycle = false;
            print_r($reqEdgeList);
            echo "<br />\n";
        }
    }
}
$allReqs=$reqEdgeList;
$noDependanciesCycle=true;
$search=true;
同时($搜索){
if(空($pkgList)){
$search=false;
echo“Req是一个DAG\n
”; }否则{ $foundleaf=false; $leaf=null; foreach($pkgList作为$key=>l){ $isLeaf=true; foreach($reqEdgeList为$k=>$edge){ 如果($edge[0]==$l){ $isLeaf=false; } } 如果($isLeaf){ $foundleaf=true; $leaf=$l; } } 如果($foundleaf){ $pkgList=array_diff($pkgList,array($leaf)); foreach($requedgelistas$key=>$value){ 如果($value[1]=$leaf){ 未设置($REQUEDGELIST[$key]); } } $reqEdgeList=数组值($reqEdgeList); }否则{ $search=false; echo“检测到请求周期\n
”; $noDependanciesCycle=false; 打印(需求列表); 回显“
\n”; } } }
(4)

为了找到A需要B需要C,但A与C冲突,我对每个冲突使用深度优先搜索,从A开始,寻找C(冲突)

$reqEdgeList=$allReqs;
回显“
\n”; $anyReqConfError=假; foreach($conedgelistas$endpoints){ 对于($i=0;$i<2;$i++){ 如果($i==0){ $startPkg=$endpoints[0]; $endPkg=$endpoints[1]; }否则{ $startPkg=$endpoints[1]; $endPkg=$endpoints[0]; } $marked=array(); foreach($allPkgs作为$pkg){ $marked[$pkg]=false; } $queue=array(); $queue[]=$startPkg;//enque $marked[$startPkg]=真; $search=true; $found=false; 同时($搜索){ $v=array\u shift($queue);//deque(对堆栈(dfs)使用array\u pop) 如果($v==$endPkg){ $search=false; $found=true; }否则{ foreach($REQUEDGELIST as$edge){ 如果($edge[0]==$v){ $w=$edge[1]; 如果(!$标记为[$w]){ $marked[$w]=真; $queue[]=$w; } } } } 如果($搜索){ $search=!empty($queue); } } 如有($已找到){ echo“$startPkg需要$endPkg,但存在冲突[$endpoints[0]$endpoints[1]]]\n
”; $anyReqConfError=真; $noDependanciesCycle=false; } } }

如果我误导了你,我将不胜感激,但我不是在问如何实现我找到的算法,我是在问(1)在PHP中从MySQL数据生成图形(如组合/数据结构类型)和(2)在PHP中进行图形遍历的最佳实践是什么。我对图形绘制不感兴趣,但谢谢你的链接。我不是要你告诉我一些模糊的算法是否适合我的任务(当然,这是我的工作)或者如何实现它,而是建议另一个(如果你知道的话),更重要的是建议(链接到)与(1)和(2)相关的示例代码。我还应该提到,这不是家庭作业,而是实际工作——我已经在其他语言中实现了图形遍历,我只是想了解其他人是如何在PHP中实现的,特别是在MySQL data.Finite中,但除此之外,不。我可能有一个很长的链,比如a=>B=>C=>…=>Z=>a。我还应该澄清,它可能是一个定向林,而不仅仅是一棵树(即未连接)。
$allReqs = $reqEdgeList;

$noDependanciesCycle = true;

$searching = true;
while ($searching) {
    if (empty($pkgList)) {
        $searching = false;
        echo "Req is a DAG\n<br />";
    } else {
        $foundleaf = false;
        $leaf = null;
        foreach ($pkgList as $key => $l) {
            $isLeaf = true;
            foreach ($reqEdgeList as $k => $edge) {
                if ($edge[0] == $l) {
                    $isLeaf = false;
                }
            }

            if ($isLeaf) {
                $foundleaf = true;
                $leaf = $l;
            }
        }
        if ($foundleaf) {
            $pkgList = array_diff($pkgList, array($leaf));
            foreach ($reqEdgeList as $key => $value) {
                if ($value[1] == $leaf) {
                    unset($reqEdgeList[$key]);
                }
            }
            $reqEdgeList = array_values($reqEdgeList);
        } else {
            $searching = false;
            echo "Req cycle detected\n<br />";
            $noDependanciesCycle = false;
            print_r($reqEdgeList);
            echo "<br />\n";
        }
    }
}
$reqEdgeList = $allReqs;
echo "<br />\n";

$anyReqConfError = false;
foreach ($conEdgeList as $endpoints) {
    for ($i = 0; $i < 2; $i++) {
        if ($i == 0) {
            $startPkg = $endpoints[0];
            $endPkg = $endpoints[1];
        } else {
            $startPkg = $endpoints[1];
            $endPkg = $endpoints[0];
        }

        $marked = array();
        foreach ($allPkgs as $pkg) {
            $marked[$pkg] = false;
        }

        $queue = array();
        $queue[] = $startPkg; // enque
        $marked[$startPkg] = true;

        $searching = true;
        $found = false;
        while ($searching) {
            $v = array_shift($queue); // deque (use array_pop for stack (dfs))
            if ($v == $endPkg) {
                $searching = false;
                $found = true;
            } else {
                foreach ($reqEdgeList as $edge) {
                    if ($edge[0] == $v) {
                        $w = $edge[1];
                        if (!$marked[$w]) {
                            $marked[$w] = true;
                            $queue[] = $w;
                        }
                    }
                }
            }

            if($searching) {
                $searching = !empty($queue);
            }
        }

        if($found) {
            echo "$startPkg requires $endPkg, but are conflicting [$endpoints[0] $endpoints[1]]\n<br />";
            $anyReqConfError = true;
            $noDependanciesCycle = false;
        }
    }
}