2011-02-08 13 views
2

私はMySQLに2つの(重要な)列AとBを持つテーブルを持っていて、その値はパッケージを参照しています。パッケージAがパッケージB.PHPを使用してMySQLデータベースのサイクルを検出する

に必要な場合にのみ、私はに期待していた場合、行は、グラフが非環式である場合、次いで(2)を決定し、PHPのグラフを生成する(1)テーブルにある(A DAG)、そうでない場合は、グラフのすべてのサイクルを(3)と印刷します。

SO 3は、(ジョンソンのアルゴリズム:http://dutta.csc.ncsu.edu/csc791_spring07/wrap/circuits_johnson.pdf)、理論的には、十分に簡単です。

(2)(3)何のサイクルをリストしないことによって行うことができますが、より高速なアルゴリズムがあった場合、私は思っていました。

I(1)の不明だ - 効率テーブルからデータを引き出し、(2)実装に役立つPHPのグラフを作成し、(3)。私はどうすればいいですか?

余談として

は、私はまた、とBとの競合は、私もを望んだ場合にのみ(4)例を見つけた場合列を有する2つの列でも、第二のテーブルを持っている(またはことを確認します何もありません): AはBを必要とし、BはCを必要としますが、AはCと競合します

+0

のコメントで任意のコードレビューをいただければと思います、あなたは最大の深さを持っていますか? – Xailor

+0

有限ですが、それ以外にはありません。私はA => B => C => ... => Z => Aのような非常に長い鎖を持つかもしれません。私はまた、樹木(すなわち、未結合)とは対照的に、有向枝である可能性があることを明確にすべきである。 – Zeophlite

答えて

2

アルゴリズムhereを使用します。基本的にはリーフノードを削除することによって、ループ(1組)または空のグラフが残っています。

$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"; 
     } 
    } 
} 

(4)

Aを求めるための競合(BがCを必要とする必要はなく、Cとの競合は、私はCを探し、Aから出発して、各競合のために深さ優先検索を使用)。

$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; 
     } 
    } 
} 

私はこの答え

-1

「私の宿題で私を助けてください。グラフを描画するという点で

は - graphvizのを見ている - これは、グラフのすべての種類を生成します。 Here's an example PHPのソースコードを解析してコールグラフを取得します。

申し訳ありませんが、私はあなたが提供する(しかし、よくあなたのソース素材へのリンクを提供するために行われる)の参照を読んで、彼らはそれが最適であるかどうかについて考えて使用しましたアルゴリズムをワークアウトすることなく、十分に忙しいです。

新しいPHPのガベージコレクタのためのソースコードを見ていたいかもしれません - 同じことを行います。 (実際にはツリーを歩くだけで済みます。すでに訪れたノードに来たら、ループがあります)。 (3)

私が終わった

$pkgList = array(); 
$result = mysqli_query($conn, 'SELECT * FROM `Packages`'); 
while (($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) != NULL) { 
    $pkgList[] = $row['idPackages']; 
} 

$reqEdgeList = array(); 
$conEdgeList = array(); 

$result = mysqli_query($conn, "SELECT * FROM `Dependancies` WHERE `Relationship` = 'Requires'"); 
while (($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) != NULL) { 
    switch ($row['Relationship']) { 
     case 'Requires': 
      $reqEdgeList[] = array($row["DependerPackage"], $row["DependeePackage"]); 
      break; 
     case 'Conflicts': 
      $conEdgeList[] = array($row["DependerPackage"], $row["DependeePackage"]); 
      break; 
    } 
} 

(2)検索

(1)でこのトピックを見つけ、誰の利益に

+0

申し訳ありませんが、私が見つけたアルゴリズムを実装する方法について質問していませんが、**(1)**グラフを生成するためのベストプラクティスは何ですか?コンビナトリアル/データ構造の種類)をPHPのMySQLデータから、そして**(2)**グラフのトラバーサルをPHPから取得します。グラフ描画に興味はありませんが、リンクに感謝します。 – Zeophlite

+0

私は、あまり知られていないアルゴリズムが私の仕事(もちろん私の仕事)やそれを実装する方法に良いのかどうか教えてくれるのではなく、別のもの(あなたが知っていれば) (1)と(2)に関連するサンプルコードを提案(リンク)します。また、これは宿題ではなく、実際の仕事 - 私は他の言語でグラフトラバーサルを実装していますが、他の人がPHPで、特にMySQLデータを使って行ったことを単に探しています。 – Zeophlite

関連する問題