Skip to content

Commit

Permalink
Fixed fill_bags_while_generating_mst
Browse files Browse the repository at this point in the history
  • Loading branch information
RaoulLuque committed May 10, 2024
1 parent 29c6c0d commit 47b9f11
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 124 deletions.
11 changes: 8 additions & 3 deletions dimacs_benchmarks/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ use std::io::Write;

use petgraph::Graph;
use std::time::SystemTime;
use treewidth_heuristic::compute_treewidth_upper_bound_not_connected;
use treewidth_heuristic::{
compute_treewidth_upper_bound_not_connected, TreewidthComputationMethod,
};

fn main() {
env_logger::init();

let computation_type: TreewidthComputationMethod = TreewidthComputationMethod::FillWhilstMST;
let heuristic = treewidth_heuristic::least_difference_heuristic;

// Opening and writing to log file
let mut benchmark_log_file =
File::create("dimacs_benchmarks/benchmark_results/dimacs_results.txt")
Expand All @@ -33,8 +38,8 @@ fn main() {
let start = SystemTime::now();
let computed_treewidth = compute_treewidth_upper_bound_not_connected(
&graph,
treewidth_heuristic::negative_intersection_heuristic,
false,
heuristic,
computation_type,
false,
);

Expand Down
77 changes: 43 additions & 34 deletions k_tree_benchmarks/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ use petgraph::dot::{Config, Dot};
use petgraph::graph::NodeIndex;
use petgraph::Graph;
use std::time::SystemTime;
use treewidth_heuristic::compute_treewidth_upper_bound;
use treewidth_heuristic::{compute_treewidth_upper_bound, TreewidthComputationMethod};

fn main() {
let k = 3;
let n = 10;
let p = 5;
let k = 10;
let n = 100;
let p = 10;
let edge_heuristic = treewidth_heuristic::least_difference_heuristic;
let number_of_trees = 100;
let computation_type = TreewidthComputationMethod::FillWhilstMST;

let mut sum_of_treewidths_predecessors = 0;
let mut sum_of_treewidths_no_predecessors = 0;
Expand Down Expand Up @@ -43,16 +44,22 @@ fn main() {
_,
_,
computed_treewidth,
) = compute_treewidth_upper_bound(&graph, edge_heuristic, true, true);
) = compute_treewidth_upper_bound(&graph, edge_heuristic, computation_type, true);

// DEBUG
let (
clique_graph_alt,
clique_graph_tree_after_filling_up_alt,
clique_graph_tree_before_filling_up_alt,
_,
_,
computed_treewidth_alt,
) = compute_treewidth_upper_bound(&graph, edge_heuristic, false, true);
) = compute_treewidth_upper_bound(
&graph,
edge_heuristic,
TreewidthComputationMethod::MSTAndFill,
true,
);

// DEBUG
// assert!(petgraph::algo::is_isomorphic_matching(
Expand Down Expand Up @@ -102,6 +109,7 @@ fn main() {
"",
);

// DEBUG
// create_dot_files(
// &graph,
// &clique_graph_alt,
Expand Down Expand Up @@ -133,27 +141,44 @@ fn create_dot_files(
i32,
petgraph::prelude::Undirected,
>,
clique_graph_tree_before_filling_up: &Graph<
HashSet<NodeIndex>,
i32,
petgraph::prelude::Undirected,
clique_graph_tree_before_filling_up: &Option<
Graph<HashSet<NodeIndex>, i32, petgraph::prelude::Undirected>,
>,
i: usize,
name: &str,
) {
fs::create_dir_all("k_tree_benchmarks/benchmark_results/visualizations")
.expect("Could not create directory for visualizations");

let start_graph_dot_file = Dot::with_config(graph, &[Config::EdgeNoLabel]);
let result_graph_dot_file =
Dot::with_config(clique_graph_tree_after_filling_up, &[Config::EdgeNoLabel]);
let clique_graph_dot_file = Dot::with_config(&clique_graph, &[Config::EdgeNoLabel]);
let clique_graph_tree_before_filling_up_dot_file =
Dot::with_config(clique_graph_tree_before_filling_up, &[Config::EdgeNoLabel]);
let clique_graph_node_indices = Dot::with_config(
clique_graph_tree_before_filling_up,
&[Config::EdgeNoLabel, Config::NodeIndexLabel],
);

fs::create_dir_all("k_tree_benchmarks/benchmark_results/visualizations")
.expect("Could not create directory for visualizations");
if let Some(clique_graph_tree_before_filling_up) = clique_graph_tree_before_filling_up {
let clique_graph_tree_before_filling_up_dot_file =
Dot::with_config(clique_graph_tree_before_filling_up, &[Config::EdgeNoLabel]);
let clique_graph_node_indices = Dot::with_config(
clique_graph_tree_before_filling_up,
&[Config::EdgeNoLabel, Config::NodeIndexLabel],
);

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_result_graph_before_filling_{}.dot",
i, name
))
.expect("Result graph without filling up file could not be created");
write!(&mut w, "{:?}", clique_graph_tree_before_filling_up_dot_file)
.expect("Unable to write dotfile for result graph without filling up to files");

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_result_graph_node_indices_{}.dot",
i, name
))
.expect("Clique graph node indices file could not be created");
write!(&mut w, "{:?}", clique_graph_node_indices)
.expect("Unable to write dotfile for Clique graph node indices to files");
}

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_starting_graph_{}.dot",
Expand All @@ -171,22 +196,6 @@ fn create_dot_files(
write!(&mut w, "{:?}", clique_graph_dot_file)
.expect("Unable to write dotfile for start graph to files");

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_result_graph_before_filling_{}.dot",
i, name
))
.expect("Result graph without filling up file could not be created");
write!(&mut w, "{:?}", clique_graph_tree_before_filling_up_dot_file)
.expect("Unable to write dotfile for result graph without filling up to files");

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_result_graph_node_indices_{}.dot",
i, name
))
.expect("Clique graph node indices file could not be created");
write!(&mut w, "{:?}", clique_graph_node_indices)
.expect("Unable to write dotfile for Clique graph node indices to files");

