Skip to content

Commit

Permalink
Merge pull request #49 from timbeurskens/feature/updated-graph-generator
Browse files Browse the repository at this point in the history
Updated graph generator
  • Loading branch information
timbeurskens authored Jul 20, 2023
2 parents 2caf492 + 8e112c4 commit a656c77
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 55 deletions.
106 changes: 105 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ rustc-hash.workspace = true
clap.workspace = true
csv.workspace = true
regex.workspace = true
rayon.workspace = true
argfile.workspace = true
wild.workspace = true

Expand All @@ -40,5 +41,7 @@ csv = "1.2"
regex = "1.7"
glob = "0.3"
pretty_assertions = "1.3"
anyhow = "1.0"
rayon = "1.7"
argfile = "0.1"
wild = "2.1"
5 changes: 3 additions & 2 deletions random_graph_gen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "random_graph_gen"
version = "0.1.0"
version = "0.2.0"
description = "Generates a random edge list formatted graph"
edition.workspace = true
authors.workspace = true
Expand All @@ -9,4 +9,5 @@ authors.workspace = true
clap.workspace = true
rand.workspace = true
rustc-hash.workspace = true
csv.workspace = true
csv.workspace = true
anyhow.workspace = true
99 changes: 72 additions & 27 deletions random_graph_gen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ struct Args {
/// Use undirected edges (test for both directions in the set-complement operation)
undirected: bool,

#[clap(long)]
/// Construct a complete graph
complete: bool,

#[clap(short, long)]
/// Output in dot (GraphViz) format
dot: bool,
Expand All @@ -39,23 +43,41 @@ struct Args {
colors: Option<usize>,
}

fn main() -> io::Result<()> {
fn main() -> anyhow::Result<()> {
let args = Args::parse();

let mut selection = if let Some(file_to_convert) = args.convert {
let file = File::open(file_to_convert).expect("Could not open file");
let file = File::open(file_to_convert)?;
let mut bufreader = BufReader::new(file);
read_graph(&mut bufreader, args.undirected).expect("Could not parse edge list")
read_graph(&mut bufreader, args.undirected)?
} else if args.complete {
if args.vertices.is_none() {
Err(anyhow::anyhow!(
"Must provide vertices for a complete graph"
))?
}

let vertices = args.vertices.unwrap();

let edges = if args.undirected {
(vertices * (vertices - 1)) / 2
} else {
vertices * (vertices - 1)
};

generate_graph(vertices, edges, args.undirected)?
} else {
if args.vertices.is_none() || args.edges.is_none() {
panic!("Must provide vertices and edges if not converting a graph");
Err(anyhow::anyhow!(
"Must provide vertices and edges if not converting a graph"
))?
}
generate_graph(args.vertices.unwrap(), args.edges.unwrap(), args.undirected)
generate_graph(args.vertices.unwrap(), args.edges.unwrap(), args.undirected)?
};

// convert to a graph-coloring problem
if let Some(num_colors) = args.colors {
selection = augment_colors(&selection, num_colors);
selection = augment_colors(&selection, num_colors)?;
}

let mut writer = if let Some(output_file) = args.output {
Expand Down Expand Up @@ -86,7 +108,7 @@ fn main() -> io::Result<()> {
}

// flush the writer before dropping it
writer.flush().expect("Could not flush write buffer");
writer.flush()?;

Ok(())
}
Expand Down Expand Up @@ -115,7 +137,7 @@ fn generate_graph(
num_vertices: usize,
num_edges: usize,
undirected: bool,
) -> Vec<(String, String)> {
) -> anyhow::Result<Vec<(String, String)>> {
let mut rng = rand::thread_rng();

let vertices = (0..num_vertices)
Expand All @@ -125,8 +147,15 @@ fn generate_graph(

for (i, v1) in vertices.iter().enumerate() {
if undirected {
for v2 in vertices[(i + 1)..].iter() {
edges.push((v1.clone(), v2.clone()));
if let Some(vertices) = vertices.get((i + 1)..) {
for v2 in vertices.iter() {
edges.push((v1.clone(), v2.clone()));
}
} else {
Err(anyhow::anyhow!(
"Index out of bounds for vertex range {}..",
i + 1
))?
}
} else {
for (j, v2) in vertices.iter().enumerate() {
Expand All @@ -139,10 +168,19 @@ fn generate_graph(

edges.shuffle(&mut rng);

edges[0..num_edges].to_vec()
if let Some(edges) = edges.get(0..num_edges) {
Ok(edges.to_vec())
} else {
Err(anyhow::anyhow!(
"Cannot satisfy the desired amount of edges"
))
}
}

fn augment_colors(edges: &Vec<(String, String)>, num_colors: usize) -> Vec<(String, String)> {
fn augment_colors(
edges: &Vec<(String, String)>,
num_colors: usize,
) -> anyhow::Result<Vec<(String, String)>> {
let mut vertex_map: FxHashMap<String, String> = FxHashMap::default();
let mut color_map: FxHashMap<String, usize> = FxHashMap::default();

Expand All @@ -164,23 +202,30 @@ fn augment_colors(edges: &Vec<(String, String)>, num_colors: usize) -> Vec<(Stri
let vertices = vertex_map.keys().cloned().collect::<Vec<String>>();

for (i, v1) in vertices.iter().enumerate() {
for v2 in vertices[(i + 1)..].iter() {
let c1 = color_map[v1];
let c2 = color_map[v2];

let ov1 = &vertex_map[v1];
let ov2 = &vertex_map[v2];

// only add an edge to new_edges if the colors are different, or the vertices are not connected
if ov1 != ov2
&& (c1 != c2
|| (!edges.contains(&(ov1.clone(), ov2.clone()))
&& !edges.contains(&(ov2.clone(), ov1.clone()))))
{
new_edges.push((v1.clone(), v2.clone()));
if let Some(vertices) = vertices.get((i + 1)..) {
for v2 in vertices.iter() {
let c1 = color_map[v1];
let c2 = color_map[v2];

let ov1 = &vertex_map[v1];
let ov2 = &vertex_map[v2];

// only add an edge to new_edges if the colors are different, or the vertices are not connected
if ov1 != ov2
&& (c1 != c2
|| (!edges.contains(&(ov1.clone(), ov2.clone()))
&& !edges.contains(&(ov2.clone(), ov1.clone()))))
{
new_edges.push((v1.clone(), v2.clone()));
}
}
} else {
Err(anyhow::anyhow!(
"Index out of bounds for vertex range {}..",
i + 1
))?
}
}

new_edges
Ok(new_edges)
}
Loading

0 comments on commit a656c77

Please sign in to comment.