1
//! Types used for representing Minion models in Rust.
2

            
3
use std::collections::HashMap;
4

            
5
pub type VarName = String;
6
pub type Tuple = (Constant, Constant);
7
pub type TwoVars = (Var, Var);
8

            
9
/// A Minion model.
10
#[non_exhaustive]
11
#[derive(Debug, Clone, PartialEq, Eq)]
12
pub struct Model {
13
    pub named_variables: SymbolTable,
14
    pub constraints: Vec<Constraint>,
15
}
16

            
17
impl Model {
18
    /// Creates an empty Minion model.
19
1344
    pub fn new() -> Model {
20
1344
        Model {
21
1344
            named_variables: SymbolTable::new(),
22
1344
            constraints: Vec::new(),
23
1344
        }
24
1344
    }
25
}
26

            
27
impl Default for Model {
28
    fn default() -> Self {
29
        Self::new()
30
    }
31
}
32

            
33
/// All supported Minion constraints.
34
#[non_exhaustive]
35
#[derive(Debug, Clone, PartialEq, Eq)]
36
pub enum Constraint {
37
    Difference(TwoVars, Var),
38
    Div(TwoVars, Var),
39
    DivUndefZero(TwoVars, Var),
40
    Modulo(TwoVars, Var),
41
    ModuloUndefZero(TwoVars, Var),
42
    Pow(TwoVars, Var),
43
    Product(TwoVars, Var),
44
    WeightedSumGeq(Vec<Constant>, Vec<Var>, Var),
45
    WeightedSumLeq(Vec<Constant>, Vec<Var>, Var),
46
    CheckAssign(Box<Constraint>),
47
    CheckGsa(Box<Constraint>),
48
    ForwardChecking(Box<Constraint>),
49
    Reify(Box<Constraint>, Var),
50
    ReifyImply(Box<Constraint>, Var),
51
    ReifyImplyQuick(Box<Constraint>, Var),
52
    WatchedAnd(Vec<Constraint>),
53
    WatchedOr(Vec<Constraint>),
54
    GacAllDiff(Vec<Var>),
55
    AllDiff(Vec<Var>),
56
    AllDiffMatrix(Vec<Var>, Constant),
57
    WatchSumGeq(Vec<Var>, Constant),
58
    WatchSumLeq(Vec<Var>, Constant),
59
    OccurrenceGeq(Vec<Var>, Constant, Constant),
60
    OccurrenceLeq(Vec<Var>, Constant, Constant),
61
    Occurrence(Vec<Var>, Constant, Var),
62
    LitSumGeq(Vec<Var>, Vec<Constant>, Constant),
63
    Gcc(Vec<Var>, Vec<Constant>, Vec<Var>),
64
    GccWeak(Vec<Var>, Vec<Constant>, Vec<Var>),
65
    LexLeqRv(Vec<Var>, Vec<Var>),
66
    LexLeq(Vec<Var>, Vec<Var>),
67
    LexLess(Vec<Var>, Vec<Var>),
68
    LexLeqQuick(Vec<Var>, Vec<Var>),
69
    LexLessQuick(Vec<Var>, Vec<Var>),
70
    WatchVecNeq(Vec<Var>, Vec<Var>),
71
    WatchVecExistsLess(Vec<Var>, Vec<Var>),
72
    Hamming(Vec<Var>, Vec<Var>, Constant),
73
    NotHamming(Vec<Var>, Vec<Var>, Constant),
74
    FrameUpdate(Vec<Var>, Vec<Var>, Vec<Var>, Vec<Var>, Constant),
75
    //HaggisGac(Vec<Var>,Vec<
76
    //HaggisGacStable
77
    //ShortStr2
78
    //ShortcTupleStr2
79
    NegativeTable(Vec<Var>, Vec<Tuple>),
80
    Table(Vec<Var>, Vec<Tuple>),
81
    GacSchema(Vec<Var>, Vec<Tuple>),
82
    LightTable(Vec<Var>, Vec<Tuple>),
83
    Mddc(Vec<Var>, Vec<Tuple>),
84
    NegativeMddc(Vec<Var>, Vec<Tuple>),
85
    Str2Plus(Vec<Var>, Var),
86
    Max(Vec<Var>, Var),
87
    Min(Vec<Var>, Var),
88
    NvalueGeq(Vec<Var>, Var),
89
    NvalueLeq(Vec<Var>, Var),
90
    SumLeq(Vec<Var>, Var),
91
    SumGeq(Vec<Var>, Var),
92
    Element(Vec<Var>, Var, Var),
93
    ElementOne(Vec<Var>, Var, Var),
94
    ElementUndefZero(Vec<Var>, Var, Var),
95
    WatchElement(Vec<Var>, Var, Var),
96
    WatchElementOne(Vec<Var>, Var, Var),
97
    WatchElementOneUndefZero(Vec<Var>, Var, Var),
98
    WatchElementUndefZero(Vec<Var>, Var, Var),
99
    WLiteral(Var, Constant),
100
    WNotLiteral(Var, Constant),
101
    WInIntervalSet(Var, Vec<Constant>),
102
    WInRange(Var, Vec<Constant>),
103
    WInset(Var, Vec<Constant>),
104
    WNotInRange(Var, Vec<Constant>),
105
    WNotInset(Var, Vec<Constant>),
106
    Abs(Var, Var),
107
    DisEq(Var, Var),
108
    Eq(Var, Var),
109
    MinusEq(Var, Var),
110
    GacEq(Var, Var),
111
    WatchLess(Var, Var),
112
    WatchNeq(Var, Var),
113
    Ineq(Var, Var, Constant),
114
    False,
115
    True,
116
}
117

            
118
/// Representation of a Minion Variable.
119
///
120
/// A variable can either be a named variable, or an anomynous "constant as a variable".
121
///
122
/// The latter is not stored in the symbol table, or counted in Minions internal list of all
123
/// variables, but is used to allow the use of a constant in the place of a variable in a
124
/// constraint.
125
#[derive(Debug, Clone, Eq, PartialEq)]
126
pub enum Var {
127
    NameRef(VarName),
128
    ConstantAsVar(i32),
129
}
130

            
131
/// Representation of a Minion constant.
132
#[non_exhaustive]
133
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
134
pub enum Constant {
135
    Bool(bool),
136
    Integer(i32),
137
}
138

            
139
/// Representation of variable domains.
140
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
141
#[non_exhaustive]
142
pub enum VarDomain {
143
    Bound(i32, i32),
144
    Discrete(i32, i32),
145
    SparseBound(i32, i32),
146
    Bool,
147
}
148

            
149
#[derive(Debug, Clone, Eq, PartialEq)]
150
#[non_exhaustive]
151
/// Stores all named variables in a Minion model alongside their domains.
152
///
153
/// Named variables referenced in [constraints](Constraint) must be in the symbol table for the
154
/// model to be valid. In the future, this will raise some sort of type error.
155
pub struct SymbolTable {
156
    table: HashMap<VarName, VarDomain>,
157

            
158
    // for now doubles both as Minion's SearchOrder and print order
159
    var_order: Vec<VarName>,
160
}
161

            
162
impl SymbolTable {
163
1344
    fn new() -> SymbolTable {
164
1344
        SymbolTable {
165
1344
            table: HashMap::new(),
166
1344
            var_order: Vec::new(),
167
1344
        }
168
1344
    }
169

            
170
    /// Creates a new variable and adds it to the symbol table.
171
    ///
172
    /// # Returns
173
    ///
174
    /// If a variable already exists with the given name, `None` is returned.
175
3927
    pub fn add_var(&mut self, name: VarName, vartype: VarDomain) -> Option<()> {
176
3927
        if self.table.contains_key(&name) {
177
            return None;
178
3927
        }
179
3927

            
180
3927
        self.table.insert(name.clone(), vartype);
181
3927
        self.var_order.push(name);
182
3927

            
183
3927
        Some(())
184
3927
    }
185

            
186
    /// Gets the domain of a named variable.
187
    ///
188
    /// # Returns
189
    ///
190
    /// `None` if no variable is known by that name.
191
3927
    pub fn get_vartype(&self, name: VarName) -> Option<VarDomain> {
192
3927
        self.table.get(&name).cloned()
193
3927
    }
194

            
195
    /// Gets the canonical ordering of variables.
196
1344
    pub fn get_variable_order(&self) -> Vec<VarName> {
197
1344
        self.var_order.clone()
198
1344
    }
199

            
200
    pub fn contains(&self, name: VarName) -> bool {
201
        self.table.contains_key(&name)
202
    }
203
}