this repo has no description
1/*
2 * Author:
3 * Tai Tran <tai.tran@student.adelaide.edu.au>
4 * Supervisor:
5 * Guido Tack <guido.tack@monash.edu>
6 */
7#ifndef __PYINTERFACE_H
8#define __PYINTERFACE_H
9
10#include "Annotation.h"
11#include "Expression.h"
12#include "Model.cpp"
13#include "Model.h"
14#include "Object.h"
15#include "Set.cpp"
16#include "Set.h"
17#include "Solver.cpp"
18#include "Solver.h"
19#include "VarSet.h"
20#include "global.cpp"
21#include "global.h"
22
23/* Helper functions that load data into a new model
24 * For example: instead of
25 import minizinc_internal
26 model = minizinc_internal.Model()
27 model.load(...)
28 we can do this:
29 import minizinc_internal
30 model = minizinc_internal.load(...)
31 */
32static PyObject* Mzn_load(PyObject* self, PyObject* args, PyObject* keywds);
33static PyObject* Mzn_load_from_string(PyObject* self, PyObject* args, PyObject* keywds);
34
35// GC::lock() and GC::unlock()
36static PyObject* Mzn_lock(PyObject* self) {
37 GC::lock();
38 Py_RETURN_NONE;
39}
40static PyObject* Mzn_unlock(PyObject* self) {
41 GC::unlock();
42 Py_RETURN_NONE;
43}
44
45/************************************************************
46 Groups of function that need an outer GCLock to work
47 ************************************************************/
48// Note: Please see Note 1 of the first python_to_minizinc declaration in global.h first
49
50// Requires:
51// - An UnOpType integer opcode
52// - A MiniZinc expression or Python value
53static PyObject* Mzn_UnOp(PyObject* self, PyObject* args);
54
55// Requires:
56// - A left hand sided MiniZinc expression or Python value
57// - A BinOpType integer opcode
58// - A right hand sided MiniZinc expression or Python value
59static PyObject* Mzn_BinOp(PyObject* self, PyObject* args);
60
61// Requires:
62// - Name of the MiniZinc function to be called (string)
63// - List of MiniZinc object or Python value
64// - (Optional, deprecated) Return type of Mzn_Call
65static PyObject* Mzn_Call(PyObject* self, PyObject* args);
66
67// Requires a name(string)
68static PyObject* Mzn_Id(PyObject* self, PyObject* args);
69// Requires:
70// - A MiniZinc expression of array type
71// - A list of integer indices (can be MiniZinc expression as well)
72static PyObject* Mzn_at(PyObject* self, PyObject* args);
73
74// ***************** END OF GROUPS *****************
75
76/* Definition: Returns a dictionary of keys: "boolfuncs", "annfuncs" and "annvars" (currently)
77 For each '*funcs':
78 Itself is another dictionary:
79 key: name of function
80 value: a list of all possible combination of parsing argument types and return type:
81 for each item in that list:
82 item[0] is a tuple argument types:
83 if a function accepts (int, int), it should be (<type 'long'>, <type 'long'>)
84
85 if a function accepts (array of [int, int]), it should be
86 ( [<type 'long'>, <type 'long'>], )
87 (notice the appearance of a list here)
88 item[1] is the return type:
89 MiniZinc Type - Python Type
90 int - long
91 float - float
92 bool - bool
93 string - str
94 VarSet - minizinc.VarSet
95 Ann - minizinc.Annotation
96 Top - NoneType (accepts everything)
97 others - minizinc.Object (means an error)
98
99 For 'annvars':
100 Just a list of ann names
101
102 */
103static PyObject* Mzn_retrieveNames(PyObject* self, PyObject* args);
104
105/********************* SKIP ******************************* */
106PyObject* eval_type(TypeInst* ti) {
107 ASTExprVec<TypeInst> ranges = ti->ranges();
108 PyObject* v;
109 switch (ti->type().bt()) {
110 case Type::BT_BOOL:
111 v = reinterpret_cast<PyObject*>(&PyBool_Type);
112 break;
113 case Type::BT_INT:
114 if (ti->type().st() == Type::ST_SET)
115 v = reinterpret_cast<PyObject*>(&MznVarSet_Type);
116 else
117 v = reinterpret_cast<PyObject*>(&PyLong_Type);
118 break;
119 case Type::BT_FLOAT:
120 v = reinterpret_cast<PyObject*>(&PyFloat_Type);
121 break;
122 case Type::BT_STRING:
123 v = reinterpret_cast<PyObject*>(&PyUnicode_Type);
124 break;
125 case Type::BT_ANN:
126 v = reinterpret_cast<PyObject*>(&MznAnnotation_Type);
127 break;
128 case Type::BT_TOP:
129 v = Py_None;
130 break;
131 default: // v = reinterpret_cast<PyObject*>(&MznVariable_Type);
132 // cout << ti->type().bt() << endl;
133 v = reinterpret_cast<PyObject*>(&MznObject_Type);
134 break;
135 throw runtime_error("CollectBoolFunctionNames: unexpected type");
136 }
137
138 if (ranges.size() == 0) {
139 Py_INCREF(v);
140 return v;
141 } else {
142 PyObject* args_tuple = PyList_New(ranges.size());
143 for (int i = 0; i != ranges.size(); ++i) {
144 Py_INCREF(v);
145 PyList_SET_ITEM(args_tuple, i, v);
146 }
147 return args_tuple;
148 }
149}
150
151void add_to_dictionary(FunctionI* fi, PyObject* toAdd) {
152 ASTExprVec<VarDecl> params = fi->params();
153 const char* str = fi->id().str().c_str();
154 PyObject* key = PyUnicode_FromString(str);
155
156 PyObject* args_and_return_type_tuple = PyTuple_New(2);
157 PyObject* args_tuple = PyTuple_New(params.size());
158 for (unsigned int i = 0; i < params.size(); ++i) {
159 PyTuple_SET_ITEM(args_tuple, i, eval_type(params[i]->ti()));
160 }
161 PyObject* return_type = eval_type(fi->ti());
162
163 PyTuple_SET_ITEM(args_and_return_type_tuple, 0, args_tuple);
164 PyTuple_SET_ITEM(args_and_return_type_tuple, 1, return_type);
165
166 PyObject* toAdd_item = PyDict_GetItem(toAdd, key);
167 if (toAdd_item == NULL) {
168 toAdd_item = PyList_New(1);
169 PyList_SET_ITEM(toAdd_item, 0, args_and_return_type_tuple);
170 if (PyDict_SetItem(toAdd, key, toAdd_item) != 0)
171 throw runtime_error("CollectBoolFunctionNames: cannot set new key to the dictionary");
172 Py_DECREF(toAdd_item);
173 } else {
174 if (PyList_Append(toAdd_item, args_and_return_type_tuple) != 0)
175 throw runtime_error("CollectBoolFunctionNames: cannot append item to the list");
176 }
177}
178
179class CollectBoolFuncNames : public ItemVisitor {
180protected:
181 bool include_global_mzn;
182 PyObject* _boolfuncs;
183
184public:
185 CollectBoolFuncNames(PyObject* boolfuncs, bool include_global_mzn0)
186 : _boolfuncs(boolfuncs), include_global_mzn(include_global_mzn0) {}
187 bool enterModel(Model* m) {
188 return m->filename() != "stdlib.mzn" && (include_global_mzn || m->filename() != "globals.mzn");
189 }
190 void vFunctionI(FunctionI* fi) {
191 if (fi->ti()->type().isvarbool() == false) return;
192
193 add_to_dictionary(fi, _boolfuncs);
194 }
195};
196
197class CollectAnnNames : public ItemVisitor {
198protected:
199 PyObject* _annfuncs;
200 PyObject* _annvars;
201 bool include_global_mzn;
202
203public:
204 CollectAnnNames(PyObject* annfuncs, PyObject* annvars, bool include_global_mzn0)
205 : _annfuncs(annfuncs), _annvars(annvars), include_global_mzn(include_global_mzn0) {}
206 bool enterModel(Model* m) {
207 return include_global_mzn || (m->filename() != "globals.mzn" && m->filename() != "stdlib.mzn");
208 }
209 void vFunctionI(FunctionI* fi) {
210 if (fi->ti()->type().isann() == false) return;
211
212 add_to_dictionary(fi, _annfuncs);
213 }
214 void vVarDeclI(VarDeclI* vdi) {
215 if (vdi->e()->ti()->type().isann()) {
216 PyList_Append(_annvars, PyUnicode_FromString(vdi->e()->id()->str().c_str()));
217 }
218 }
219};
220
221/********************* END OF SKIP ******************************* */
222
223static PyMethodDef Mzn_methods[] = {
224 {"load", (PyCFunction)Mzn_load, METH_KEYWORDS, "Load MiniZinc model from MiniZinc file"},
225 {"load_from_string", (PyCFunction)Mzn_load_from_string, METH_KEYWORDS,
226 "Load MiniZinc model from stdin"},
227 {"BinOp", (PyCFunction)Mzn_BinOp, METH_VARARGS, "Add a binary expression into the model"},
228 {"UnOp", (PyCFunction)Mzn_UnOp, METH_VARARGS, "Add a unary expression into the model"},
229 {"Id", (PyCFunction)Mzn_Id, METH_VARARGS,
230 "Return a MiniZinc Variable containing the given name"},
231 {"Call", (PyCFunction)Mzn_Call, METH_VARARGS, "MiniZinc Call"},
232
233 {"at", (PyCFunction)Mzn_at, METH_VARARGS, "Array Access"},
234 {"retrieveNames", (PyCFunction)Mzn_retrieveNames, METH_VARARGS,
235 "Returns names of MiniZinc functions and variables"},
236 {"lock", (PyCFunction)Mzn_lock, METH_NOARGS, "Internal: Create a lock for garbage collection"},
237 {"unlock", (PyCFunction)Mzn_lock, METH_NOARGS,
238 "Internal: Unlock a lock for garbage collection"},
239 {NULL}};
240
241#if PY_MAJOR_VERSION >= 3
242
243static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT,
244 "minizinc",
245 "A python interface for MiniZinc constraint modeling",
246 -1,
247 Mzn_methods,
248 NULL,
249 NULL,
250 NULL,
251 NULL};
252
253#endif
254
255#endif