this repo has no description
1/* Python Interface for MiniZinc constraint modelling
2 * Author:
3 * Tai Tran <tai.tran@student.adelaide.edu.au>
4 * Supervisor:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7
8#include "Solver.h"
9
10static PyObject* PyMznSolver_get_value_helper(PyMznSolver* self, const char* const name) {
11 for (unsigned int i = 0; i < self->_m->size(); ++i) {
12 if (VarDeclI* vdi = (*(self->_m))[i]->dyn_cast<VarDeclI>()) {
13 if (strcmp(vdi->e()->id()->str().c_str(), name) == 0) {
14 GCLock Lock;
15 if (PyObject* PyValue = minizinc_to_python(vdi->e()))
16 return PyValue;
17 else {
18 char buffer[50];
19 sprintf(buffer, "Cannot retrieve the value of '%s'", name);
20 PyErr_SetString(PyExc_RuntimeError, buffer);
21 return NULL;
22 }
23 }
24 }
25 }
26 char buffer[50];
27 sprintf(buffer, "'%s' not found", name);
28 PyErr_SetString(PyExc_RuntimeError, buffer);
29 return NULL;
30}
31
32static PyObject* PyMznSolver_get_value(PyMznSolver* self, PyObject* args) {
33 const char* name;
34 PyObject* obj;
35 if (!(self->_m)) {
36 PyErr_SetString(PyExc_RuntimeError, "No model (maybe you need to call Model.next() first");
37 return NULL;
38 }
39 if (!PyArg_ParseTuple(args, "O", &obj)) {
40 PyErr_SetString(PyExc_TypeError, "Accept 1 argument of strings or list/tuple of strings");
41 return NULL;
42 }
43 if (PyUnicode_Check(obj)) {
44 name = PyUnicode_AsUTF8(obj);
45 return PyMznSolver_get_value_helper(self, name);
46 ;
47 } else
48 // XXX: INEFFICIENT function to retrieve values, consider optimize it later
49 // Python Dictionary would be good
50 if (PyList_Check(obj)) {
51 Py_ssize_t n = PyList_GET_SIZE(obj);
52 PyObject* ret = PyList_New(n);
53 for (Py_ssize_t i = 0; i != n; ++i) {
54 PyObject* item = PyList_GET_ITEM(obj, i);
55 if (!PyUnicode_Check(item)) {
56 Py_DECREF(ret);
57 PyErr_SetString(PyExc_RuntimeError, "Elements must be strings");
58 return NULL;
59 }
60 name = PyUnicode_AsUTF8(item);
61 PyObject* value = PyMznSolver_get_value_helper(self, name);
62 if (value == NULL) {
63 Py_DECREF(ret);
64 return NULL;
65 }
66 PyList_SET_ITEM(ret, i, value);
67 }
68 return ret;
69 } else if (PyTuple_Check(obj)) {
70 Py_ssize_t n = PyTuple_GET_SIZE(obj);
71 PyObject* ret = PyTuple_New(n);
72 for (Py_ssize_t i = 0; i != n; ++i) {
73 PyObject* item = PyTuple_GET_ITEM(obj, i);
74 if (!PyUnicode_Check(item)) {
75 Py_DECREF(ret);
76 PyErr_SetString(PyExc_RuntimeError, "Elements must be strings");
77 return NULL;
78 }
79 name = PyUnicode_AsUTF8(item);
80 PyObject* value = PyMznSolver_get_value_helper(self, name);
81 if (value == NULL) {
82 Py_DECREF(ret);
83 return NULL;
84 }
85 PyTuple_SET_ITEM(ret, i, value);
86 }
87 return ret;
88 } else {
89 PyErr_SetString(PyExc_TypeError, "Object must be a string or a list/tuple of strings");
90 return NULL;
91 }
92}
93
94PyObject* PyMznSolver::next() {
95 if (solver == NULL) throw runtime_error("Solver Object not found");
96 GCLock lock;
97 SolverInstance::Status status = solver->solve();
98 if (status == SolverInstance::SAT || status == SolverInstance::OPT) {
99 _m = env->output();
100 Py_RETURN_NONE;
101 }
102 if (_m == NULL)
103 return PyUnicode_FromString("Unsatisfied");
104 else
105 return PyUnicode_FromString("Reached last solution");
106}
107
108static void PyMznSolver_dealloc(PyMznSolver* self) {
109 if (self->env) delete self->env;
110 if (self->solver) delete self->solver;
111 Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
112}
113
114static PyObject* PyMznSolver_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
115 PyMznSolver* self = reinterpret_cast<PyMznSolver*>(type->tp_alloc(type, 0));
116 self->solver = NULL;
117 self->_m = NULL;
118 self->env = NULL;
119 return reinterpret_cast<PyObject*>(self);
120}
121
122static int PyMznSolver_init(PyMznSolver* self, PyObject* args) { return 0; }
123
124static PyObject* PyMznSolver_next(PyMznSolver* self) { return self->next(); }