use graph_gen::{ErModel, Graph, Max2SatGraph, Generatable};
use structopt::StructOpt;
use crate::Output::Dimacs;
use std::str::FromStr;
#[derive(StructOpt)]
struct Args {
#[structopt(name="nb_vertices", short, long)]
n: usize,
#[structopt(name="probability", short, long)]
p: f64,
#[structopt(name="loops", short, long)]
loops: bool,
#[structopt(name="digraph", short, long)]
digraph: bool,
#[structopt(name="max2sat", short, long)]
max2sat: bool,
#[structopt(name="output", short, long)]
output : Option<Output>,
#[structopt(name="weights", short, long)]
weights: Option<Vec<isize>>
}
enum Output {
Dimacs, GraphViz
}
impl Default for Output {
fn default() -> Self {
Dimacs
}
}
impl FromStr for Output {
type Err = String;
fn from_str(txt: &str) -> Result<Output, String> {
if &txt.to_lowercase() == "dimacs" {
return Ok(Output::Dimacs);
}
if &txt.to_lowercase() == "graphviz" {
return Ok(Output::GraphViz);
}
if &txt.to_lowercase() == "dot" {
return Ok(Output::GraphViz);
}
Err(txt.to_owned())
}
}
impl Args {
fn graph(&self) -> Graph {
let n = if self.max2sat { 2 * self.n } else { self.n };
let mut model = ErModel::new(n, self.p);
if self.digraph {
model = model.digraph();
}
if self.loops {
model = model.with_self_loops();
}
let mut graph = model.generator().gen();
if let Some(weights) = self.weights.as_ref() {
graph.pluck_random_weights(weights);
}
graph
}
fn wcnf(&self, g: Graph) -> Max2SatGraph {
Max2SatGraph::new(g)
}
fn generatable(&self) -> Generatable {
let graph = self.graph();
if self.max2sat {
Generatable::GenSat {s : self.wcnf(graph)}
} else {
Generatable::GenGraph {g : graph}
}
}
fn output(&self, g: &Generatable) -> String {
match &self.output {
None => g.to_dimacs(),
Some(o) => match o {
Output::Dimacs => g.to_dimacs(),
Output::GraphViz => g.to_dot()
}
}
}
}
fn main() {
let args = Args::from_args();
let graph= args.generatable();
let out = args.output(&graph);
println!("{}", out);
}