this repo has no description
1#include "Model.h"
2
3using namespace MiniZinc;
4using namespace std;
5
6int MznModel::addData(const char* const name, PyObject* value) {
7 GCLock Lock;
8 if (value == NULL) {
9 PyErr_SetString(PyExc_TypeError, "MiniZinc: Model.addData: Received a NULL value");
10 return -1;
11 }
12 for (unsigned int i = 0; i < _m->size(); i++)
13 if (VarDeclI* vdi = (*_m)[i]->dyn_cast<VarDeclI>()) {
14 if (strcmp(vdi->e()->id()->str().c_str(), name) == 0) {
15 vector<pair<int, int> > dimList;
16 Type type;
17 Expression* rhs =
18 python_to_minizinc(value, vdi->e()->ti()->ranges()); //, vdi->e()->type(), name);
19 if (rhs == NULL) return -1;
20 vdi->e()->e(rhs);
21 return 0;
22 }
23 }
24 MZN_PYERR_SET_STRING(PyExc_TypeError, "MiniZinc: Model.addData: Undefined name '%s'", name);
25 return -1;
26}
27
28int MznModel::load(PyObject* args, PyObject* keywds, bool fromFile) {
29 GCLock Lock;
30 Model* saveModel = _m;
31 stringstream errorStream;
32 vector<string> data;
33
34 PyObject* obj = Py_None;
35 char* options = NULL;
36 const char* py_string;
37 char* errorFile = "./error.txt";
38
39 bool isDict = false;
40
41 if (fromFile) {
42 char* kwlist[] = {"file", "data", "options"};
43 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|Os", kwlist, &py_string, &obj, &options)) {
44 PyErr_SetString(PyExc_TypeError, "MiniZinc: load: Parsing error");
45 return -1;
46 }
47 if (options != NULL) {
48 char* pch;
49 bool t_flag = false;
50 pch = strtok(options, " ");
51 while (pch != NULL) {
52 if (strcmp(pch, "-t") == 0)
53 t_flag = true;
54 else {
55 if (t_flag) {
56 char* ptr;
57 int t = strtol(pch, &ptr, 10);
58 if (t == 0) {
59 PyErr_SetString(PyExc_ValueError,
60 "MiniZinc: Model.load: Time value must be a valid positive number");
61 return -1;
62 }
63 timeLimit = t;
64 t_flag = false;
65 } else {
66 PyErr_SetString(PyExc_ValueError, "MiniZinc: Model.load: Unknown option");
67 return -1;
68 }
69 }
70 pch = strtok(NULL, " ");
71 }
72 }
73 if (obj != Py_None) {
74 if (PyUnicode_Check(obj)) {
75 data.push_back(string(PyUnicode_AsUTF8(obj)));
76 } else if (PyList_Check(obj)) {
77 Py_ssize_t n = PyList_GET_SIZE(obj);
78 for (Py_ssize_t i = 0; i != n; ++i) {
79 const char* name = PyUnicode_AsUTF8(PyList_GET_ITEM(obj, i));
80 if (name == NULL) {
81 PyErr_SetString(PyExc_TypeError,
82 "MiniZinc: Model.load: Element in the list must be a filename");
83 return -1;
84 }
85 data.push_back(string(name));
86 }
87 } else if (PyDict_Check(obj)) {
88 isDict = true;
89 } else {
90 PyErr_SetString(PyExc_TypeError,
91 "MiniZinc: Model.load: The second argument must be either a filename, a "
92 "list of filenames or a dictionary of data");
93 return -1;
94 }
95 }
96 vector<string> models{py_string};
97 _m = parse(models, data, *includePaths, false, false, false, errorStream);
98 _e = new Env(_m);
99 } else {
100 char* kwlist[] = {"string", "error", "options"};
101 if (!PyArg_ParseTupleAndKeywords(args, keywds, "s|ss", kwlist, &py_string, &errorFile,
102 &options)) {
103 PyErr_SetString(PyExc_TypeError, "MiniZinc: Model.load: Keyword parsing error");
104 return -1;
105 }
106 _m = parseFromString(string(py_string), errorFile, *includePaths, false, false, false,
107 errorStream);
108 _e = new Env(_m);
109 }
110 if (_m) {
111 delete saveModel;
112 if (isDict) {
113 stringstream assignments;
114 Py_ssize_t pos = 0;
115 PyObject* key;
116 PyObject* value;
117 GCLock lock;
118 while (PyDict_Next(obj, &pos, &key, &value)) {
119 const char* name = PyUnicode_AsUTF8(key);
120 if (addData(name, value) == -1) {
121 // addData handles the error message
122 return -1;
123 }
124 }
125 }
126 loaded = true;
127 return 0;
128 } else {
129 const std::string tmp = "MiniZinc: Model.load: " + errorStream.str();
130 PyErr_SetString(PyExc_RuntimeError, tmp.c_str());
131 return -1;
132 }
133}
134
135PyObject* MznModel::solve(PyObject* args, PyObject* kwds) {
136 if (!loaded) {
137 PyErr_SetString(PyExc_RuntimeError,
138 "MiniZinc: Model.solve: No data has been loaded into the model");
139 return NULL;
140 }
141
142 PyObject* dict = NULL;
143
144 static char* kwlist[] = {"dict", "solver", "time", NULL};
145
146 char* solverName = "";
147 unsigned long newTimeLimit = 0;
148
149 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Osk", kwlist, &dict, &solverName, &newTimeLimit)) {
150 PyErr_SetString(PyExc_RuntimeError, "MiniZinc: Model.solve: Parsing error");
151 return NULL;
152 }
153
154 Model* saveModel;
155 {
156 GCLock lock;
157 saveModel = copy(_e->envi(), _m);
158 Py_ssize_t pos = 0;
159 PyObject* key;
160 PyObject* value;
161 if (dict) {
162 while (PyDict_Next(dict, &pos, &key, &value)) {
163 const char* name = PyUnicode_AsUTF8(key);
164 if (addData(name, value) == -1) {
165 // addData handled the error message
166 goto SOLVE__ERROR_HANDLING;
167 }
168 }
169 }
170 if (newTimeLimit > 0) {
171 timeLimit = newTimeLimit;
172 }
173 if (strlen(solverName)) {
174 if (set_solver(solverName) == NULL) {
175 // setSolver handled the error message
176 goto SOLVE__ERROR_HANDLING;
177 }
178 }
179 goto SOLVE__NO_ERROR;
180 SOLVE__ERROR_HANDLING:
181 delete _m;
182 _m = saveModel;
183 _e = new Env(_m);
184 return NULL;
185 }
186
187SOLVE__NO_ERROR:
188 vector<TypeError> typeErrors;
189 try {
190 MiniZinc::typecheck(*_e, _m, typeErrors, false);
191 } catch (LocationException& e) {
192 MZN_PYERR_SET_STRING(PyExc_RuntimeError, "MiniZinc: Model.solve: %s: %s", e.what(),
193 e.msg().c_str());
194 return NULL;
195 }
196 if (typeErrors.size() > 0) {
197 stringstream errorLog;
198 for (unsigned int i = 0; i < typeErrors.size(); i++) {
199 errorLog << typeErrors[i].loc() << ":" << endl;
200 errorLog << typeErrors[i].what() << ": " << typeErrors[i].msg() << "\n";
201 }
202 const std::string& tmp = errorLog.str();
203 const char* cstr = tmp.c_str();
204 PyErr_SetString(PyExc_TypeError, cstr);
205 return NULL;
206 }
207 MiniZinc::registerBuiltins(*_e, _m);
208
209 Env* env = _e;
210 try {
211 FlatteningOptions fopts;
212 flatten(*env, fopts);
213 } catch (LocationException& e) {
214 stringstream errorLog;
215 errorLog << e.what() << ": " << std::endl;
216 env->dumpErrorStack(errorLog);
217 errorLog << " " << e.msg() << std::endl;
218 const std::string& tmp = errorLog.str();
219 const char* cstr = tmp.c_str();
220 PyErr_SetString(PyExc_RuntimeError, cstr);
221 return NULL;
222 }
223 if (env->warnings().size() != 0) {
224 stringstream warningLog;
225 warningLog << "MiniZinc: Model.solve: Warning:\n";
226 for (unsigned int i = 0; i < env->warnings().size(); i++) {
227 warningLog << env->warnings()[i];
228 }
229 const std::string& tmp = warningLog.str();
230 const char* cstr = tmp.c_str();
231 PyErr_WarnEx(PyExc_RuntimeWarning, cstr, 1);
232 }
233 optimize(*env);
234 oldflatzinc(*env);
235 GCLock lock;
236 Options options;
237 if (timeLimit != 0) options.setIntParam("time", timeLimit);
238 delete _m;
239 _m = saveModel;
240 _e = new Env(_m);
241 PyMznSolver* ret = reinterpret_cast<PyMznSolver*>(PyMznSolver_new(&PyMznSolver_Type, NULL, NULL));
242 switch (sc) {
243 case SC_UNKNOWN:
244 delete env;
245 PyErr_SetString(PyExc_ValueError, "MiniZinc: Model.solve: Solver name is not set");
246 return NULL;
247
248 case SC_GECODE:
249 ret->solver = new GecodeSolverInstance(*env, options);
250 break;
251 }
252 ret->solver->processFlatZinc();
253 ret->env = env;
254 return reinterpret_cast<PyObject*>(ret);
255}
256
257/*
258 * Description: Creates a minizinc constraint
259 * Note: Need an outer GCLock for this to work
260 */
261static PyObject* MznModel_Constraint(MznModel* self, PyObject* args) {
262 PyObject* obj;
263 if (!PyArg_ParseTuple(args, "O", &obj)) {
264 PyErr_SetString(PyExc_TypeError,
265 "MiniZinc: Model.Constraint: Requires an object of Minizinc Variable");
266 return NULL;
267 }
268
269 GCLock Lock;
270 ConstraintI* i;
271 if (PyObject_ExactTypeCheck(obj, &MznExpression_Type)) {
272 i = new ConstraintI(Location(), (reinterpret_cast<MznExpression*>(obj)->e));
273 } else if (PyBool_Check(obj)) {
274 bool val = PyObject_IsTrue(obj);
275 i = new ConstraintI(Location(), new BoolLit(Location(), val));
276 } else {
277 PyErr_SetString(
278 PyExc_TypeError,
279 "MiniZinc: Model.Constraint: Object must be a MiniZinc Variable or Python Boolean value");
280 return NULL;
281 }
282 self->_m->addItem(i);
283 Py_RETURN_NONE;
284}
285
286/*
287 * Description: Defines the type of solution of the model
288 */
289// The responsibility to check if the parsed argument is annotation or not is of the Python
290// interface, not the C++ interface
291static PyObject* MznModel_SolveItem(MznModel* self, PyObject* args) {
292 unsigned int solveType;
293 PyObject* PyExp = NULL;
294 PyObject* PyAnn = NULL;
295 Expression* e = NULL;
296 Expression* ann = NULL;
297
298 if (!PyArg_ParseTuple(args, "I|OO", &solveType, &PyAnn, &PyExp)) {
299 PyErr_SetString(PyExc_TypeError,
300 "MiniZinc: Model.SolveItem: Requires a solver code, an annotation (can be "
301 "NULL) and an optional expression (for optimisation)");
302 return NULL;
303 }
304
305 if (solveType > 2) {
306 PyErr_SetString(
307 PyExc_ValueError,
308 "MiniZinc: Model.SolveItem: Invalid solver code (Must be a positive less than 3 integer)");
309 return NULL;
310 }
311 if (solveType) {
312 if (PyExp == NULL) {
313 PyErr_SetString(
314 PyExc_TypeError,
315 "MiniZinc: Model.SolveItem: Optimisation solver requires an addition constraint object");
316 return NULL;
317 } else if (PyObject_ExactTypeCheck(PyExp, &MznExpression_Type)) {
318 e = reinterpret_cast<MznExpression*>(PyExp)->e;
319 } else {
320 PyErr_SetString(PyExc_TypeError,
321 "MiniZinc: Model.SolveItem: Expression must be a Minizinc Variable Object");
322 return NULL;
323 }
324 }
325
326 GCLock Lock;
327 SolveI* i;
328 switch (solveType) {
329 case 0:
330 i = SolveI::sat(Location());
331 break;
332 case 1:
333 i = SolveI::min(Location(), (e));
334 break;
335 case 2:
336 i = SolveI::max(Location(), (e));
337 break;
338 }
339 if (PyObject_IsTrue(PyAnn)) {
340 if (PyObject_TypeCheck(PyAnn, &MznExpression_Type)) {
341 ann = reinterpret_cast<MznExpression*>(PyAnn)->e;
342 i->ann().add(ann);
343 } else if (PyList_Check(PyAnn)) {
344 long n = PyList_GET_SIZE(PyAnn);
345 for (long idx = 0; idx != n; ++idx) {
346 PyObject* PyItem = PyList_GET_ITEM(PyAnn, idx);
347 if (!PyObject_TypeCheck(PyItem, &MznExpression_Type)) {
348 // XXX: CONSIDER REVIEW - should I delete i or it will be automatically deleted
349 delete i;
350 MZN_PYERR_SET_STRING(
351 PyExc_TypeError,
352 "MiniZinc: Model.SolveItem: Item at position %ld must be a MiniZinc Variable", idx);
353 return NULL;
354 }
355 ann = reinterpret_cast<MznExpression*>(PyItem)->e;
356 i->ann().add(ann);
357 }
358 } else if (PyTuple_Check(PyAnn)) {
359 long n = PyTuple_GET_SIZE(PyAnn);
360 for (long idx = 0; idx != n; ++idx) {
361 PyObject* PyItem = PyTuple_GET_ITEM(PyAnn, idx);
362 if (!PyObject_TypeCheck(PyItem, &MznExpression_Type)) {
363 // XXX: CONSIDER REVIEW
364 delete i;
365 MZN_PYERR_SET_STRING(
366 PyExc_TypeError,
367 "MiniZinc: Model.SolveItem: Item at position %ld must be a MiniZinc Variable", idx);
368 return NULL;
369 }
370 ann = reinterpret_cast<MznExpression*>(PyItem)->e;
371 i->ann().add(ann);
372 }
373 } else {
374 // XXX: CONSIDER REVIEW
375 delete i;
376 PyErr_SetString(PyExc_TypeError,
377 "MiniZinc: Model.SolveItem: Annotation must be a single value of or a "
378 "list/tuple of MiniZinc Variable Object");
379 return NULL;
380 }
381 }
382 self->_m->addItem(i);
383 Py_RETURN_NONE;
384}
385
386static PyObject* MznModel_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
387 MznModel* self = reinterpret_cast<MznModel*>(type->tp_alloc(type, 0));
388 if (self == NULL) {
389 PyErr_SetString(PyExc_RuntimeError, "MiniZinc: Unable to create new model");
390 return NULL;
391 }
392 self->includePaths = NULL;
393 self->_m = NULL;
394 self->_e = NULL;
395 return reinterpret_cast<PyObject*>(self);
396}
397
398static int MznModel_init(MznModel* self, PyObject* args = NULL) {
399 self->loaded = false;
400 string std_lib_dir;
401 if (char* MZNSTDLIBDIR = getenv("MZN_STDLIB_DIR")) {
402 std_lib_dir = string(MZNSTDLIBDIR);
403 } else {
404 PyErr_SetString(PyExc_EnvironmentError,
405 "MiniZinc: Model.init: No MiniZinc library directory MZN_STDLIB_DIR defined.");
406 return -1;
407 }
408 stringstream libNames;
409 libNames << "include \"globals.mzn\";";
410 if (args != NULL) {
411 PyObject* PyLibNames = NULL;
412 if (PyUnicode_Check(args)) {
413 libNames << "\ninclude \"" << PyUnicode_AsUTF8(args) << "\";";
414 } else if (PyTuple_Check(args)) {
415 Py_ssize_t n = PyTuple_GET_SIZE(args);
416 if (n > 1) {
417 PyErr_SetString(PyExc_TypeError, "MiniZinc: Model.init: Accept at most 1 argument");
418 return -1;
419 } else if (n == 1) {
420 PyLibNames = PyTuple_GET_ITEM(args, 0);
421 if (PyObject_IsTrue(PyLibNames)) {
422 if (PyUnicode_Check(PyLibNames)) {
423 libNames << "\ninclude \"" << PyUnicode_AsUTF8(PyLibNames) << "\";";
424 } else if (PyList_Check(PyLibNames)) {
425 Py_ssize_t n = PyList_GET_SIZE(PyLibNames);
426 for (Py_ssize_t i = 0; i != n; ++i) {
427 PyObject* temp = PyList_GET_ITEM(PyLibNames, i);
428 if (!PyUnicode_Check(temp)) {
429 PyErr_SetString(PyExc_TypeError,
430 "MiniZinc: Model.init: Items in parsing list must be strings");
431 return -1;
432 }
433 libNames << "\ninclude \"" << PyUnicode_AsUTF8(temp) << "\";";
434 }
435 } else if (PyTuple_Check(PyLibNames)) {
436 Py_ssize_t n = PyTuple_GET_SIZE(PyLibNames);
437 for (Py_ssize_t i = 0; i != n; ++i) {
438 PyObject* temp = PyTuple_GET_ITEM(PyLibNames, i);
439 if (!PyUnicode_Check(temp)) {
440 PyErr_SetString(PyExc_TypeError,
441 "MiniZinc: Model.init: Items in parsing tuples must be strings");
442 return -1;
443 }
444 libNames << "\ninclude \"" << PyUnicode_AsUTF8(temp) << "\";";
445 }
446 } else {
447 PyErr_SetString(PyExc_TypeError,
448 "MiniZinc: Model.init: Parsing argument must be a string or "
449 "list/tuple of strings");
450 return -1;
451 }
452 }
453 }
454 }
455 }
456 const std::string& libNamesStr = libNames.str();
457 self->timeLimit = 0;
458 self->includePaths = new vector<string>;
459 self->includePaths->push_back(std_lib_dir + "/gecode/");
460 self->includePaths->push_back(std_lib_dir + "/std/");
461 self->sc = MznModel::default_solver;
462 stringstream errorStream;
463 self->_m = parseFromString(libNamesStr, "error.txt", *(self->includePaths), false, false, false,
464 errorStream);
465 self->_e = new Env(self->_m);
466 if (!(self->_m)) {
467 const std::string& tmp = errorStream.str();
468 const char* cstr = tmp.c_str();
469 PyErr_SetString(PyExc_EnvironmentError, cstr);
470 return -1;
471 }
472 return 0;
473}
474
475static void MznModel_dealloc(MznModel* self) {
476 if (self->_m) delete self->_m;
477 if (self->_m) delete self->includePaths;
478 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
479}
480
481static PyObject* MznModel_addData(MznModel* self, PyObject* args) {
482 PyObject* obj;
483 const char* name;
484 if (!PyArg_ParseTuple(args, "sO", &name, &obj)) {
485 PyErr_SetString(PyExc_RuntimeError, "MiniZinc: Model.addData: Parsing error");
486 return NULL;
487 }
488 if (self->addData(name, obj) == -1) {
489 // addData set error string already
490 return NULL;
491 }
492 Py_RETURN_NONE;
493}
494
495static PyObject* MznModel_copy(MznModel* self) {
496 MznModel* ret = reinterpret_cast<MznModel*>(MznModel_new(&MznModel_Type, NULL, NULL));
497 GCLock lock;
498 ret->_m = copy(self->_e->envi(), self->_m);
499 ret->includePaths = new vector<string>(*(self->includePaths));
500
501 ret->timeLimit = self->timeLimit;
502 ret->loaded = self->loaded;
503 return reinterpret_cast<PyObject*>(ret);
504}
505
506static PyObject* MznModel_debugprint(MznModel* self) {
507 debugprint(self->_m);
508 Py_RETURN_NONE;
509}
510
511static PyObject* MznModel_load(MznModel* self, PyObject* args, PyObject* keywds) {
512 if (self->load(args, keywds, true) < 0) return NULL;
513 Py_RETURN_NONE;
514}
515
516static PyObject* MznModel_load_from_string(MznModel* self, PyObject* args, PyObject* keywds) {
517 if (self->load(args, keywds, false) < 0) return NULL;
518 Py_RETURN_NONE;
519}
520
521static PyObject* MznModel_solve(MznModel* self, PyObject* args, PyObject* kwds) {
522 return self->solve(args, kwds);
523}
524
525static PyObject* MznModel_set_time_limit(MznModel* self, PyObject* args) {
526 unsigned long t;
527 if (!PyArg_ParseTuple(args, "k", &t)) {
528 PyErr_SetString(PyExc_TypeError,
529 "MiniZinc: Model.set_time_limit: Time limit must be an integer");
530 return NULL;
531 }
532 self->timeLimit = t;
533 return Py_None;
534}
535
536PyObject* MznModel::set_solver(const char* s) {
537 std::string name(s);
538 // lower characters in name
539 for (std::string::iterator i = name.begin(); i != name.end(); ++i)
540 if (*i <= 'Z' && *i >= 'A') *i = *i - ('Z' - 'z');
541 if (name == "gecode")
542 sc = SC_GECODE;
543 else {
544 MZN_PYERR_SET_STRING(PyExc_ValueError, "MiniZinc: Model.set_solver: Unexpected solver name: %s",
545 name.c_str());
546 return NULL;
547 }
548 return Py_None;
549}
550
551static PyObject* MznModel_set_solver(MznModel* self, PyObject* args) {
552 const char* s;
553 if (!PyArg_ParseTuple(args, "s", &s)) {
554 PyErr_SetString(PyExc_TypeError, "MiniZinc: Model.set_solver: Solver name must be a string");
555 return NULL;
556 }
557 return (self->set_solver(s));
558}
559
560static PyObject* MznModel_Declaration(MznModel* self, PyObject* args) {
561 GCLock Lock;
562 enum TypeId {
563 PARINT, // 0
564 PARBOOL, // 1
565 PARFLOAT, // 2
566 PARSTRING, // 3
567 ANN, // 4
568 PARSETINT, // 5
569 PARSETBOOL, // 6
570 PARSETFLOAT, // 7
571 PARSETSTRING, // 8
572 VARINT, // 9
573 VARBOOL, // 10
574 VARFLOAT, // 11
575 VARSETINT, // 12
576 VARBOT, // 13
577 BOT, // 14
578 TOP, // 15
579 VARTOP, // 16
580 OPTVARTOP // 17
581 };
582
583 char* name;
584 long tid;
585 PyObject* pydim = NULL;
586 PyObject* pylb = NULL;
587 PyObject* pyub = NULL;
588 PyObject* pyval = NULL;
589 Type type;
590 Expression* domain = NULL;
591 Expression* initValue = NULL;
592 Py_ssize_t dim;
593
594 vector<TypeInst*> ranges;
595 Type::BaseType code = Type::BT_UNKNOWN;
596
597 if (!PyArg_ParseTuple(args, "sO|OOO", &name, &pyval, &pydim, &pylb, &pyub)) {
598 MZN_PYERR_SET_STRING(PyExc_TypeError,
599 "MiniZinc: MznModel.Declaration: Variable parsing error");
600 return NULL;
601 }
602 // if only 2 arguments, second value is the initial value
603 if (pydim == NULL) {
604 vector<pair<int, int> > dimList;
605 initValue = python_to_minizinc(pyval, type, dimList);
606 dim = dimList.size();
607 domain = NULL;
608 } else
609 // else if > 2 arguments, create a MiniZinc Variable
610 {
611#if PY_MAJOR_VERSION < 3
612 if (PyInt_Check(pyval)) {
613 tid = PyInt_AS_LONG(pyval);
614 pyval = NULL;
615 } else
616#endif
617 if (PyLong_Check(pyval)) {
618 tid = PyLong_AsLong(pyval);
619 pyval = NULL;
620 } else {
621 PyErr_SetString(PyExc_TypeError,
622 "MiniZinc: MznModel.Declaration: Type Id must be an integer");
623 return NULL;
624 }
625 if (tid > 17 || tid < 0) {
626 PyErr_SetString(PyExc_ValueError, "MiniZinc: MznModel.Declaration: Type Id is from 0 to 17");
627 return NULL;
628 }
629
630 int errorOccurred;
631 ranges = pydim_to_minizinc_ranges(pydim, errorOccurred);
632 if (errorOccurred) return NULL;
633 dim = ranges.size();
634
635 // Process different types
636 switch (static_cast<TypeId>(tid)) {
637 case VARINT:
638 type = Type::varint(dim);
639 code = Type::BT_INT;
640 if (pyub == NULL) {
641 Type tempType;
642 vector<pair<int, int> > tempDimList;
643 domain = python_to_minizinc(pylb, tempType, tempDimList);
644 if (tempType.st() != Type::ST_SET) {
645 PyErr_SetString(PyExc_TypeError,
646 "MiniZinc: MznModel.Declaration: If 5th argument does not exist, 4th "
647 "argument must be a Minizinc Set");
648 return NULL;
649 }
650 } else
651 domain = new BinOp(Location(), one_dim_python_to_minizinc(pylb, code), BOT_DOTDOT,
652 one_dim_python_to_minizinc(pyub, code));
653 break;
654 case VARBOOL:
655 type = Type::varbool(dim);
656 break;
657 case VARFLOAT:
658 type = Type::varfloat(dim);
659 code = Type::BT_FLOAT;
660 domain = new BinOp(Location(), one_dim_python_to_minizinc(pylb, code), BOT_DOTDOT,
661 one_dim_python_to_minizinc(pyub, code));
662 break;
663 case VARSETINT:
664 type = Type::varsetint(dim);
665 if (pyub == NULL) {
666 Type tempType;
667 vector<pair<int, int> > tempDimList;
668 domain = python_to_minizinc(pylb, tempType, tempDimList);
669 if (tempType.st() != Type::ST_SET) {
670 PyErr_SetString(PyExc_TypeError,
671 "MiniZinc: MznModel.Declaration: If 5th argument does not exist, 4th "
672 "argument must be a Minizinc Set");
673 return NULL;
674 }
675 } else
676 domain = new BinOp(Location(), one_dim_python_to_minizinc(pylb, code), BOT_DOTDOT,
677 one_dim_python_to_minizinc(pyub, code));
678 break;
679 default:
680 MZN_PYERR_SET_STRING(PyExc_ValueError,
681 "MiniZinc: MznModel.Declaration: Value code %li not supported", tid);
682 return NULL;
683 }
684 }
685
686 VarDecl* vd = new VarDecl(Location(), new TypeInst(Location(), type, ranges, domain),
687 string(name), initValue);
688 self->_m->addItem(new VarDeclI(Location(), vd));
689 self->loaded = true;
690
691 PyObject* ret = MznExpression_new(&MznExpression_Type, NULL, NULL);
692 reinterpret_cast<MznExpression*>(ret)->e = vd->id();
693 return ret;
694}