diff --git a/Cargo.lock b/Cargo.lock index 4bdbbda..daf6aec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,27 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "csv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" +dependencies = [ + "memchr", +] + [[package]] name = "either" version = "1.12.0" @@ -62,6 +83,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "libc" version = "0.2.155" @@ -74,6 +101,12 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + [[package]] name = "petgraph" version = "0.6.5" @@ -90,6 +123,24 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.5" @@ -125,10 +176,48 @@ name = "rustc-hash" version = "2.0.0" source = "git+https://github.com/rust-lang/rustc-hash#8f258eec1f9e4a328fa0f7d370fcf7d51251ce96" +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "treewidth-heuristic-using-clique-graphs" version = "0.1.0" dependencies = [ + "csv", "itertools", "log", "petgraph", @@ -136,6 +225,12 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index deee918..b677b0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,4 +12,5 @@ petgraph = "0.6.4" itertools = "0.13" rand = "0.8.5" rustc-hash = { version ="2.0.0", git = "https://github.com/rust-lang/rustc-hash"} -log = "0.4.21" \ No newline at end of file +log = "0.4.21" +csv = "1.3.0" diff --git a/src/compute_treewidth_upper_bound.rs b/src/compute_treewidth_upper_bound.rs index fe62b44..65cbadf 100644 --- a/src/compute_treewidth_upper_bound.rs +++ b/src/compute_treewidth_upper_bound.rs @@ -20,8 +20,13 @@ use find_width_of_tree_decomposition::find_width_of_tree_decomposition; /// MSTAndUseTreeStructure Constructs a minimum spanning tree of the clique graph and fills up the /// bags afterwards trying to speed up filling up by using the tree structure /// -/// FillWhilstMST Fill bags while constructing a spanning tree minimizing according to the edge +/// FillWhilstMST Fills bags while constructing a spanning tree minimizing according to the edge /// heuristic +/// +/// FillWhilstMSTAndLogBagSize Does the same computation as FillWhilstMST however tracks the size of the +/// biggest bag every time a new vertex is added to the current spanning tree. The file +/// k-tree-benchmarks/benchmark_results/k_tree_maximum_bag_size_over_time.csv (where k-tree-benchmarks +/// is a subdirectory of the runtime directory) otherwise this option will panic. /// /// FillWhilstMSTEdgeUpdate Fill bags while constructing a spanning tree minimizing according to /// the edge heuristic. Updating adjacencies in clique graph according to bag updates @@ -35,6 +40,7 @@ pub enum SpanningTreeConstructionMethod { MSTAndFill, MSTAndUseTreeStructure, FillWhilstMST, + FillWhilstMSTAndLogBagSize, FillWhilstMSTEdgeUpdate, FillWhilstMSTTree, FillWhilstMSTBagSize, @@ -175,6 +181,24 @@ pub fn compute_treewidth_upper_bound< &clique_graph, edge_weight_function, clique_graph_map, + false, + ); + + (clique_graph_tree, None, None, None, clique_graph) + } + SpanningTreeConstructionMethod::FillWhilstMSTAndLogBagSize => { + let (clique_graph, clique_graph_map) = + construct_clique_graph_with_bags(cliques, edge_weight_function); + + let clique_graph_tree: Graph< + std::collections::HashSet, + O, + petgraph::prelude::Undirected, + > = fill_bags_while_generating_mst::( + &clique_graph, + edge_weight_function, + clique_graph_map, + true, ); (clique_graph_tree, None, None, None, clique_graph) diff --git a/src/fill_bags_while_generating_mst.rs b/src/fill_bags_while_generating_mst.rs index 5d3f866..f6c2b49 100644 --- a/src/fill_bags_while_generating_mst.rs +++ b/src/fill_bags_while_generating_mst.rs @@ -1,5 +1,7 @@ +use csv::WriterBuilder; use log::trace; use petgraph::{graph::NodeIndex, Graph, Undirected}; +use std::fs::File; use std::{ collections::{HashMap, HashSet}, hash::BuildHasher, @@ -11,11 +13,22 @@ use std::{ /// prim's algorithm and the edge labels in the clique graph as edge weights. Whenever a new vertex /// is added to the spanning tree, the bags of the current spanning tree are filled up/updated /// according to the [tree decomposition criteria][https://en.wikipedia.org/wiki/Tree_decomposition#Definition]. +/// +/// **Panics** +/// The log_bag_size parameter enables logging of the increase in size of the biggest bag of the spanning +/// tree over time while the spanning tree is constructed (i.e. for each new vertex added to the spanning +/// tree, logs the current size of the biggest bag). If log_bag_size == true the file +/// k-tree-benchmarks/benchmark_results/k_tree_maximum_bag_size_over_time.csv (where k-tree-benchmarks +/// is a subdirectory of the runtime directory) has to exist otherwise this function will panic. pub fn fill_bags_while_generating_mst( clique_graph: &Graph, O, Undirected>, edge_weight_heuristic: fn(&HashSet, &HashSet) -> O, clique_graph_map: HashMap, S>, + log_bag_size: bool, ) -> Graph, O, Undirected> { + // For logging the size of the maximum bags. Stays empty if log_bag_size == False + let mut vector_for_logging = Vec::new(); + let mut result_graph: Graph, O, Undirected> = Graph::new_undirected(); // Maps the vertex indices from the clique graph to the corresponding vertex indices in the result graph let mut node_index_map: HashMap = Default::default(); @@ -45,29 +58,16 @@ pub fn fill_bags_while_generating_mst