Thicket data repository for the EEG
at main 4.5 kB view raw
1{ 2 "id": "https://www.tunbury.org/2025/07/21/depth-first-topological-ordering", 3 "title": "Depth-first topological ordering", 4 "link": "https://www.tunbury.org/2025/07/21/depth-first-topological-ordering/", 5 "updated": "2025-07-21T00:00:00", 6 "published": "2025-07-21T00:00:00", 7 "summary": "Over the last few months, I have written several posts on the package installation graphs specifically, Topological Sort of Packages, Installation order for opam packages and Transitive Reduction of Package Graph. In this post, I’d like to cover a alternative ordering solution.", 8 "content": "<p>Over the last few months, I have written several posts on the package installation graphs specifically, <a href=\"https://www.tunbury.org/2025/03/25/topological-sort/\">Topological Sort of Packages</a>, <a href=\"https://www.tunbury.org/2025/03/31/opam-post-deps/\">Installation order for opam packages</a> and <a href=\"https://www.tunbury.org/2025/06/23/transitive-reduction/\">Transitive Reduction of Package Graph</a>. In this post, I’d like to cover a alternative ordering solution.</p>\n\n<p>Considering the graph above, first presented in the <a href=\"https://www.tunbury.org/2025/03/25/topological-sort/\">Topological Sort of Packages</a>, which produces the installation order below.</p>\n\n<ol>\n <li>base-threads.base</li>\n <li>base-unix.base</li>\n <li>ocaml-variants</li>\n <li>ocaml-config</li>\n <li>ocaml</li>\n <li>dune</li>\n</ol>\n\n<p>The code presented processed nodes when all their dependencies are satisfied (i.e., when their in-degree becomes 0). This typically means we process “leaf” nodes (nodes with no dependencies) first and then work our way up. However, it may make sense to process the leaf packages only when required rather than as soon as they can be processed. The easiest way to achieve this is to reverse the edges in the DAG, perform the topological sort, and then install the pages in reverse order.</p>\n\n<div><div><pre><code><span>let</span> <span>reverse_dag</span> <span>(</span><span>dag</span> <span>:</span> <span>PackageSet</span><span>.</span><span>t</span> <span>PackageMap</span><span>.</span><span>t</span><span>)</span> <span>:</span> <span>PackageSet</span><span>.</span><span>t</span> <span>PackageMap</span><span>.</span><span>t</span> <span>=</span>\n <span>let</span> <span>initial_reversed</span> <span>=</span> <span>PackageMap</span><span>.</span><span>fold</span> <span>(</span><span>fun</span> <span>package</span> <span>_</span> <span>acc</span> <span>-&gt;</span>\n <span>PackageMap</span><span>.</span><span>add</span> <span>package</span> <span>PackageSet</span><span>.</span><span>empty</span> <span>acc</span>\n <span>)</span> <span>dag</span> <span>PackageMap</span><span>.</span><span>empty</span> <span>in</span>\n <span>PackageMap</span><span>.</span><span>fold</span> <span>(</span><span>fun</span> <span>package</span> <span>dependencies</span> <span>reversed_dag</span> <span>-&gt;</span>\n <span>PackageSet</span><span>.</span><span>fold</span> <span>(</span><span>fun</span> <span>dependency</span> <span>acc</span> <span>-&gt;</span>\n <span>let</span> <span>current_dependents</span> <span>=</span> <span>PackageMap</span><span>.</span><span>find</span> <span>dependency</span> <span>acc</span> <span>in</span>\n <span>PackageMap</span><span>.</span><span>add</span> <span>dependency</span> <span>(</span><span>PackageSet</span><span>.</span><span>add</span> <span>package</span> <span>current_dependents</span><span>)</span> <span>acc</span>\n <span>)</span> <span>dependencies</span> <span>reversed_dag</span>\n <span>)</span> <span>dag</span> <span>initial_reversed</span>\n</code></pre></div></div>\n\n<p>With such a function, we can write this:</p>\n\n<div><div><pre><code><span>reverse_dag</span> <span>dune</span> <span>|&gt;</span> <span>topological_sort</span> <span>|&gt;</span> <span>List</span><span>.</span><span>rev</span>\n</code></pre></div></div>\n\n<ol>\n <li>ocaml-variants</li>\n <li>ocaml-config</li>\n <li>ocaml</li>\n <li>base-unix.base</li>\n <li>base-threads.base</li>\n <li>dune</li>\n</ol>\n\n<p>Now, we don’t install base-unix and base-threads until they are actually required for the installation of dune.</p>", 9 "content_type": "html", 10 "author": { 11 "name": "Mark Elvers", 12 "email": "mark.elvers@tunbury.org", 13 "uri": null 14 }, 15 "categories": [ 16 "OCaml,opam", 17 "tunbury.org" 18 ], 19 "source": "https://www.tunbury.org/atom.xml" 20}