minion_rs/
ast.rs

1//! Types used for representing Minion models in Rust.
2
3use std::collections::HashMap;
4
5pub type VarName = String;
6pub type Tuple = (Constant, Constant);
7pub type TwoVars = (Var, Var);
8
9/// A Minion model.
10#[non_exhaustive]
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct Model {
13    pub named_variables: SymbolTable,
14    pub constraints: Vec<Constraint>,
15}
16
17impl 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
27impl 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)]
36pub 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)]
126pub 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)]
134pub 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]
142pub 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.
155pub 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
162impl SymbolTable {
163    fn new() -> SymbolTable {
164        SymbolTable {
165            table: HashMap::new(),
166            var_order: Vec::new(),
167        }
168    }
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    pub fn add_var(&mut self, name: VarName, vartype: VarDomain) -> Option<()> {
176        if self.table.contains_key(&name) {
177            return None;
178        }
179
180        self.table.insert(name.clone(), vartype);
181        self.var_order.push(name);
182
183        Some(())
184    }
185
186    /// Gets the domain of a named variable.
187    ///
188    /// # Returns
189    ///
190    /// `None` if no variable is known by that name.
191    pub fn get_vartype(&self, name: VarName) -> Option<VarDomain> {
192        self.table.get(&name).cloned()
193    }
194
195    /// Gets the canonical ordering of variables.
196    pub fn get_variable_order(&self) -> Vec<VarName> {
197        self.var_order.clone()
198    }
199
200    pub fn contains(&self, name: VarName) -> bool {
201        self.table.contains_key(&name)
202    }
203}