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(); }