1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker f2a1c4e389 Squashed 'software/mza/' content from commit f970a59b17
git-subtree-dir: software/mza
git-subtree-split: f970a59b177c13ca3dd8aaef8cc6681d83b7e813
2021-07-11 16:34:30 +10:00

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