Lutz Roeder 3 лет назад
Родитель
Сommit
bfac36f2a8
2 измененных файлов с 34 добавлено и 29 удалено
  1. 33 28
      source/dagre.js
  2. 1 1
      test/models.json

+ 33 - 28
source/dagre.js

@@ -15,7 +15,7 @@ dagre.layout = (graph, options) => {
         if (options.time) {
             /* eslint-disable */
             console.log(name + ': ' + duration + 'ms');
-            /* eslint-enable */
+        /* eslint-enable */
         }
         return result;
     };
@@ -284,16 +284,13 @@ dagre.layout = (graph, options) => {
                 }
                 return t;
             };
-            // Initializes ranks for the input graph using the longest path algorithm. This
-            // algorithm scales well and is fast in practice, it yields rather poor
-            // solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
-            // ranks wide and leaving edges longer than necessary. However, due to its
-            // speed, this algorithm is good for getting an initial ranking that can be fed
-            // into other algorithms.
+            // Initializes ranks for the input graph using the longest path algorithm.
+            // This algorithm scales well and is fast in practice, it yields rather poor solutions.
+            // Nodes are pushed to the lowest layer possible, leaving the bottom ranks wide and leaving edges longer than necessary.
+            // However, due to its speed, this algorithm is good for getting an initial ranking that can be fed into other algorithms.
             //
-            // This algorithm does not normalize layers because it will be used by other
-            // algorithms in most cases. If using this algorithm directly, be sure to
-            // run normalize at the end.
+            // This algorithm does not normalize layers because it will be used by other algorithms in most cases.
+            // If using this algorithm directly, be sure to run normalize at the end.
             //
             // Pre-conditions:
             //    1. Input graph is a DAG.
@@ -303,25 +300,33 @@ dagre.layout = (graph, options) => {
             //    1. Each node will be assign an (unnormalized) 'rank' property.
             const longestPath = (g) => {
                 const visited = new Set();
-                const dfs = (v) => {
-                    const node = g.node(v);
-                    if (visited.has(v)) {
-                        return node.label.rank;
-                    }
-                    visited.add(v);
-                    let rank = Number.MAX_SAFE_INTEGER;
-                    for (const e of node.out) {
-                        rank = Math.min(rank, dfs(e.w) - e.label.minlen);
-                    }
-                    if (rank === Number.MAX_SAFE_INTEGER) {
-                        rank = 0;
+                const stack = [ Array.from(g.nodes.values()).filter((node) => node.in.length === 0).reverse() ];
+                while (stack.length > 0) {
+                    const current = stack[stack.length - 1];
+                    if (Array.isArray(current)) {
+                        const node = current.pop();
+                        if (current.length === 0) {
+                            stack.pop();
+                        }
+                        if (!visited.has(node)) {
+                            visited.add(node);
+                            const children = node.out.map((e) => e.wNode);
+                            if (children.length > 0) {
+                                stack.push(node);
+                                stack.push(children.reverse());
+                            }
+                            else {
+                                node.label.rank = 0;
+                            }
+                        }
                     }
-                    node.label.rank = rank;
-                    return rank;
-                };
-                for (const node of g.nodes.values()) {
-                    if (node.in.length === 0) {
-                        dfs(node.v);
+                    else {
+                        stack.pop();
+                        let rank = Number.MAX_SAFE_INTEGER;
+                        for (const e of current.out) {
+                            rank = Math.min(rank, e.wNode.label.rank - e.label.minlen);
+                        }
+                        current.label.rank = rank;
                     }
                 }
             };

+ 1 - 1
test/models.json

@@ -3571,7 +3571,7 @@
     "target":   "netron_issue_589_5.onnx.zip",
     "source":   "https://github.com/lutzroeder/netron/files/9124841/netron_issue_589_5.onnx.zip",
     "format":   "ONNX v6",
-    "error":    "Maximum call stack size exceeded",
+    "action":   "skip-render",
     "link":     "https://github.com/lutzroeder/netron/issues/589"
   },
   {