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#ifndef __MZNSET_H
9#define __MZNSET_H
10
11#include "Object.h"
12
13#include <exception>
14#include <list>
15#include <vector>
16
17#if PY_MAJOR_VERSION >= 3
18#define Py_TPFLAGS_HAVE_ITER 0
19#endif
20
21using namespace std;
22using namespace MiniZinc;
23
24struct MznRange {
25 long long min;
26 long long max;
27 MznRange(long long min, long long max) : min(min), max(max) {}
28};
29
30/*
31 * My custom defined Set
32 *
33 * MznSet_init and MznSet_push take a variable list of arguments:
34 * (item1, item2, ..., itemn)
35 * For each item, it can be either a value or a list/tuple of min and max values:
36 * item? = 1,4 or 5 ....
37 * or item? = [1,10] or [5,6]
38 * or item? = (1,10) or (5,6)
39 * For example, a Set of 1..5, 7, 10..15 can be defined like this:
40 * minizinc_internal.Set( [1,5], 7, [10,15] )
41 *
42 * The set will automatically merge ranges if it can.
43 *
44 * XXX: should a Set of {1,2,6,35} be written as 1..2, 6, 35
45 * or 1, 2, 6, 35?
46 */
47
48struct MznSet : MznObject {
49 list<MznRange>* ranges;
50
51 void clear() { ranges->clear(); }
52
53 void push(long long min, long long max);
54 void push(long long v);
55
56 long long min();
57 long long max();
58
59 long long size() { return ranges->size(); }
60 bool continuous();
61 bool contains(long long val);
62
63 // Requires an outer GC Lock
64 Expression* e() {
65 vector<IntSetVal::Range> setRanges;
66 for (list<MznRange>::const_iterator it = ranges->begin(); it != ranges->end(); ++it) {
67 setRanges.push_back(IntSetVal::Range(IntVal(it->min), IntVal(it->max)));
68 }
69 Expression* rhs = new SetLit(Location(), IntSetVal::a(setRanges));
70 return rhs;
71 }
72};
73
74enum Mzn_PyContainer_Type { MZN_T_LIST, MZN_T_TUPLE, MZN_T_OTHER };
75
76inline Mzn_PyContainer_Type Mzn_PyContainer_Check(PyObject* o) {
77 if (PyList_Check(o))
78 return MZN_T_LIST;
79 else if (PyTuple_Check(o))
80 return MZN_T_TUPLE;
81 else
82 return MZN_T_OTHER;
83}
84
85inline Py_ssize_t Mzn_PyContainer_Size(PyObject* o, Mzn_PyContainer_Type t) {
86 switch (t) {
87 case MZN_T_LIST:
88 return PyList_Size(o);
89 case MZN_T_TUPLE:
90 return PyTuple_Size(o);
91 default:
92 return -1;
93 }
94}
95
96inline PyObject* Mzn_PyContainer_GetItem(PyObject* o, Py_ssize_t i, Mzn_PyContainer_Type t) {
97 switch (t) {
98 case MZN_T_LIST:
99 return PyList_GetItem(o, i);
100 case MZN_T_TUPLE:
101 return PyTuple_GetItem(o, i);
102 default:
103 return NULL;
104 }
105}
106
107// Set representation on terminal command
108// XXX: should be redefined as MznSet_str
109static PyObject* MznSet_repr(PyObject* self);
110
111// Push accepts 1 argument, which is exactly like the Set initialization
112static PyObject* MznSet_push(MznSet* self, PyObject* args);
113static PyObject* MznSet_output(MznSet* self);
114static PyObject* MznSet_min(MznSet* self);
115static PyObject* MznSet_max(MznSet* self);
116static PyObject* MznSet_continuous(MznSet* self);
117static PyObject* MznSet_contains(MznSet* self, PyObject* args);
118static PyObject* MznSet_clear(MznSet* self);
119
120static int MznSet_init(MznSet* self, PyObject* args);
121static PyObject* MznSet_new(PyTypeObject* type, PyObject* args, PyObject* kwds);
122static void MznSet_dealloc(MznSet* self);
123static PyObject* MznSet_iter(PyObject* self);
124
125static PyMethodDef MznSet_methods[] = {
126 {"output", (PyCFunction)MznSet_output, METH_NOARGS, "Return all values in the set"},
127 {"push", (PyCFunction)MznSet_push, METH_VARARGS, "Expand the set"},
128 {"min", (PyCFunction)MznSet_min, METH_NOARGS, "Lower bound of the set"},
129 {"max", (PyCFunction)MznSet_max, METH_NOARGS, "Upper bound of the set"},
130 {"continuous", (PyCFunction)MznSet_continuous, METH_NOARGS,
131 "Check whether the set is continous"},
132 {"contains", (PyCFunction)MznSet_contains, METH_VARARGS,
133 "Check whether a python value is in the Set"},
134 {"clear", (PyCFunction)MznSet_clear, METH_NOARGS, "Clear the set"},
135 {NULL} /* Sentinel */
136};
137
138static PyMemberDef MznSet_members[] = {
139 {NULL} /* Sentinel */
140};
141
142static PyTypeObject MznSet_Type = {
143 PyVarObject_HEAD_INIT(NULL, 0) "minizinc.Set", /* tp_name */
144 sizeof(MznSet), /* tp_basicsize */
145 0, /* tp_itemsize */
146 (destructor)MznSet_dealloc, /* tp_dealloc */
147 0, /* tp_print */
148 0, /* tp_getattr */
149 0, /* tp_setattr */
150 0, /* tp_reserved */
151 MznSet_repr, /* tp_repr */
152 0, /* tp_as_number */
153 0, /* tp_as_sequence */
154 0, /* tp_as_mapping */
155 0, /* tp_hash */
156 0, /* tp_call */
157 0, /* tp_str */
158 0, /* tp_getattro */
159 0, /* tp_setattro */
160 0, /* tp_as_buffer */
161 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_flags */
162 "Minizinc Set Object", /* tp_doc */
163 0, /* tp_traverse */
164 0, /* tp_clear */
165 0, /* tp_richcompare */
166 0, /* tp_weaklistoffset */
167 MznSet_iter, /* tp_iter */
168 0, /* tp_iternext */
169 MznSet_methods, /* tp_methods */
170 MznSet_members, /* tp_members */
171 0, /* tp_getset */
172 &MznObject_Type, /* tp_base */
173 0, /* tp_dict */
174 0, /* tp_descr_get */
175 0, /* tp_descr_set */
176 0, /* tp_dictoffset */
177 (initproc)MznSet_init, /* tp_init */
178 0, /* tp_alloc */
179 MznSet_new, /* tp_new */
180};
181
182struct MznSetIter {
183 // To support python iteration
184 PyObject_HEAD list<MznRange>::const_iterator listIndex;
185 list<MznRange>::const_iterator listBegin;
186 list<MznRange>::const_iterator listEnd;
187 long long currentValue;
188};
189
190static PyObject* MznSetIter_new(PyTypeObject* type, PyObject* args, PyObject* kwds);
191static void MznSetIter_dealloc(MznSetIter* self);
192static PyObject* MznSetIter_iternext(PyObject* self);
193
194static PyTypeObject MznSetIter_Type = {
195 PyVarObject_HEAD_INIT(NULL, 0) "minizinc.SetIterator", /* tp_name */
196 sizeof(MznSetIter), /* tp_basicsize */
197 0, /* tp_itemsize */
198 (destructor)MznSetIter_dealloc, /* tp_dealloc */
199 0, /* tp_print */
200 0, /* tp_getattr */
201 0, /* tp_setattr */
202 0, /* tp_reserved */
203 0, /* tp_repr */
204 0, /* tp_as_number */
205 0, /* tp_as_sequence */
206 0, /* tp_as_mapping */
207 0, /* tp_hash */
208 0, /* tp_call */
209 0, /* tp_str */
210 0, /* tp_getattro */
211 0, /* tp_setattro */
212 0, /* tp_as_buffer */
213 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /* tp_flags */
214 "Minizinc Set Iterator", /* tp_doc */
215 0, /* tp_traverse */
216 0, /* tp_clear */
217 0, /* tp_richcompare */
218 0, /* tp_weaklistoffset */
219 PyObject_SelfIter, /* tp_iter */
220 (iternextfunc)MznSetIter_iternext, /* tp_iternext */
221 0, /* tp_methods */
222 0, /* tp_members */
223 0, /*MznModel_getseters, /* tp_getset */
224 0, /* tp_base */
225 0, /* tp_dict */
226 0, /* tp_descr_get */
227 0, /* tp_descr_set */
228 0, /* tp_dictoffset */
229 0, /* tp_init */
230 0, /* tp_alloc */
231 0, /* tp_new */
232};
233
234#endif