let mut w = fs::File::create(format!(
"k_tree_benchmarks/benchmark_results/visualizations/{}_result_graph_{}.dot",
i, name
Expand Down
172 changes: 100 additions & 72 deletions treewidth_heuristic/src/compute_treewidth_upper_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ use crate::*;
use itertools::Itertools;
use petgraph::{graph::NodeIndex, Graph, Undirected};

#[derive(Clone, Copy)]
pub enum TreewidthComputationMethod {
MSTAndFill,
MSTAndUseTreeStructure,
FillWhilstMST,
}

/// Computes an upper bound for the treewidth using the clique graph operator.
///
/// Can either use the tree structure in the spanning tree to fill up the bags of vertices
Expand All @@ -16,12 +23,12 @@ use petgraph::{graph::NodeIndex, Graph, Undirected};
pub fn compute_treewidth_upper_bound<N: Clone, E: Clone>(
graph: &Graph<N, E, Undirected>,
edge_weight_heuristic: fn(&HashSet<NodeIndex>, &HashSet<NodeIndex>) -> i32,
use_predecessor_map_to_fill_bags: bool,
use_predecessor_map_to_fill_bags: TreewidthComputationMethod,
check_tree_decomposition_bool: bool,
) -> (
Graph<HashSet<NodeIndex>, i32, Undirected>,
Graph<HashSet<NodeIndex>, i32, Undirected>,
Graph<HashSet<NodeIndex>, i32, Undirected>,
Option<Graph<HashSet<NodeIndex>, i32, Undirected>>,
Option<HashMap<NodeIndex, (NodeIndex, usize)>>,
Option<HashMap<NodeIndex, HashSet<NodeIndex>>>,
usize,
Expand All @@ -35,73 +42,94 @@ pub fn compute_treewidth_upper_bound<N: Clone, E: Clone>(
predecessor_map,
clique_graph_tree_before_filling,
clique_graph,
) = if use_predecessor_map_to_fill_bags {
let (clique_graph, clique_graph_map) =
construct_clique_graph_with_bags(cliques, edge_weight_heuristic);
// DEBUG
// println!("Initial clique graph: {:?}", clique_graph);

let mut clique_graph_tree: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
let clique_graph_tree_before_filling = clique_graph_tree.clone();

// DEBUG
let mut clique_graph_tree_copy: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
assert!(petgraph::algo::is_isomorphic_matching(
&clique_graph_tree,
&clique_graph_tree_copy,
|a, b| a.eq(b),
|a, b| a.eq(b)
));

let predecessor_map =
fill_bags_along_paths_using_structure(&mut clique_graph_tree, &clique_graph_map);
// DEBUG
// println!(
// "Clique graph tree after filling up: {:?} \n \n",
// clique_graph_tree
// );

(
clique_graph_tree,
Some(clique_graph_map),
Some(predecessor_map),
clique_graph_tree_before_filling,
clique_graph,
)
} else {
let clique_graph: Graph<_, _, _> = construct_clique_graph(cliques, edge_weight_heuristic);

let mut clique_graph_tree: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
let clique_graph_tree_before_filling = clique_graph_tree.clone();

fill_bags_along_paths(&mut clique_graph_tree);
) = match use_predecessor_map_to_fill_bags {
TreewidthComputationMethod::MSTAndUseTreeStructure => {
let (clique_graph, clique_graph_map) =
construct_clique_graph_with_bags(cliques, edge_weight_heuristic);
// DEBUG
// println!("Initial clique graph: {:?}", clique_graph);

let mut clique_graph_tree: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
let clique_graph_tree_before_filling = clique_graph_tree.clone();

// DEBUG
let mut clique_graph_tree_copy: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
assert!(petgraph::algo::is_isomorphic_matching(
&clique_graph_tree,
&clique_graph_tree_copy,
|a, b| a.eq(b),
|a, b| a.eq(b)
));

let predecessor_map =
fill_bags_along_paths_using_structure(&mut clique_graph_tree, &clique_graph_map);
// DEBUG
// println!(
// "Clique graph tree after filling up: {:?} \n \n",
// clique_graph_tree
// );

(
clique_graph_tree,
Some(clique_graph_map),
Some(predecessor_map),
Some(clique_graph_tree_before_filling),
clique_graph,
)
}
TreewidthComputationMethod::MSTAndFill => {
let clique_graph: Graph<_, _, _> =
construct_clique_graph(cliques, edge_weight_heuristic);

let mut clique_graph_tree: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = petgraph::data::FromElements::from_elements(petgraph::algo::min_spanning_tree(
&clique_graph,
));
let clique_graph_tree_before_filling = clique_graph_tree.clone();

fill_bags_along_paths(&mut clique_graph_tree);

(
clique_graph_tree,
None,
None,
Some(clique_graph_tree_before_filling),
clique_graph,
)
}
TreewidthComputationMethod::FillWhilstMST => {
let (clique_graph, clique_graph_map) =
construct_clique_graph_with_bags(cliques, edge_weight_heuristic);

let clique_graph_tree: Graph<
std::collections::HashSet<petgraph::prelude::NodeIndex>,
i32,
petgraph::prelude::Undirected,
> = fill_bags_while_generating_mst::<N, E>(
&clique_graph,
edge_weight_heuristic,
clique_graph_map,
);

(
clique_graph_tree,
None,
None,
clique_graph_tree_before_filling,
clique_graph,
)
(clique_graph_tree, None, None, None, clique_graph)
}
};

if check_tree_decomposition_bool {
assert!(check_tree_decomposition(
&graph,
Expand All @@ -127,7 +155,7 @@ pub fn compute_treewidth_upper_bound<N: Clone, E: Clone>(
pub fn compute_treewidth_upper_bound_not_connected<N: Clone, E: Clone>(
graph: &Graph<N, E, Undirected>,
edge_weight_heuristic: fn(&HashSet<NodeIndex>, &HashSet<NodeIndex>) -> i32,
use_predecessor_map_to_fill_bags: bool,
use_predecessor_map_to_fill_bags: TreewidthComputationMethod,
check_tree_decomposition_bool: bool,
) -> usize {
let components = find_connected_components::<Vec<_>, _, _>(graph);
Expand Down Expand Up @@ -163,14 +191,14 @@ mod tests {
let _ = compute_treewidth_upper_bound_not_connected(
&test_graph.graph,
neutral_heuristic,
true,
TreewidthComputationMethod::MSTAndUseTreeStructure,
true,
);

let _ = compute_treewidth_upper_bound_not_connected(
&test_graph.graph,
neutral_heuristic,
false,
TreewidthComputationMethod::MSTAndFill,
true,
);
}
Expand All @@ -183,15 +211,15 @@ mod tests {
let computed_treewidth = compute_treewidth_upper_bound_not_connected(
&test_graph.graph,
neutral_heuristic,
true,
TreewidthComputationMethod::MSTAndUseTreeStructure,
false,
);
assert_eq!(computed_treewidth, test_graph.treewidth);

let computed_treewidth = compute_treewidth_upper_bound_not_connected(
&test_graph.graph,
neutral_heuristic,
false,
TreewidthComputationMethod::MSTAndFill,
false,
);
assert_eq!(computed_treewidth, test_graph.treewidth);
Expand Down
Loading

0 comments on commit 47b9f11

Please sign in to comment.