Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
13 kB · 385 lines
C++
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386/* Python Interface for MiniZinc constraint modelling * Author: * Tai Tran <tai.tran@student.adelaide.edu.au> * Supervisor: * Guido Tack <guido.tack@monash.edu> */
#include "pyinterface.h"
using namespace MiniZinc;using namespace std;
static PyObject* Mzn_Call(PyObject* self, PyObject* args) { const char* name; PyObject* variableTuple; PyTypeObject* returnType; if (!PyArg_ParseTuple(args, "sO|O", &name, &variableTuple, &returnType)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_Call: Accepts 2 values: a string, a list of minizinc variable"); PyErr_Print(); return NULL; }
if (!PyList_Check(variableTuple)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_Call: Second argument must be a list"); return NULL; }
long len = PyList_GET_SIZE(variableTuple); vector<Expression*> expressionList(len); for (long i = 0; i != len; ++i) { PyObject* pyval = PyList_GET_ITEM(variableTuple, i); if (PyObject_TypeCheck(pyval, &MznObject_Type)) { expressionList[i] = MznObject_get_e(reinterpret_cast<MznObject*>(pyval)); } else { Type type; vector<pair<int, int> > dimList; expressionList[i] = python_to_minizinc(pyval, type, dimList); if (expressionList[i] == NULL) { MZN_PYERR_SET_STRING(PyExc_RuntimeError, "MiniZinc: MznCall: Second argument, item at position %li must be a " "MiniZinc Object or Python int/float/string/list/tuple", i); return NULL; } } }
PyObject* ret = MznExpression_new(&MznExpression_Type, NULL, NULL);
reinterpret_cast<MznExpression*>(ret)->e = new Call(Location(), string(name), expressionList);
return ret;}
static PyObject* Mzn_Id(PyObject* self, PyObject* args) { const char* name; if (!PyArg_ParseTuple(args, "s", &name)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_Id: Argument must be a string"); return NULL; } PyObject* ret = MznExpression_new(&MznExpression_Type, NULL, NULL); reinterpret_cast<MznExpression*>(ret)->e = new Id(Location(), name, NULL); return ret;}
static PyObject* Mzn_at(PyObject* self, PyObject* args) { PyObject* Py_array; PyObject* Py_idx; if (!PyArg_ParseTuple(args, "OO", &Py_array, &Py_idx)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: at: Parsing error"); return NULL; }
if (!PyObject_TypeCheck(Py_array, &MznExpression_Type)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: at: First argument must be a MiniZinc Expression"); return NULL; }
if (!PyList_Check(Py_idx)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: at: Second argument must be a list of indices"); return NULL; }
Py_ssize_t n = PyList_GET_SIZE(Py_idx);
vector<Expression*> idx(n); for (Py_ssize_t i = 0; i != n; ++i) { PyObject* obj = PyList_GetItem(Py_idx, i);#if PY_MAJOR_VERSION < 3 if (PyInt_Check(obj)) { long index = PyInt_AS_LONG(obj); idx[i] = IntLit::a(IntVal(index)); } else#endif if (PyLong_Check(obj)) { int overflow; long long index = PyLong_AsLongLongAndOverflow(obj, &overflow); if (overflow) { MZN_PYERR_SET_STRING(PyExc_OverflowError, "MiniZinc: at: Index at pos %li overflowed", i); return NULL; } idx[i] = IntLit::a(IntVal(index)); } else if (PyObject_TypeCheck(obj, &MznExpression_Type)) { idx[i] = reinterpret_cast<MznExpression*>(obj)->e; } else { PyErr_SetString(PyExc_TypeError, "MiniZinc: ArrayAccess: Indices must be integers or MiniZinc Expression"); return NULL; } }
MznExpression* ret = reinterpret_cast<MznExpression*>(MznExpression_new(&MznExpression_Type, NULL, NULL)); ret->e = new ArrayAccess(Location(), reinterpret_cast<MznExpression*>(Py_array)->e, idx); return reinterpret_cast<PyObject*>(ret);}
static PyObject* Mzn_UnOp(PyObject* self, PyObject* args) { /* enum UnOpType { UOT_NOT, // 0 UOT_PLUS, // 1 UOT_MINUS // 2 };*/ PyObject* r; unsigned int op; if (!PyArg_ParseTuple(args, "IO", &op, &r)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_UnOp: Requires a MiniZinc object and an integer"); return NULL; } Expression* rhs;
if (PyObject_TypeCheck(r, &MznExpression_Type)) { rhs = reinterpret_cast<MznExpression*>(r)->e; } else if (PyBool_Check(r)) { rhs = new BoolLit(Location(), PyObject_IsTrue(r)); } else#if PY_MAJOR_VERSION < 3 if (PyInt_Check(r)) { rhs = IntLit::a(IntVal(PyInt_AS_LONG(r))); } else#endif if (PyLong_Check(r)) { int overflow; long long c_val = PyLong_AsLongLongAndOverflow(r, &overflow); if (overflow) { PyErr_SetString(PyExc_OverflowError, "MiniZinc: Mzn_UnOp: Object is overflowed"); return NULL; } rhs = IntLit::a(IntVal(c_val)); } else if (PyFloat_Check(r)) { rhs = new FloatLit(Location(), PyFloat_AS_DOUBLE(r)); } else if (PyUnicode_Check(r)) { rhs = new StringLit(Location(), string(PyUnicode_AsUTF8(r))); } else { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_UnOp: Object must be a Python value or a MiniZinc object"); return NULL; }
GCLock Lock;
PyObject* ret = MznExpression_new(&MznExpression_Type, NULL, NULL); reinterpret_cast<MznExpression*>(ret)->e = new UnOp(Location(), static_cast<UnOpType>(op), rhs); return ret;}
/* * Description: Creates a minizinc BinOp expression * Note: Need an outer GCLock for this to work */static PyObject* Mzn_BinOp(PyObject* self, PyObject* args) { /* enum BinOpType { BOT_PLUS, // 0 BOT_MINUS, // 1 BOT_MULT, // 2 BOT_DIV, // 3 BOT_IDIV, // 4 BOT_MOD, // 5 BOT_LE, // 6 BOT_LQ, // 7 BOT_GR, // 8 BOT_GQ, // 9 BOT_EQ, //10 BOT_NQ, //11 BOT_IN, //12 BOT_SUBSET, //13 BOT_SUPERSET, //14 BOT_UNION, //15 BOT_DIFF, //16 BOT_SYMDIFF, //17 BOT_INTERSECT, //18 BOT_PLUSPLUS, //19 BOT_EQUIV, //20 BOT_IMPL, //21 BOT_RIMPL, //22 BOT_OR, //23 BOT_AND, //24 BOT_XOR, //25 BOT_DOTDOT //26 };*/ PyObject* PyPre[2]; unsigned int op; if (!PyArg_ParseTuple(args, "OIO", &PyPre[0], &op, &PyPre[1])) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_BinOp: Requires two MiniZinc objects and an integer"); return NULL; } Expression* pre[2]; // pre[0]: lhs; // pre[1]: rhs; for (int i = 0; i != 2; ++i) { if (PyObject_TypeCheck(PyPre[i], &MznExpression_Type)) { pre[i] = reinterpret_cast<MznExpression*>(PyPre[i])->e; } else if (PyBool_Check(PyPre[i])) { pre[i] = new BoolLit(Location(), PyObject_IsTrue(PyPre[i])); } else#if PY_MAJOR_VERSION < 3 if (PyInt_Check(PyPre[i])) { pre[i] = IntLit::a(IntVal(PyInt_AS_LONG(PyPre[i]))); } else#endif
if (PyLong_Check(PyPre[i])) { int overflow; long long c_val = PyLong_AsLongLongAndOverflow(PyPre[i], &overflow); if (overflow) { PyErr_SetString(PyExc_OverflowError, "MiniZinc: Mzn_UnOp: Object is overflowed"); return NULL; } pre[i] = IntLit::a(IntVal(c_val)); } else if (PyFloat_Check(PyPre[i])) { pre[i] = new FloatLit(Location(), PyFloat_AS_DOUBLE(PyPre[i])); } else if (PyUnicode_Check(PyPre[i])) { pre[i] = new StringLit(Location(), string(PyUnicode_AsUTF8(PyPre[i]))); } else { if (i == 0) PyErr_SetString( PyExc_TypeError, "MiniZinc: Mzn_BinOp: Left hand side object must be a Python value or MiniZinc object"); else PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_BinOp: Right hand side object must be a Python value or " "MiniZinc object"); return NULL; } }
GCLock Lock;
PyObject* ret = MznExpression_new(&MznExpression_Type, NULL, NULL); reinterpret_cast<MznExpression*>(ret)->e = (new BinOp(Location(), pre[0], static_cast<BinOpType>(op), pre[1])); return ret;}
static PyObject* Mzn_load(PyObject* self, PyObject* args, PyObject* keywds) { PyObject* model = MznModel_new(&MznModel_Type, NULL, NULL); if (MznModel_init(reinterpret_cast<MznModel*>(model), NULL) < 0) return NULL; if (MznModel_load(reinterpret_cast<MznModel*>(model), args, keywds) == NULL) return NULL; return model;}
static PyObject* Mzn_load_from_string(PyObject* self, PyObject* args, PyObject* keywds) { PyObject* model = MznModel_new(&MznModel_Type, NULL, NULL); if (model == NULL) return NULL; if (MznModel_init(reinterpret_cast<MznModel*>(model), NULL) < 0) return NULL; if (MznModel_load_from_string(reinterpret_cast<MznModel*>(model), args, keywds) == NULL) return NULL; return model;}
static PyObject* Mzn_retrieveNames(PyObject* self, PyObject* args) { PyObject* boolfuncs = PyDict_New(); PyObject* annfuncs = PyDict_New(); PyObject* annvars = PyList_New(0); PyObject* libName = NULL;
{ Py_ssize_t n = PyTuple_GET_SIZE(args); if (n > 1) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_retrieveNames: accepts at most 1 argument"); return NULL; } else if (n == 1) { libName = PyTuple_GET_ITEM(args, 0); if (PyObject_IsTrue(libName)) { if (!PyUnicode_Check(libName)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Mzn_retrieveNames: first argument must be a string"); return NULL; } } else libName = NULL; } }
// If a library name is specified here, it means that this function is called at least once // already. If that's the case, functions in globals.mzn and stdlib.mzn will be already defined, // so we dont want to reinclude it bool include_global_mzn = (libName == NULL);
MznModel* tempModel = reinterpret_cast<MznModel*>(MznModel_new(&MznModel_Type, NULL, NULL));
if (MznModel_init(tempModel, libName) != 0) { return NULL; } CollectBoolFuncNames bool_fv(boolfuncs, include_global_mzn); CollectAnnNames ann_fv(annfuncs, annvars, include_global_mzn); iterItems(bool_fv, tempModel->_m); iterItems(ann_fv, tempModel->_m); MznModel_dealloc(tempModel);
PyObject* dict = PyDict_New(); PyDict_SetItemString(dict, "boolfuncs", boolfuncs); PyDict_SetItemString(dict, "annfuncs", annfuncs); PyDict_SetItemString(dict, "annvars", annvars);
Py_DECREF(boolfuncs); Py_DECREF(annfuncs); Py_DECREF(annvars); return dict;}
#if PY_MAJOR_VERSION >= 3
#define INITERROR return NULL
// PyObject*PyMODINIT_FUNC PyInit_minizinc_internal(void)#else#define INITERROR return
PyMODINIT_FUNC initminizinc_internal(void)
#endif
{#if PY_MAJOR_VERSION >= 3 PyObject* module = PyModule_Create(&moduledef);#else PyObject* module = Py_InitModule3("minizinc_internal", Mzn_methods, "A python interface for MiniZinc constraint modeling");#endif
if (module == NULL) INITERROR;
if (PyType_Ready(&MznObject_Type) < 0) INITERROR; Py_INCREF(&MznObject_Type); PyModule_AddObject(module, "Object", reinterpret_cast<PyObject*>(&MznObject_Type));
if (PyType_Ready(&MznSetIter_Type) < 0) INITERROR; Py_INCREF(&MznSetIter_Type); PyModule_AddObject(module, "Set_Iter", reinterpret_cast<PyObject*>(&MznSetIter_Type));
if (PyType_Ready(&MznExpression_Type) < 0) INITERROR; Py_INCREF(&MznExpression_Type); PyModule_AddObject(module, "Expression", reinterpret_cast<PyObject*>(&MznExpression_Type));
if (PyType_Ready(&MznAnnotation_Type) < 0) INITERROR; Py_INCREF(&MznAnnotation_Type); PyModule_AddObject(module, "Annotation", reinterpret_cast<PyObject*>(&MznAnnotation_Type));
if (PyType_Ready(&MznSet_Type) < 0) INITERROR; Py_INCREF(&MznSet_Type); PyModule_AddObject(module, "Set", reinterpret_cast<PyObject*>(&MznSet_Type));
if (PyType_Ready(&MznVarSet_Type) < 0) INITERROR; Py_INCREF(&MznVarSet_Type); PyModule_AddObject(module, "VarSet", reinterpret_cast<PyObject*>(&MznVarSet_Type));
if (PyType_Ready(&MznModel_Type) < 0) INITERROR; Py_INCREF(&MznModel_Type); PyModule_AddObject(module, "Model", reinterpret_cast<PyObject*>(&MznModel_Type));
if (PyType_Ready(&PyMznSolver_Type) < 0) INITERROR; Py_INCREF(&PyMznSolver_Type); PyModule_AddObject(module, "Solver", reinterpret_cast<PyObject*>(&PyMznSolver_Type));
#if PY_MAJOR_VERSION >= 3 return module;#endif}