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
    pub fn new() -> Model {
20
        Model {
21
            named_variables: SymbolTable::new(),
22
            constraints: Vec::new(),
23
        }
24
    }
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
}
115

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

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

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

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

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

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

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

            
178
        self.table.insert(name.clone(), vartype);
179
        self.var_order.push(name);
180

            
181
        Some(())
182
    }
183

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

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

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