Explorar el Código

put parse_dimac into a module

still in the same file, though.
Lucas Stadler %!s(int64=10) %!d(string=hace) años
padre
commit
d36ec472e2
Se han modificado 1 ficheros con 63 adiciones y 61 borrados
  1. 63 61
      rust/dpll/cnf.rs

+ 63 - 61
rust/dpll/cnf.rs

@ -10,79 +10,81 @@
10 10
use std::io;
11 11
use std::io::Read;
12 12
13
struct CNF {
14
    num_vars: u32,
15
    num_clauses: u32,
16
    clauses: Vec<Vec<i32>>
17
}
13
mod cnf {
14
    pub struct CNF {
15
        pub num_vars: u32,
16
        pub num_clauses: u32,
17
        pub clauses: Vec<Vec<i32>>
18
    }
18 19
19
/// Parses a CNF formula in DIMAC format.
20
///
21
/// # Examples
22
///
23
/// A simple example for a formula in DIMAC format is below:
24
///
25
/// ```text
26
/// p cnf 5 3
27
/// 1 2 3 0
28
/// -2 3 4 0
29
/// 4 5 0
30
/// ```
31
///
32
/// The above represents a formula with 5 variables and 3 clauses.  The first
33
/// line specifies this.  Each following line represents a clause with possibly
34
/// negated literals, terminated by 0 and a newline.
35
fn parse_dimac(dimac: &str) -> Result<CNF, String> {
36
    let mut lines = dimac.lines();
37
    let mut num_vars;
38
    let mut num_clauses;
39
    
40
    match lines.next() {
41
        None => { return Err("expected cnf description".to_string()) }
42
        Some(line) => {
43
            let desc: Vec<&str> = line.split(" ").collect();
44
            if desc.len() != 4 || desc[0] != "p" || desc[1] != "cnf" {
45
                return Err("cnf description must be of the form 'p cnf <num vars> <num clauses>'".to_string())
46
            }
47
            match desc[2].parse::<u32>() {
48
                Ok(n) => { num_vars = n }
49
                Err(e) => { return Err(format!("<num vars> must be a positive integer: {}", e)) }
50
            }
51
            
52
            match desc[3].parse::<u32>() {
53
                Ok(n) => { num_clauses = n }
54
                Err(e) => { return Err(format!("<num clauses> must be a positive integer: {}", e)) }
20
    /// Parses a CNF formula in DIMAC format.
21
    ///
22
    /// # Examples
23
    ///
24
    /// A simple example for a formula in DIMAC format is below:
25
    ///
26
    /// ```text
27
    /// p cnf 5 3
28
    /// 1 2 3 0
29
    /// -2 3 4 0
30
    /// 4 5 0
31
    /// ```
32
    ///
33
    /// The above represents a formula with 5 variables and 3 clauses.  The first
34
    /// line specifies this.  Each following line represents a clause with possibly
35
    /// negated literals, terminated by 0 and a newline.
36
    pub fn parse_dimac(dimac: &str) -> Result<CNF, String> {
37
        let mut lines = dimac.lines();
38
        let mut num_vars;
39
        let mut num_clauses;
40
        
41
        match lines.next() {
42
            None => { return Err("expected cnf description".to_string()) }
43
            Some(line) => {
44
                let desc: Vec<&str> = line.split(" ").collect();
45
                if desc.len() != 4 || desc[0] != "p" || desc[1] != "cnf" {
46
                    return Err("cnf description must be of the form 'p cnf <num vars> <num clauses>'".to_string())
47
                }
48
                match desc[2].parse::<u32>() {
49
                    Ok(n) => { num_vars = n }
50
                    Err(e) => { return Err(format!("<num vars> must be a positive integer: {}", e)) }
51
                }
52
                
53
                match desc[3].parse::<u32>() {
54
                    Ok(n) => { num_clauses = n }
55
                    Err(e) => { return Err(format!("<num clauses> must be a positive integer: {}", e)) }
56
                }
55 57
            }
56 58
        }
57
    }
58 59
59
    let clause_lines: Vec<&str> = lines.collect();
60
    if clause_lines.len() as u32 != num_clauses {
61
        return Err(format!("Wrong number of clauses: Expected {}, but got {}", num_clauses, clause_lines.len()))
62
    }
63
64
    let mut clauses: Vec<Vec<i32>> = Vec::with_capacity(num_clauses as usize);
65
    for clause_line in clause_lines {
66
        let mut vars: Vec<i32> = clause_line.split(" ").map(|x| x.parse::<i32>().unwrap()).collect();
67
        if vars.is_empty() {
68
            return Err("empty clause".to_string())
60
        let clause_lines: Vec<&str> = lines.collect();
61
        if clause_lines.len() as u32 != num_clauses {
62
            return Err(format!("Wrong number of clauses: Expected {}, but got {}", num_clauses, clause_lines.len()))
69 63
        }
70
        if vars[vars.len()-1] != 0 {
71
            return Err("clause must be terminated with 0".to_string())
64
65
        let mut clauses: Vec<Vec<i32>> = Vec::with_capacity(num_clauses as usize);
66
        for clause_line in clause_lines {
67
            let mut vars: Vec<i32> = clause_line.split(" ").map(|x| x.parse::<i32>().unwrap()).collect();
68
            if vars.is_empty() {
69
                return Err("empty clause".to_string())
70
            }
71
            if vars[vars.len()-1] != 0 {
72
                return Err("clause must be terminated with 0".to_string())
73
            }
74
            let l = vars.len();
75
            vars.truncate(l - 1);
76
            clauses.push(vars)
72 77
        }
73
        let l = vars.len();
74
        vars.truncate(l - 1);
75
        clauses.push(vars)
76
    }
77 78
78
    let cnf = CNF { num_vars: num_vars, num_clauses: num_clauses, clauses: clauses };
79
    return Ok(cnf)
79
        let cnf = CNF { num_vars: num_vars, num_clauses: num_clauses, clauses: clauses };
80
        return Ok(cnf)
81
    }
80 82
}
81 83
82 84
fn main() {
83 85
    let input: &mut String = &mut String::new();
84 86
    match io::stdin().read_to_string(input) {
85
        Ok(_) => match parse_dimac(input) {
87
        Ok(_) => match cnf::parse_dimac(input) {
86 88
            Ok(cnf) => {
87 89
                println!("cnf has {} variables and {} clauses", cnf.num_vars, cnf.num_clauses);
88 90
                for clause in cnf.clauses {