solver.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*-----------------------------------------------------------------------------
  2. | Copyright (c) 2013-2017, Nucleic Development Team.
  3. |
  4. | Distributed under the terms of the Modified BSD License.
  5. |
  6. | The full license is in the file COPYING.txt, distributed with this software.
  7. |----------------------------------------------------------------------------*/
  8. #include <Python.h>
  9. #include <kiwi/kiwi.h>
  10. #include "pythonhelpers.h"
  11. #include "types.h"
  12. #include "util.h"
  13. using namespace PythonHelpers;
  14. static PyObject*
  15. Solver_new( PyTypeObject* type, PyObject* args, PyObject* kwargs )
  16. {
  17. if( PyTuple_GET_SIZE( args ) != 0 || ( kwargs && PyDict_Size( kwargs ) != 0 ) )
  18. return py_type_fail( "Solver.__new__ takes no arguments" );
  19. PyObject* pysolver = PyType_GenericNew( type, args, kwargs );
  20. if( !pysolver )
  21. return 0;
  22. Solver* self = reinterpret_cast<Solver*>( pysolver );
  23. new( &self->solver ) kiwi::Solver();
  24. return pysolver;
  25. }
  26. static void
  27. Solver_dealloc( Solver* self )
  28. {
  29. self->solver.~Solver();
  30. Py_TYPE( self )->tp_free( pyobject_cast( self ) );
  31. }
  32. static PyObject*
  33. Solver_addConstraint( Solver* self, PyObject* other )
  34. {
  35. if( !Constraint::TypeCheck( other ) )
  36. return py_expected_type_fail( other, "Constraint" );
  37. Constraint* cn = reinterpret_cast<Constraint*>( other );
  38. try
  39. {
  40. self->solver.addConstraint( cn->constraint );
  41. }
  42. catch( const kiwi::DuplicateConstraint& )
  43. {
  44. PyErr_SetObject( DuplicateConstraint, other );
  45. return 0;
  46. }
  47. catch( const kiwi::UnsatisfiableConstraint& )
  48. {
  49. PyErr_SetObject( UnsatisfiableConstraint, other );
  50. return 0;
  51. }
  52. Py_RETURN_NONE;
  53. }
  54. static PyObject*
  55. Solver_removeConstraint( Solver* self, PyObject* other )
  56. {
  57. if( !Constraint::TypeCheck( other ) )
  58. return py_expected_type_fail( other, "Constraint" );
  59. Constraint* cn = reinterpret_cast<Constraint*>( other );
  60. try
  61. {
  62. self->solver.removeConstraint( cn->constraint );
  63. }
  64. catch( const kiwi::UnknownConstraint& )
  65. {
  66. PyErr_SetObject( UnknownConstraint, other );
  67. return 0;
  68. }
  69. Py_RETURN_NONE;
  70. }
  71. static PyObject*
  72. Solver_hasConstraint( Solver* self, PyObject* other )
  73. {
  74. if( !Constraint::TypeCheck( other ) )
  75. return py_expected_type_fail( other, "Constraint" );
  76. Constraint* cn = reinterpret_cast<Constraint*>( other );
  77. return newref( self->solver.hasConstraint( cn->constraint ) ? Py_True : Py_False );
  78. }
  79. static PyObject*
  80. Solver_addEditVariable( Solver* self, PyObject* args )
  81. {
  82. PyObject* pyvar;
  83. PyObject* pystrength;
  84. if( !PyArg_ParseTuple( args, "OO", &pyvar, &pystrength ) )
  85. return 0;
  86. if( !Variable::TypeCheck( pyvar ) )
  87. return py_expected_type_fail( pyvar, "Variable" );
  88. double strength;
  89. if( !convert_to_strength( pystrength, strength ) )
  90. return 0;
  91. Variable* var = reinterpret_cast<Variable*>( pyvar );
  92. try
  93. {
  94. self->solver.addEditVariable( var->variable, strength );
  95. }
  96. catch( const kiwi::DuplicateEditVariable& )
  97. {
  98. PyErr_SetObject( DuplicateEditVariable, pyvar );
  99. return 0;
  100. }
  101. catch( const kiwi::BadRequiredStrength& e )
  102. {
  103. PyErr_SetString( BadRequiredStrength, e.what() );
  104. return 0;
  105. }
  106. Py_RETURN_NONE;
  107. }
  108. static PyObject*
  109. Solver_removeEditVariable( Solver* self, PyObject* other )
  110. {
  111. if( !Variable::TypeCheck( other ) )
  112. return py_expected_type_fail( other, "Variable" );
  113. Variable* var = reinterpret_cast<Variable*>( other );
  114. try
  115. {
  116. self->solver.removeEditVariable( var->variable );
  117. }
  118. catch( const kiwi::UnknownEditVariable& )
  119. {
  120. PyErr_SetObject( UnknownEditVariable, other );
  121. return 0;
  122. }
  123. Py_RETURN_NONE;
  124. }
  125. static PyObject*
  126. Solver_hasEditVariable( Solver* self, PyObject* other )
  127. {
  128. if( !Variable::TypeCheck( other ) )
  129. return py_expected_type_fail( other, "Variable" );
  130. Variable* var = reinterpret_cast<Variable*>( other );
  131. return newref( self->solver.hasEditVariable( var->variable ) ? Py_True : Py_False );
  132. }
  133. static PyObject*
  134. Solver_suggestValue( Solver* self, PyObject* args )
  135. {
  136. PyObject* pyvar;
  137. PyObject* pyvalue;
  138. if( !PyArg_ParseTuple( args, "OO", &pyvar, &pyvalue ) )
  139. return 0;
  140. if( !Variable::TypeCheck( pyvar ) )
  141. return py_expected_type_fail( pyvar, "Variable" );
  142. double value;
  143. if( !convert_to_double( pyvalue, value ) )
  144. return 0;
  145. Variable* var = reinterpret_cast<Variable*>( pyvar );
  146. try
  147. {
  148. self->solver.suggestValue( var->variable, value );
  149. }
  150. catch( const kiwi::UnknownEditVariable& )
  151. {
  152. PyErr_SetObject( UnknownEditVariable, pyvar );
  153. return 0;
  154. }
  155. Py_RETURN_NONE;
  156. }
  157. static PyObject*
  158. Solver_updateVariables( Solver* self )
  159. {
  160. self->solver.updateVariables();
  161. Py_RETURN_NONE;
  162. }
  163. static PyObject*
  164. Solver_reset( Solver* self )
  165. {
  166. self->solver.reset();
  167. Py_RETURN_NONE;
  168. }
  169. static PyObject*
  170. Solver_dump( Solver* self )
  171. {
  172. PyObjectPtr dump_str( PyUnicode_FromString( self->solver.dumps().c_str() ) );
  173. PyObject_Print( dump_str.get(), stdout, 0 );
  174. Py_RETURN_NONE;
  175. }
  176. static PyObject*
  177. Solver_dumps( Solver* self )
  178. {
  179. return PyUnicode_FromString( self->solver.dumps().c_str() );
  180. }
  181. static PyMethodDef
  182. Solver_methods[] = {
  183. { "addConstraint", ( PyCFunction )Solver_addConstraint, METH_O,
  184. "Add a constraint to the solver." },
  185. { "removeConstraint", ( PyCFunction )Solver_removeConstraint, METH_O,
  186. "Remove a constraint from the solver." },
  187. { "hasConstraint", ( PyCFunction )Solver_hasConstraint, METH_O,
  188. "Check whether the solver contains a constraint." },
  189. { "addEditVariable", ( PyCFunction )Solver_addEditVariable, METH_VARARGS,
  190. "Add an edit variable to the solver." },
  191. { "removeEditVariable", ( PyCFunction )Solver_removeEditVariable, METH_O,
  192. "Remove an edit variable from the solver." },
  193. { "hasEditVariable", ( PyCFunction )Solver_hasEditVariable, METH_O,
  194. "Check whether the solver contains an edit variable." },
  195. { "suggestValue", ( PyCFunction )Solver_suggestValue, METH_VARARGS,
  196. "Suggest a desired value for an edit variable." },
  197. { "updateVariables", ( PyCFunction )Solver_updateVariables, METH_NOARGS,
  198. "Update the values of the solver variables." },
  199. { "reset", ( PyCFunction )Solver_reset, METH_NOARGS,
  200. "Reset the solver to the initial empty starting condition." },
  201. { "dump", ( PyCFunction )Solver_dump, METH_NOARGS,
  202. "Dump a representation of the solver internals to stdout." },
  203. { "dumps", ( PyCFunction )Solver_dumps, METH_NOARGS,
  204. "Dump a representation of the solver internals to a string." },
  205. { 0 } // sentinel
  206. };
  207. PyTypeObject Solver_Type = {
  208. PyVarObject_HEAD_INIT( &PyType_Type, 0 )
  209. "kiwisolver.Solver", /* tp_name */
  210. sizeof( Solver ), /* tp_basicsize */
  211. 0, /* tp_itemsize */
  212. (destructor)Solver_dealloc, /* tp_dealloc */
  213. (printfunc)0, /* tp_print */
  214. (getattrfunc)0, /* tp_getattr */
  215. (setattrfunc)0, /* tp_setattr */
  216. #if PY_VERSION_HEX >= 0x03050000
  217. ( PyAsyncMethods* )0, /* tp_as_async */
  218. #elif PY_VERSION_HEX >= 0x03000000
  219. ( void* ) 0, /* tp_reserved */
  220. #else
  221. ( cmpfunc )0, /* tp_compare */
  222. #endif
  223. (reprfunc)0, /* tp_repr */
  224. (PyNumberMethods*)0, /* tp_as_number */
  225. (PySequenceMethods*)0, /* tp_as_sequence */
  226. (PyMappingMethods*)0, /* tp_as_mapping */
  227. (hashfunc)0, /* tp_hash */
  228. (ternaryfunc)0, /* tp_call */
  229. (reprfunc)0, /* tp_str */
  230. (getattrofunc)0, /* tp_getattro */
  231. (setattrofunc)0, /* tp_setattro */
  232. (PyBufferProcs*)0, /* tp_as_buffer */
  233. Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
  234. 0, /* Documentation string */
  235. (traverseproc)0, /* tp_traverse */
  236. (inquiry)0, /* tp_clear */
  237. (richcmpfunc)0, /* tp_richcompare */
  238. 0, /* tp_weaklistoffset */
  239. (getiterfunc)0, /* tp_iter */
  240. (iternextfunc)0, /* tp_iternext */
  241. (struct PyMethodDef*)Solver_methods, /* tp_methods */
  242. (struct PyMemberDef*)0, /* tp_members */
  243. 0, /* tp_getset */
  244. 0, /* tp_base */
  245. 0, /* tp_dict */
  246. (descrgetfunc)0, /* tp_descr_get */
  247. (descrsetfunc)0, /* tp_descr_set */
  248. 0, /* tp_dictoffset */
  249. (initproc)0, /* tp_init */
  250. (allocfunc)PyType_GenericAlloc, /* tp_alloc */
  251. (newfunc)Solver_new, /* tp_new */
  252. (freefunc)PyObject_Del, /* tp_free */
  253. (inquiry)0, /* tp_is_gc */
  254. 0, /* tp_bases */
  255. 0, /* tp_mro */
  256. 0, /* tp_cache */
  257. 0, /* tp_subclasses */
  258. 0, /* tp_weaklist */
  259. (destructor)0 /* tp_del */
  260. };
  261. PyObject* DuplicateConstraint;
  262. PyObject* UnsatisfiableConstraint;
  263. PyObject* UnknownConstraint;
  264. PyObject* DuplicateEditVariable;
  265. PyObject* UnknownEditVariable;
  266. PyObject* BadRequiredStrength;
  267. int import_solver()
  268. {
  269. DuplicateConstraint = PyErr_NewException(
  270. const_cast<char*>( "kiwisolver.DuplicateConstraint" ), 0, 0 );
  271. if( !DuplicateConstraint )
  272. return -1;
  273. UnsatisfiableConstraint = PyErr_NewException(
  274. const_cast<char*>( "kiwisolver.UnsatisfiableConstraint" ), 0, 0 );
  275. if( !UnsatisfiableConstraint )
  276. return -1;
  277. UnknownConstraint = PyErr_NewException(
  278. const_cast<char*>( "kiwisolver.UnknownConstraint" ), 0, 0 );
  279. if( !UnknownConstraint )
  280. return -1;
  281. DuplicateEditVariable = PyErr_NewException(
  282. const_cast<char*>( "kiwisolver.DuplicateEditVariable" ), 0, 0 );
  283. if( !DuplicateEditVariable )
  284. return -1;
  285. UnknownEditVariable = PyErr_NewException(
  286. const_cast<char*>( "kiwisolver.UnknownEditVariable" ), 0, 0 );
  287. if( !UnknownEditVariable )
  288. return -1;
  289. BadRequiredStrength = PyErr_NewException(
  290. const_cast<char*>( "kiwisolver.BadRequiredStrength" ), 0, 0 );
  291. if( !BadRequiredStrength )
  292. return -1;
  293. return PyType_Ready( &Solver_Type );
  294. }