Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
9.7 kB · 327 lines
C++
at develop
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327/* Python Interface for MiniZinc constraint modelling * Author: * Tai Tran <tai.tran@student.adelaide.edu.au> * Supervisor: * Guido Tack <guido.tack@monash.edu> */
#include "Set.h"
static void MznSet_dealloc(MznSet* self) { delete self->ranges; Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));}
static PyObject* MznSet_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { MznSet* self = reinterpret_cast<MznSet*>(type->tp_alloc(type, 0)); self->ranges = new list<MznRange>; self->tid = MOC_SET; return reinterpret_cast<PyObject*>(self);}
static PyObject* MznSet_iter(PyObject* self) { MznSetIter* iter = reinterpret_cast<MznSetIter*>(MznSetIter_new(&MznSetIter_Type, NULL, NULL)); iter->listBegin = reinterpret_cast<MznSet*>(self)->ranges->begin(); iter->listEnd = reinterpret_cast<MznSet*>(self)->ranges->end(); iter->listIndex = iter->listBegin; iter->currentValue = iter->listBegin->min; return reinterpret_cast<PyObject*>(iter);}
bool MznSet::contains(long long val) { list<MznRange>::iterator it = ranges->begin(); list<MznRange>::iterator end = ranges->end(); assert(it != end); for (; it++ != end;) if (val < it->min) return false; else if (val <= it->max) return true; return false;}
bool MznSet::continuous() { if (ranges->empty()) throw length_error("Ranges cannot be empty"); else { // returning ranges.size() == 1, with O(1) time complexity list<MznRange>::iterator it = ranges->begin(); return ++it == ranges->end(); }}
void MznSet::push(long long min, long long max) { if (ranges->empty()) { MznRange toAdd(min, max); ranges->push_front(toAdd); return; } list<MznRange>::iterator it, last; for (it = ranges->begin(); it != ranges->end(); ++it) { if (min <= it->max + 1) { if (it->min < min) min = it->min; if (max <= it->max) { ranges->insert(it, MznRange(min, max)); return; } goto FOUNDMIN; } continue; FOUNDMIN: last = it; while (++it != ranges->end()) { if (max < it->min - 1) { break; } else { ranges->erase(last); last = it; if (max <= it->max) { break; } else ++it; } } last->min = min; last->max = max; return; } ranges->push_back(MznRange(min, max));}
void MznSet::push(long long v) { list<MznRange>::iterator it, last; last = ranges->begin(); if (ranges->empty()) { MznRange toAdd(v, v); ranges->push_front(toAdd); return; } for (it = last; it != ranges->end(); ++it) { if (v < it->min) { if (v == it->min - 1) { it->min = v; if (last->max == v) { last->max = it->max; ranges->erase(it); return; } } else { // if (last->max < v) { MznRange toAdd(v, v); ranges->insert(it, toAdd); } return; } } else if (v > it->max) { if (v == it->max + 1) { it->max = v; } last = it; continue; } else { return; } } if (last->max < v) { MznRange toAdd(v, v); ranges->insert(it, toAdd); } return;}
long long MznSet::min() { assert(ranges->begin() != ranges->end()); return ranges->front().min;}
long long MznSet::max() { assert(ranges->begin() != ranges->end()); return ranges->back().max;}
static PyObject* MznSet_min(MznSet* self) { return c_to_py_number(self->min()); }
static PyObject* MznSet_max(MznSet* self) { return c_to_py_number(self->max()); }
static PyObject* MznSet_continuous(MznSet* self) { return PyBool_FromLong(self->continuous()); }
static PyObject* MznSet_contains(MznSet* self, PyObject* args) { PyObject* py_val; if (!PyArg_ParseTuple(args, "O", &py_val)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Set.contains: Parsing error"); return NULL; } long long c_val = py_to_c_number(py_val); if (PyErr_Occurred()) { PyObject *ptype, *pmessage, *ptraceback; PyErr_Fetch(&ptype, &pmessage, &ptraceback); const char* pStrErrorMessage = PyUnicode_AsUTF8(pmessage); string error = "MiniZinc: Set.contains: " + string(pStrErrorMessage); PyErr_SetString(ptype, error.c_str()); return NULL; }
return PyBool_FromLong(self->contains(c_val));}
static PyObject* MznSet_push(MznSet* self, PyObject* isv) { /*PyObject* isv; if (!PyArg_ParseTuple(args,"O",&isv)) { PyErr_SetString(PyExc_TypeError, "MiniZinc: Set.push: Parsing error"); return NULL; }*/ // if (isv == NULL) // Py_RETURN_NONE;
Py_ssize_t size = PyTuple_Size(isv);
for (Py_ssize_t i = 0; i != size; ++i) { PyObject* elem = PyTuple_GetItem(isv, i);
Mzn_PyContainer_Type elem_type = Mzn_PyContainer_Check(elem); Py_ssize_t elem_size = Mzn_PyContainer_Size(elem, elem_type);
switch (elem_size) { // elem_size == -1 means it is neither list nor tuple case -1: { int overflow; long long c_val = py_to_c_number(elem, &overflow); if (PyErr_Occurred()) { if (overflow) { MZN_PYERR_SET_STRING(PyExc_OverflowError, "MiniZinc: Set.push: Overflow at tuple element at pos %li", i); return NULL; } else { MZN_PYERR_SET_STRING(PyExc_TypeError, "MiniZinc: Set.push: Type mismatched at tuple element pos %li: " "expected an integer or list of integers", i); return NULL; } } self->push(c_val); break; } case 1: { PyObject* py_val = Mzn_PyContainer_GetItem(elem, 0, elem_type); long long c_val = py_to_c_number(py_val); if (PyErr_Occurred()) { PyObject *ptype, *pmessage, *ptraceback; PyErr_Fetch(&ptype, &pmessage, &ptraceback); const char* pStrErrorMessage = PyUnicode_AsUTF8(pmessage); string error = "MiniZinc: Set.push: tuple item %li: " + string(pStrErrorMessage); MZN_PYERR_SET_STRING(ptype, error.c_str(), i); return NULL; } self->push(c_val); break; } case 2: { PyObject* p_min = Mzn_PyContainer_GetItem(elem, 0, elem_type); PyObject* p_max = Mzn_PyContainer_GetItem(elem, 1, elem_type); long long c_min = py_to_c_number(p_min); if (PyErr_Occurred()) { PyObject *ptype, *pmessage, *ptraceback; PyErr_Fetch(&ptype, &pmessage, &ptraceback); const char* pStrErrorMessage = PyUnicode_AsUTF8(pmessage); string error = "MiniZinc: Set.push: tuple item %li, first argument: " + string(pStrErrorMessage); MZN_PYERR_SET_STRING(ptype, error.c_str(), i); return NULL; }
long long c_max = py_to_c_number(p_max); if (PyErr_Occurred()) { PyObject *ptype, *pmessage, *ptraceback; PyErr_Fetch(&ptype, &pmessage, &ptraceback); const char* pStrErrorMessage = PyUnicode_AsUTF8(pmessage); string error = "MiniZinc: Set.push: tuple item %li, second argument: " + string(pStrErrorMessage); MZN_PYERR_SET_STRING(ptype, error.c_str(), i); return NULL; }
if (c_min < c_max) self->push(c_min, c_max); else if (c_min > c_max) self->push(c_max, c_min); else self->push(c_min); break; } default: PyErr_SetString(PyExc_TypeError, "MiniZinc: Set.push: The sublist size can only be 1 or 2"); return NULL; } } Py_RETURN_NONE;}
static int MznSet_init(MznSet* self, PyObject* args) { if (MznSet_push(self, args) == NULL) return -1; return 0;}
static PyObject* MznSet_clear(MznSet* self) { self->clear(); Py_RETURN_NONE;}
static PyObject* MznSet_output(MznSet* self) { stringstream s; for (list<MznRange>::iterator it = self->ranges->begin(); it != self->ranges->end(); ++it) { s << it->min << ".." << it->max << " "; } const std::string& tmp = s.str(); const char* cstr = tmp.c_str(); PyObject* result = PyUnicode_FromString(cstr); return result;}
static PyObject* MznSet_repr(PyObject* self) { stringstream output; list<MznRange>* r = (reinterpret_cast<MznSet*>(self))->ranges; if (r->begin() == r->end()) output << "Empty Set"; else for (list<MznRange>::iterator it = r->begin();;) { if (it->min == it->max) output << it->min; else output << it->min << ".." << it->max; if (++it == r->end()) break; else output << ", "; } const std::string& tmp = output.str(); return PyUnicode_FromString(tmp.c_str());}
static void MznSetIter_dealloc(MznSetIter* self) { Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));}
static PyObject* MznSetIter_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { return type->tp_alloc(type, 0);}
static PyObject* MznSetIter_iternext(PyObject* self) { MznSetIter* iter = reinterpret_cast<MznSetIter*>(self); if (iter->listIndex == iter->listEnd) { iter->listIndex = iter->listBegin; iter->currentValue = iter->listBegin->min; PyErr_SetNone(PyExc_StopIteration); return NULL; } else { PyObject* result = c_to_py_number(iter->currentValue); iter->currentValue++; if (iter->currentValue > iter->listIndex->max) { iter->listIndex++; if (iter->listIndex != iter->listEnd) iter->currentValue = iter->listIndex->min; } return result; }}