A set of benchmarks to compare a new prototype MiniZinc implementation
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
3/*
4 * Main authors:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8/* This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11
12#ifndef __MINIZINC_MODEL_HH__
13#define __MINIZINC_MODEL_HH__
14
15#include <minizinc/ast.hh>
16#include <minizinc/gc.hh>
17
18#include <iterator>
19#include <unordered_map>
20#include <unordered_set>
21#include <vector>
22
23namespace MiniZinc {
24
25class VarDeclIterator;
26class ConstraintIterator;
27class FunctionIterator;
28
29class CopyMap;
30class EnvI;
31
32/// A MiniZinc model
33class Model {
34 friend class GC;
35 friend class FZNSolverInstance;
36 friend Model* copy(EnvI& env, CopyMap& cm, Model* m, bool isFlatModel);
37
38protected:
39 /// Previous model in root set list
40 Model* _roots_prev;
41 /// Next model in root set list
42 Model* _roots_next;
43
44 struct FnEntry {
45 std::vector<Type> t;
46 FunctionI* fi;
47 bool isPolymorphic;
48 FnEntry(FunctionI* fi0);
49 bool operator<(const FnEntry&) const;
50 static bool compare(const FnEntry& e1, const FnEntry& e2);
51 };
52
53 /// Add all instances of polymorphic entry \a fe to \a entries
54 void addPolymorphicInstances(Model::FnEntry& fe, std::vector<FnEntry>& entries);
55
56 /// Type of map from identifiers to function declarations
57 typedef ASTStringMap<std::vector<FnEntry> >::t FnMap;
58 /// Map from identifiers to function declarations
59 FnMap fnmap;
60
61 /// Type of map from Type (represented as int) to reverse mapper functions
62 typedef std::unordered_map<int, FunctionI*> RevMapperMap;
63 /// Map from Type (represented as int) to reverse mapper functions
64 RevMapperMap revmapmap;
65
66 /// Filename of the model
67 ASTString _filename;
68 /// Path of the model
69 ASTString _filepath;
70 /// Parent model if model was included
71 Model* _parent;
72 /// Items in the model
73 std::vector<Item*> _items;
74 /// Pointer to the solve item
75 SolveI* _solveItem;
76 /// Pointer to the output item
77 OutputI* _outputItem;
78 /// File-level documentation comment
79 std::string _docComment;
80
81 /// Store some declarations
82 struct FnDecls {
83 using TCheckedDecl = std::pair<bool, FunctionI*>; // bool means that it was checked
84 TCheckedDecl bounds_disj = {false, nullptr}; // SCIP's bound disjunction
85 } fnDecls;
86
87public:
88 /// Construct empty model
89 Model(void);
90 /// Destructor
91 ~Model(void);
92
93 /// Add \a i to the model
94 void addItem(Item* i);
95
96 /// Get parent model
97 Model* parent(void) const { return _parent; }
98 /// Set parent model to \a p
99 void setParent(Model* p) {
100 assert(_parent == NULL);
101 _parent = p;
102 }
103
104 /// Get file name
105 ASTString filename(void) const { return _filename; }
106 /// Get file path
107 ASTString filepath(void) const { return _filepath; }
108 /// Set file name
109 void setFilename(const std::string& f) {
110 assert(_filename.size() == 0);
111 _filename = ASTString(f);
112 }
113 /// Set file path
114 void setFilepath(const std::string& f) {
115 assert(_filepath.size() == 0);
116 _filepath = ASTString(f);
117 }
118
119 /// Register a builtin function item
120 void registerFn(EnvI& env, FunctionI* fi);
121 /// Sort functions by type
122 void sortFn(void);
123 /// Check that registered functions do not clash wrt overloading
124 void checkFnOverloading(EnvI& env);
125 /// Fix function table after type checking
126 void fixFnMap(void);
127 /// Return function declaration for \a id matching \a args
128 FunctionI* matchFn(EnvI& env, const ASTString& id, const std::vector<Expression*>& args,
129 bool strictEnums) const;
130 /// Return function declaration for \a id matching types \a t
131 FunctionI* matchFn(EnvI& env, const ASTString& id, const std::vector<Type>& t, bool strictEnums);
132 /// Return function declaration matching call \a c
133 FunctionI* matchFn(EnvI& env, Call* c, bool strictEnums) const;
134 /// Return function declaration for reverse mapper for type \a t
135 FunctionI* matchRevMap(EnvI& env, const Type& t) const;
136 /// Merge all builtin functions into \a m
137 void mergeStdLib(EnvI& env, Model* m) const;
138
139 /// Return item \a i
140 Item*& operator[](int i);
141 /// Return item \a i
142 const Item* operator[](int i) const;
143 /// Return number of items
144 unsigned int size(void) const;
145
146 typedef std::vector<Item*>::iterator iterator;
147 typedef std::vector<Item*>::const_iterator const_iterator;
148
149 /// Iterator for beginning of items
150 iterator begin(void);
151 /// Iterator for beginning of items
152 const_iterator begin(void) const;
153 /// Iterator for end of items
154 iterator end(void);
155 /// Iterator for end of items
156 const_iterator end(void) const;
157
158 ConstraintIterator begin_constraints(void);
159 ConstraintIterator end_constraints(void);
160 VarDeclIterator begin_vardecls(void);
161 VarDeclIterator end_vardecls(void);
162 FunctionIterator begin_functions(void);
163 FunctionIterator end_functions(void);
164
165 SolveI* solveItem(void);
166
167 OutputI* outputItem(void);
168 void setOutputItem(OutputI* oi);
169
170 /// Add a file-level documentation comment
171 void addDocComment(std::string s) { _docComment += s; }
172
173 /// Return the file-level documentation comment
174 const std::string& docComment(void) const { return _docComment; }
175
176 /// Remove all items marked as removed
177 void compact(void);
178
179 /// Get the stored function declarations
180 FnDecls& getFnDecls() { return fnDecls; }
181};
182
183class VarDeclIterator {
184 Model* _model;
185 Model::iterator _it;
186
187public:
188 typedef Model::iterator::difference_type difference_type;
189 typedef Model::iterator::value_type value_type;
190 typedef VarDeclI& reference;
191 typedef VarDeclI* pointer;
192 typedef std::forward_iterator_tag iterator_category;
193
194 VarDeclIterator() {}
195 VarDeclIterator(const VarDeclIterator& vi) : _it(vi._it) {}
196 VarDeclIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
197 while (_it != _model->end() && !(*_it)->isa<VarDeclI>()) {
198 ++_it;
199 }
200 }
201 ~VarDeclIterator() {}
202
203 VarDeclIterator& operator=(const VarDeclIterator& vi) {
204 if (this != &vi) {
205 _it = vi._it;
206 }
207 return *this;
208 }
209 bool operator==(const VarDeclIterator& vi) const { return _it == vi._it; }
210 bool operator!=(const VarDeclIterator& vi) const { return _it != vi._it; }
211 VarDeclIterator& operator++() {
212 do {
213 ++_it;
214 } while (_it != _model->end() && !(*_it)->isa<VarDeclI>());
215 return *this;
216 }
217
218 reference operator*() const { return *(*_it)->cast<VarDeclI>(); }
219 pointer operator->() const { return (*_it)->cast<VarDeclI>(); }
220};
221
222class ConstraintIterator {
223 Model* _model;
224 Model::iterator _it;
225
226public:
227 typedef Model::iterator::difference_type difference_type;
228 typedef Model::iterator::value_type value_type;
229 typedef ConstraintI& reference;
230 typedef ConstraintI* pointer;
231 typedef std::forward_iterator_tag iterator_category;
232
233 ConstraintIterator() {}
234 ConstraintIterator(const ConstraintIterator& vi) : _it(vi._it) {}
235 ConstraintIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
236 while (_it != _model->end() && !(*_it)->isa<ConstraintI>()) {
237 ++_it;
238 }
239 }
240 ~ConstraintIterator() {}
241
242 ConstraintIterator& operator=(const ConstraintIterator& vi) {
243 if (this != &vi) {
244 _it = vi._it;
245 }
246 return *this;
247 }
248 bool operator==(const ConstraintIterator& vi) const { return _it == vi._it; }
249 bool operator!=(const ConstraintIterator& vi) const { return _it != vi._it; }
250 ConstraintIterator& operator++() {
251 do {
252 ++_it;
253 } while (_it != _model->end() && !(*_it)->isa<ConstraintI>());
254 return *this;
255 }
256
257 reference operator*() const { return *(*_it)->cast<ConstraintI>(); }
258 pointer operator->() const { return (*_it)->cast<ConstraintI>(); }
259};
260
261class FunctionIterator {
262 Model* _model;
263 Model::iterator _it;
264
265public:
266 typedef Model::iterator::difference_type difference_type;
267 typedef Model::iterator::value_type value_type;
268 typedef FunctionI& reference;
269 typedef FunctionI* pointer;
270 typedef std::forward_iterator_tag iterator_category;
271
272 FunctionIterator() {}
273 FunctionIterator(const FunctionIterator& vi) : _it(vi._it) {}
274 FunctionIterator(Model* model, const Model::iterator& it) : _model(model), _it(it) {
275 while (_it != _model->end() && !(*_it)->isa<FunctionI>()) {
276 ++_it;
277 }
278 }
279 ~FunctionIterator() {}
280
281 FunctionIterator& operator=(const FunctionIterator& vi) {
282 if (this != &vi) {
283 _it = vi._it;
284 }
285 return *this;
286 }
287 bool operator==(const FunctionIterator& vi) const { return _it == vi._it; }
288 bool operator!=(const FunctionIterator& vi) const { return _it != vi._it; }
289 FunctionIterator& operator++() {
290 do {
291 ++_it;
292 } while (_it != _model->end() && !(*_it)->isa<FunctionI>());
293 return *this;
294 }
295
296 reference operator*() const { return *(*_it)->cast<FunctionI>(); }
297 pointer operator->() const { return (*_it)->cast<FunctionI>(); }
298};
299
300class EnvI;
301
302/// Environment
303class Env {
304private:
305 EnvI* e;
306
307public:
308 Env(Model* m = NULL, std::ostream& outstream = std::cout, std::ostream& errstream = std::cerr);
309 ~Env(void);
310
311 Model* model(void);
312 void model(Model* m);
313 Model* flat(void);
314 void swap();
315 Model* output(void);
316 EnvI& envi(void);
317 const EnvI& envi(void) const;
318 std::ostream& dumpErrorStack(std::ostream& os);
319 const std::vector<std::string>& warnings(void);
320 void clearWarnings(void);
321 unsigned int maxCallStack(void) const;
322 std::ostream& evalOutput(std::ostream& os);
323};
324
325class CallStackItem {
326public:
327 EnvI& env;
328 CallStackItem(EnvI& env0, Expression* e);
329 CallStackItem(EnvI& env0, Id* ident, IntVal i);
330 ~CallStackItem(void);
331};
332
333/// Visitor for model items
334class ItemVisitor {
335public:
336 /// Enter model
337 bool enterModel(Model* m) { return true; }
338 /// Enter item
339 bool enter(Item* m) { return true; }
340 /// Visit include item
341 void vIncludeI(IncludeI*) {}
342 /// Visit variable declaration
343 void vVarDeclI(VarDeclI*) {}
344 /// Visit assign item
345 void vAssignI(AssignI*) {}
346 /// Visit constraint item
347 void vConstraintI(ConstraintI*) {}
348 /// Visit solve item
349 void vSolveI(SolveI*) {}
350 /// Visit output item
351 void vOutputI(OutputI*) {}
352 /// Visit function item
353 void vFunctionI(FunctionI*) {}
354};
355
356/// Iterator over items in a model and all its included models
357template <class I>
358class ItemIter {
359protected:
360 I& iter;
361
362public:
363 ItemIter(I& iter0) : iter(iter0) {}
364 void run(Model* m) {
365 std::unordered_set<Model*> seen;
366 std::vector<Model*> models;
367 models.push_back(m);
368 seen.insert(m);
369 while (!models.empty()) {
370 Model* cm = models.back();
371 models.pop_back();
372 if (!iter.enterModel(cm)) continue;
373 std::vector<Model*> includedModels;
374 for (unsigned int i = 0; i < cm->size(); i++) {
375 if ((*cm)[i]->removed()) continue;
376 if (!iter.enter((*cm)[i])) continue;
377 switch ((*cm)[i]->iid()) {
378 case Item::II_INC:
379 if (seen.find((*cm)[i]->cast<IncludeI>()->m()) == seen.end()) {
380 includedModels.push_back((*cm)[i]->cast<IncludeI>()->m());
381 seen.insert((*cm)[i]->cast<IncludeI>()->m());
382 }
383 iter.vIncludeI((*cm)[i]->cast<IncludeI>());
384 break;
385 case Item::II_VD:
386 iter.vVarDeclI((*cm)[i]->cast<VarDeclI>());
387 break;
388 case Item::II_ASN:
389 iter.vAssignI((*cm)[i]->cast<AssignI>());
390 break;
391 case Item::II_CON:
392 iter.vConstraintI((*cm)[i]->cast<ConstraintI>());
393 break;
394 case Item::II_SOL:
395 iter.vSolveI((*cm)[i]->cast<SolveI>());
396 break;
397 case Item::II_OUT:
398 iter.vOutputI((*cm)[i]->cast<OutputI>());
399 break;
400 case Item::II_FUN:
401 iter.vFunctionI((*cm)[i]->cast<FunctionI>());
402 break;
403 }
404 }
405 for (unsigned int i = static_cast<unsigned int>(includedModels.size()); i--;) {
406 models.push_back(includedModels[i]);
407 }
408 }
409 }
410};
411
412/// Run iterator \a i over all items of model \a m
413template <class I>
414void iterItems(I& i, Model* m) {
415 ItemIter<I>(i).run(m);
416}
417
418} // namespace MiniZinc
419
420#endif