1
use core::panic;
2
use std::{
3
    collections::HashMap,
4
    env::{Vars, vars},
5
    io::Lines,
6
};
7

            
8
use rustsat::{
9
    clause,
10
    instances::{BasicVarManager, Cnf, SatInstance},
11
    solvers::{Solve, SolverResult},
12
    types::{Clause, Lit, TernaryVal},
13
};
14

            
15
use rustsat_minisat::core::Minisat;
16

            
17
use anyhow::{Result, anyhow};
18

            
19
use crate::{
20
    ast::{CnfClause, Expression, Moo, Name},
21
    bug,
22
    solver::Error,
23
};
24

            
25
pub fn handle_lit(
26
    l1: &Expression,
27
    vars_added: &mut HashMap<Name, Lit>,
28
    inst: &mut SatInstance,
29
) -> Lit {
30
    match l1 {
31
        // simple literal
32
        // TODO (ss504) check what can be done to avoid cloning
33
        Expression::Atomic(_, _) => handle_atom(l1.clone(), true, vars_added, inst),
34
        // not literal
35
        Expression::Not(_, _) => handle_not(l1, vars_added, inst),
36

            
37
        _ => bug!("Literal expected"),
38
    }
39
}
40

            
41
pub fn handle_not(
42
    expr: &Expression,
43
    vars_added: &mut HashMap<Name, Lit>,
44
    inst: &mut SatInstance,
45
) -> Lit {
46
    match expr {
47
        Expression::Not(_, ref_a) => {
48
            let ref_a = Moo::clone(ref_a);
49
            let a = Moo::unwrap_or_clone(ref_a);
50
            handle_atom(a, false, vars_added, inst)
51
        }
52
        _ => bug!("Not Expression Expected"),
53
    }
54
}
55

            
56
pub fn handle_atom(
57
    a: Expression,
58
    polarity: bool,
59
    vars_added: &mut HashMap<Name, Lit>,
60
    inst: &mut SatInstance,
61
) -> Lit {
62
    // polarity false for not
63
    match a {
64
        Expression::Atomic(_, atom) => match atom {
65
            conjure_cp_core::ast::Atom::Literal(literal) => {
66
                todo!("Not Sure if we are handling Lits as-is or not..")
67
            }
68
            conjure_cp_core::ast::Atom::Reference(reference) => match &*(reference.name()) {
69
                conjure_cp_core::ast::Name::User(_)
70
                | conjure_cp_core::ast::Name::Represented(_)
71
                | conjure_cp_core::ast::Name::Machine(_) => {
72
                    // TODO: Temp Clone
73
                    // let m = n.clone();
74
                    let lit_temp: Lit = fetch_lit(reference.name().clone(), vars_added, inst);
75
                    if polarity { lit_temp } else { !lit_temp }
76
                }
77
                _ => todo!("Not implemented yet"),
78
            },
79
        },
80
        _ => bug!("atomic expected"),
81
    }
82
}
83

            
84
pub fn fetch_lit(name: Name, vars_added: &mut HashMap<Name, Lit>, inst: &mut SatInstance) -> Lit {
85
    if !vars_added.contains_key(&name) {
86
        vars_added.insert(name.clone(), inst.new_lit());
87
    }
88
    *(vars_added
89
        .get(&name)
90
        .unwrap_or_else(|| bug!("Literal could not be fetched")))
91
}
92

            
93
pub fn handle_disjn(
94
    disjn: &CnfClause,
95
    vars_added: &mut HashMap<Name, Lit>,
96
    inst_in_use: &mut SatInstance,
97
) {
98
    let mut lits = Clause::new();
99

            
100
    for literal in disjn.iter() {
101
        let lit: Lit = handle_lit(literal, vars_added, inst_in_use);
102
        lits.add(lit);
103
    }
104

            
105
    inst_in_use.add_clause(lits);
106
}
107

            
108
pub fn handle_cnf(
109
    vec_cnf: &Vec<CnfClause>,
110
    vars_added: &mut HashMap<Name, Lit>,
111
    finds: Vec<Name>,
112
) -> SatInstance {
113
    let mut inst = SatInstance::new();
114

            
115
    tracing::info!("{:?} are all the decision vars found.", finds);
116

            
117
    for name in finds {
118
        vars_added.insert(name, inst.new_lit());
119
    }
120

            
121
    for disjn in vec_cnf {
122
        handle_disjn(disjn, vars_added, &mut inst);
123
    }
124

            
125
    inst
126
}
127

            
128
// Error reserved for future use
129
// TODO: Integrate or remove
130
#[derive(Error, Debug)]
131
pub enum CNFError {
132
    #[error("Variable with name `{0}` not found")]
133
    VariableNameNotFound(String),
134

            
135
    #[error("Variable with name `{0}` not of right type")]
136
    BadVariableType(String),
137

            
138
    #[error("Unexpected Expression `{0}` inside Not(). Only Not(Reference) or Not(Not) allowed!")]
139
    UnexpectedExpressionInsideNot(Expression),
140

            
141
    #[error("Unexpected Expression `{0}` as literal. Only Not() or Reference() allowed!")]
142
    UnexpectedLiteralExpression(Expression),
143

            
144
    #[error("Unexpected Expression `{0}` inside And(). Only And(vec<Or>) allowed!")]
145
    UnexpectedExpressionInsideAnd(Expression),
146

            
147
    #[error("Unexpected Expression `{0}` inside Or(). Only Or(lit, lit) allowed!")]
148
    UnexpectedExpressionInsideOr(Expression),
149

            
150
    #[error("Unexpected Expression `{0}` found!")]
151
    UnexpectedExpression(Expression),
152
}