git-subtree-dir: software/mza git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
234 lines
9.3 KiB
C++
234 lines
9.3 KiB
C++
/* Python Interface for MiniZinc constraint modelling
|
|
* Author:
|
|
* Tai Tran <tai.tran@student.adelaide.edu.au>
|
|
* Supervisor:
|
|
* Guido Tack <guido.tack@monash.edu>
|
|
*/
|
|
|
|
#ifndef __MZNSET_H
|
|
#define __MZNSET_H
|
|
|
|
#include "Object.h"
|
|
|
|
#include <exception>
|
|
#include <list>
|
|
#include <vector>
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
#define Py_TPFLAGS_HAVE_ITER 0
|
|
#endif
|
|
|
|
using namespace std;
|
|
using namespace MiniZinc;
|
|
|
|
struct MznRange {
|
|
long long min;
|
|
long long max;
|
|
MznRange(long long min, long long max) : min(min), max(max) {}
|
|
};
|
|
|
|
/*
|
|
* My custom defined Set
|
|
*
|
|
* MznSet_init and MznSet_push take a variable list of arguments:
|
|
* (item1, item2, ..., itemn)
|
|
* For each item, it can be either a value or a list/tuple of min and max values:
|
|
* item? = 1,4 or 5 ....
|
|
* or item? = [1,10] or [5,6]
|
|
* or item? = (1,10) or (5,6)
|
|
* For example, a Set of 1..5, 7, 10..15 can be defined like this:
|
|
* minizinc_internal.Set( [1,5], 7, [10,15] )
|
|
*
|
|
* The set will automatically merge ranges if it can.
|
|
*
|
|
* XXX: should a Set of {1,2,6,35} be written as 1..2, 6, 35
|
|
* or 1, 2, 6, 35?
|
|
*/
|
|
|
|
struct MznSet : MznObject {
|
|
list<MznRange>* ranges;
|
|
|
|
void clear() { ranges->clear(); }
|
|
|
|
void push(long long min, long long max);
|
|
void push(long long v);
|
|
|
|
long long min();
|
|
long long max();
|
|
|
|
long long size() { return ranges->size(); }
|
|
bool continuous();
|
|
bool contains(long long val);
|
|
|
|
// Requires an outer GC Lock
|
|
Expression* e() {
|
|
vector<IntSetVal::Range> setRanges;
|
|
for (list<MznRange>::const_iterator it = ranges->begin(); it != ranges->end(); ++it) {
|
|
setRanges.push_back(IntSetVal::Range(IntVal(it->min), IntVal(it->max)));
|
|
}
|
|
Expression* rhs = new SetLit(Location(), IntSetVal::a(setRanges));
|
|
return rhs;
|
|
}
|
|
};
|
|
|
|
enum Mzn_PyContainer_Type { MZN_T_LIST, MZN_T_TUPLE, MZN_T_OTHER };
|
|
|
|
inline Mzn_PyContainer_Type Mzn_PyContainer_Check(PyObject* o) {
|
|
if (PyList_Check(o))
|
|
return MZN_T_LIST;
|
|
else if (PyTuple_Check(o))
|
|
return MZN_T_TUPLE;
|
|
else
|
|
return MZN_T_OTHER;
|
|
}
|
|
|
|
inline Py_ssize_t Mzn_PyContainer_Size(PyObject* o, Mzn_PyContainer_Type t) {
|
|
switch (t) {
|
|
case MZN_T_LIST:
|
|
return PyList_Size(o);
|
|
case MZN_T_TUPLE:
|
|
return PyTuple_Size(o);
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
inline PyObject* Mzn_PyContainer_GetItem(PyObject* o, Py_ssize_t i, Mzn_PyContainer_Type t) {
|
|
switch (t) {
|
|
case MZN_T_LIST:
|
|
return PyList_GetItem(o, i);
|
|
case MZN_T_TUPLE:
|
|
return PyTuple_GetItem(o, i);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Set representation on terminal command
|
|
// XXX: should be redefined as MznSet_str
|
|
static PyObject* MznSet_repr(PyObject* self);
|
|
|
|
// Push accepts 1 argument, which is exactly like the Set initialization
|
|
static PyObject* MznSet_push(MznSet* self, PyObject* args);
|
|
static PyObject* MznSet_output(MznSet* self);
|
|
static PyObject* MznSet_min(MznSet* self);
|
|
static PyObject* MznSet_max(MznSet* self);
|
|
static PyObject* MznSet_continuous(MznSet* self);
|
|
static PyObject* MznSet_contains(MznSet* self, PyObject* args);
|
|
static PyObject* MznSet_clear(MznSet* self);
|
|
|
|
static int MznSet_init(MznSet* self, PyObject* args);
|
|
static PyObject* MznSet_new(PyTypeObject* type, PyObject* args, PyObject* kwds);
|
|
static void MznSet_dealloc(MznSet* self);
|
|
static PyObject* MznSet_iter(PyObject* self);
|
|
|
|
static PyMethodDef MznSet_methods[] = {
|
|
{"output", (PyCFunction)MznSet_output, METH_NOARGS, "Return all values in the set"},
|
|
{"push", (PyCFunction)MznSet_push, METH_VARARGS, "Expand the set"},
|
|
{"min", (PyCFunction)MznSet_min, METH_NOARGS, "Lower bound of the set"},
|
|
{"max", (PyCFunction)MznSet_max, METH_NOARGS, "Upper bound of the set"},
|
|
{"continuous", (PyCFunction)MznSet_continuous, METH_NOARGS,
|
|
"Check whether the set is continous"},
|
|
{"contains", (PyCFunction)MznSet_contains, METH_VARARGS,
|
|
"Check whether a python value is in the Set"},
|
|
{"clear", (PyCFunction)MznSet_clear, METH_NOARGS, "Clear the set"},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyMemberDef MznSet_members[] = {
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static PyTypeObject MznSet_Type = {
|
|
PyVarObject_HEAD_INIT(NULL, 0) "minizinc.Set", /* tp_name */
|
|
sizeof(MznSet), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)MznSet_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_reserved */
|
|
MznSet_repr, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_flags */
|
|
"Minizinc Set Object", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
MznSet_iter, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
MznSet_methods, /* tp_methods */
|
|
MznSet_members, /* tp_members */
|
|
0, /* tp_getset */
|
|
&MznObject_Type, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
(initproc)MznSet_init, /* tp_init */
|
|
0, /* tp_alloc */
|
|
MznSet_new, /* tp_new */
|
|
};
|
|
|
|
struct MznSetIter {
|
|
// To support python iteration
|
|
PyObject_HEAD list<MznRange>::const_iterator listIndex;
|
|
list<MznRange>::const_iterator listBegin;
|
|
list<MznRange>::const_iterator listEnd;
|
|
long long currentValue;
|
|
};
|
|
|
|
static PyObject* MznSetIter_new(PyTypeObject* type, PyObject* args, PyObject* kwds);
|
|
static void MznSetIter_dealloc(MznSetIter* self);
|
|
static PyObject* MznSetIter_iternext(PyObject* self);
|
|
|
|
static PyTypeObject MznSetIter_Type = {
|
|
PyVarObject_HEAD_INIT(NULL, 0) "minizinc.SetIterator", /* tp_name */
|
|
sizeof(MznSetIter), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
(destructor)MznSetIter_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_reserved */
|
|
0, /* tp_repr */
|
|
0, /* tp_as_number */
|
|
0, /* tp_as_sequence */
|
|
0, /* tp_as_mapping */
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
0, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_flags */
|
|
"Minizinc Set Iterator", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
PyObject_SelfIter, /* tp_iter */
|
|
(iternextfunc)MznSetIter_iternext, /* tp_iternext */
|
|
0, /* tp_methods */
|
|
0, /* tp_members */
|
|
0, /*MznModel_getseters, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
0, /* tp_new */
|
|
};
|
|
|
|
#endif |