1
use std::cell::RefCell;
2
use std::fmt::Debug;
3
use std::sync::{Arc, RwLock};
4

            
5
use derivative::Derivative;
6
use serde::{Deserialize, Serialize};
7
use serde_with::serde_as;
8

            
9
use crate::ast::{DecisionVariable, Domain, Expression, Name, SymbolTable};
10
use crate::context::Context;
11
use crate::metadata::Metadata;
12

            
13
#[serde_as]
14
#[derive(Derivative, Clone, Debug, Serialize, Deserialize)]
15
#[derivative(PartialEq, Eq)]
16
pub struct Model {
17
    #[serde_as(as = "Vec<(_, _)>")]
18
    pub variables: SymbolTable,
19
    pub constraints: Expression,
20
    #[serde(skip)]
21
    #[derivative(PartialEq = "ignore")]
22
    pub context: Arc<RwLock<Context<'static>>>,
23
    next_var: RefCell<i32>,
24
}
25

            
26
impl Model {
27
    pub fn new(
28
        variables: SymbolTable,
29
        constraints: Expression,
30
        context: Arc<RwLock<Context<'static>>>,
31
    ) -> Model {
32
        Model {
33
            variables,
34
            constraints,
35
            context,
36
            next_var: RefCell::new(0),
37
        }
38
    }
39

            
40
    pub fn new_empty(context: Arc<RwLock<Context<'static>>>) -> Model {
41
        Model::new(Default::default(), Expression::Nothing, context)
42
    }
43
    // Function to update a DecisionVariable based on its Name
44
    pub fn update_domain(&mut self, name: &Name, new_domain: Domain) {
45
        if let Some(decision_var) = self.variables.get_mut(name) {
46
            decision_var.domain = new_domain;
47
        }
48
    }
49

            
50
    pub fn get_domain(&self, name: &Name) -> Option<&Domain> {
51
        self.variables.get(name).map(|v| &v.domain)
52
    }
53

            
54
    // Function to add a new DecisionVariable to the Model
55
    pub fn add_variable(&mut self, name: Name, decision_var: DecisionVariable) {
56
        self.variables.insert(name, decision_var);
57
    }
58

            
59
    pub fn get_constraints_vec(&self) -> Vec<Expression> {
60
        match &self.constraints {
61
            Expression::And(_, constraints) => constraints.clone(),
62
            Expression::Nothing => vec![],
63
            _ => vec![self.constraints.clone()],
64
        }
65
    }
66

            
67
    pub fn set_constraints(&mut self, constraints: Vec<Expression>) {
68
        if constraints.is_empty() {
69
            self.constraints = Expression::Nothing;
70
        } else if constraints.len() == 1 {
71
            self.constraints = constraints[0].clone();
72
        } else {
73
            self.constraints = Expression::And(Metadata::new(), constraints);
74
        }
75
    }
76

            
77
    pub fn set_context(&mut self, context: Arc<RwLock<Context<'static>>>) {
78
        self.context = context;
79
    }
80

            
81
    pub fn add_constraint(&mut self, expression: Expression) {
82
        // ToDo (gs248) - there is no checking whatsoever
83
        // We need to properly validate the expression but this is just for testing
84
        let mut constraints = self.get_constraints_vec();
85
        constraints.push(expression);
86
        self.set_constraints(constraints);
87
    }
88

            
89
    pub fn add_constraints(&mut self, expressions: Vec<Expression>) {
90
        let mut constraints = self.get_constraints_vec();
91
        constraints.extend(expressions);
92
        self.set_constraints(constraints);
93
    }
94

            
95
    /// Returns an arbitrary variable name that is not in the model.
96
    pub fn gensym(&self) -> Name {
97
        let num = *self.next_var.borrow();
98
        *(self.next_var.borrow_mut()) += 1;
99
        Name::MachineName(num) // incremented when inserted
100
    }
101
}