~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to scipy/sandbox/newoptimize/tnc/moduleTNC.c

  • Committer: Bazaar Package Importer
  • Author(s): Ondrej Certik
  • Date: 2008-06-16 22:58:01 UTC
  • mfrom: (2.1.24 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080616225801-irdhrpcwiocfbcmt
Tags: 0.6.0-12
* The description updated to match the current SciPy (Closes: #489149).
* Standards-Version bumped to 3.8.0 (no action needed)
* Build-Depends: netcdf-dev changed to libnetcdf-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Python TNC module */
 
2
 
 
3
/*
 
4
 * Copyright (c) 2004-2005, Jean-Sebastien Roy (js@jeannot.org)
 
5
 *
 
6
 * Permission is hereby granted, free of charge, to any person obtaining a
 
7
 * copy of this software and associated documentation files (the
 
8
 * "Software"), to deal in the Software without restriction, including
 
9
 * without limitation the rights to use, copy, modify, merge, publish,
 
10
 * distribute, sublicense, and/or sell copies of the Software, and to
 
11
 * permit persons to whom the Software is furnished to do so, subject to
 
12
 * the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included
 
15
 * in all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
20
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
21
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
22
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
23
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
24
 */
 
25
 
 
26
static char const rcsid[] =
 
27
  "@(#) $Jeannot: moduleTNC.c,v 1.12 2005/01/28 18:27:31 js Exp $";
 
28
 
 
29
#include "Python.h"
 
30
#include <stdlib.h>
 
31
#include <stdio.h>
 
32
#include <math.h>
 
33
 
 
34
#include "tnc.h"
 
35
 
 
36
typedef struct _pytnc_state
 
37
{
 
38
  PyObject *py_function;
 
39
  int n;
 
40
  int failed;
 
41
} pytnc_state;
 
42
 
 
43
static tnc_function function;
 
44
static PyObject *moduleTNC_minimize(PyObject *self, PyObject *args);
 
45
static int PyObject_AsDouble(PyObject *py_obj, double *x);
 
46
static double *PyList_AsDoubleArray(PyObject *py_list, int *size);
 
47
static PyObject *PyDoubleArray_AsList(int size, double *x);
 
48
static int PyList_IntoDoubleArray(PyObject *py_list, double *x, int size);
 
49
 
 
50
int PyObject_AsDouble(PyObject *py_obj, double *x)
 
51
{
 
52
  PyObject *py_float;
 
53
 
 
54
  py_float = PyNumber_Float(py_obj);
 
55
 
 
56
  if (py_float == NULL) return -1;
 
57
 
 
58
  *x = PyFloat_AsDouble(py_float);
 
59
 
 
60
  Py_DECREF(py_float);
 
61
  return 0;
 
62
}
 
63
 
 
64
double *PyList_AsDoubleArray(PyObject *py_list, int *size)
 
65
{
 
66
  int i;
 
67
  double *x;
 
68
 
 
69
  if (!PyList_Check(py_list))
 
70
  {
 
71
    *size = -1;
 
72
    return NULL;
 
73
  }
 
74
 
 
75
  *size = PyList_Size(py_list);
 
76
  if (*size <= 0) return NULL;
 
77
  x = malloc((*size)*sizeof(*x));
 
78
  if (x == NULL) return NULL;
 
79
 
 
80
  for (i=0; i<(*size); i++)
 
81
  {
 
82
    PyObject *py_float = PyList_GetItem(py_list, i);
 
83
    if (py_float == NULL || PyObject_AsDouble(py_float, &(x[i])))
 
84
    {
 
85
      free(x);
 
86
      return NULL;
 
87
    }
 
88
  }
 
89
 
 
90
  return x;
 
91
}
 
92
 
 
93
int PyList_IntoDoubleArray(PyObject *py_list, double *x, int size)
 
94
{
 
95
  int i;
 
96
 
 
97
  if (py_list == NULL) return 1;
 
98
 
 
99
  if (!PyList_Check(py_list)) return 1;
 
100
 
 
101
  if (size != PyList_Size(py_list)) return 1;
 
102
 
 
103
  for (i=0; i<size; i++)
 
104
  {
 
105
    PyObject *py_float = PyList_GetItem(py_list, i);
 
106
    if (py_float == NULL || PyObject_AsDouble(py_float, &(x[i])))
 
107
      return 1;
 
108
  }
 
109
 
 
110
  return 0;
 
111
}
 
112
 
 
113
PyObject *PyDoubleArray_AsList(int size, double *x)
 
114
{
 
115
  int i;
 
116
  PyObject *py_list;
 
117
 
 
118
  py_list = PyList_New(size);
 
119
  if (py_list == NULL) return NULL;
 
120
 
 
121
  for (i=0; i<size; i++)
 
122
  {
 
123
    PyObject *py_float;
 
124
    py_float = PyFloat_FromDouble(x[i]);
 
125
    if (py_float == NULL || PyList_SetItem(py_list, i, py_float))
 
126
    {
 
127
      Py_DECREF(py_list);
 
128
      return NULL;
 
129
    }
 
130
  }
 
131
 
 
132
  return py_list;
 
133
}
 
134
 
 
135
static int function(double x[], double *f, double g[], void *state)
 
136
{
 
137
  PyObject *py_list, *arglist, *py_grad, *result = NULL;
 
138
  pytnc_state *py_state = (pytnc_state *)state;
 
139
 
 
140
  py_list = PyDoubleArray_AsList(py_state->n, x);
 
141
  if (py_list == NULL)
 
142
  {
 
143
    PyErr_SetString(PyExc_MemoryError, "tnc: memory allocation failed.");
 
144
    goto failure;
 
145
  }
 
146
 
 
147
  arglist = Py_BuildValue("(N)", py_list);
 
148
  result = PyEval_CallObject(py_state->py_function, arglist);
 
149
  Py_DECREF(arglist);
 
150
 
 
151
  if (result == NULL)
 
152
    goto failure;
 
153
 
 
154
  if (result == Py_None)
 
155
  {
 
156
    Py_DECREF(result);
 
157
    return 1;
 
158
  }
 
159
 
 
160
  if (!PyArg_ParseTuple(result, "dO!", f, &PyList_Type, &py_grad))
 
161
  {
 
162
    PyErr_SetString(PyExc_ValueError,
 
163
      "tnc: invalid return value from minimized function.");
 
164
    goto failure;
 
165
  }
 
166
 
 
167
  if (PyList_IntoDoubleArray(py_grad, g, py_state->n))
 
168
    goto failure;
 
169
 
 
170
  Py_DECREF(result);
 
171
 
 
172
  return 0;
 
173
 
 
174
failure:
 
175
  py_state->failed = 1;
 
176
  Py_XDECREF(result);
 
177
  return 1;
 
178
}
 
179
 
 
180
PyObject *moduleTNC_minimize(PyObject *self, PyObject *args)
 
181
{
 
182
  PyObject *py_x0, *py_low, *py_up, *py_list, *py_scale, *py_offset;
 
183
  PyObject *py_function = NULL;
 
184
  pytnc_state py_state;
 
185
  int n, n1, n2, n3, n4;
 
186
 
 
187
  int rc, msg, maxCGit, maxnfeval, nfeval = 0;
 
188
  double *x, *low, *up, *scale = NULL, *offset = NULL;
 
189
  double f, eta, stepmx, accuracy, fmin, ftol, xtol, pgtol, rescale;
 
190
 
 
191
  if (!PyArg_ParseTuple(args, "OO!O!O!O!O!iiidddddddd",
 
192
    &py_function,
 
193
    &PyList_Type, &py_x0,
 
194
    &PyList_Type, &py_low,
 
195
    &PyList_Type, &py_up,
 
196
    &PyList_Type, &py_scale,
 
197
    &PyList_Type, &py_offset,
 
198
    &msg, &maxCGit, &maxnfeval, &eta, &stepmx, &accuracy, &fmin, &ftol,
 
199
    &xtol, &pgtol,
 
200
    &rescale
 
201
    ))
 
202
    return NULL;
 
203
 
 
204
  if (!PyCallable_Check(py_function))
 
205
  {
 
206
    PyErr_SetString(PyExc_TypeError, "tnc: function must be callable");
 
207
    return NULL;
 
208
  }
 
209
 
 
210
  scale = PyList_AsDoubleArray(py_scale, &n3);
 
211
  if (n3 != 0 && scale == NULL)
 
212
  {
 
213
    PyErr_SetString(PyExc_ValueError, "tnc: invalid scaling parameters.");
 
214
    return NULL;
 
215
  }
 
216
 
 
217
  offset = PyList_AsDoubleArray(py_offset, &n4);
 
218
  if (n4 != 0 && offset == NULL)
 
219
  {
 
220
    PyErr_SetString(PyExc_ValueError, "tnc: invalid offset parameters.");
 
221
    return NULL;
 
222
  }
 
223
 
 
224
  x = PyList_AsDoubleArray(py_x0, &n);
 
225
  if (n != 0 && x == NULL)
 
226
  {
 
227
    if (scale) free(scale);
 
228
 
 
229
    PyErr_SetString(PyExc_ValueError, "tnc: invalid initial vector.");
 
230
    return NULL;
 
231
  }
 
232
 
 
233
  low = PyList_AsDoubleArray(py_low, &n1);
 
234
  up = PyList_AsDoubleArray(py_up, &n2);
 
235
 
 
236
  if ((n1 != 0 && low == NULL) || (n2 != 0 && up == NULL))
 
237
  {
 
238
    if (scale) free(scale);
 
239
    if (x) free(x);
 
240
    if (low) free(low);
 
241
    if (up) free(up);
 
242
 
 
243
    PyErr_SetString(PyExc_ValueError, "tnc: invalid bounds.");
 
244
    return NULL;
 
245
  }
 
246
 
 
247
  if (n1 != n2 || n != n1 || (scale != NULL && n != n3)
 
248
    || (offset != NULL && n != n4))
 
249
  {
 
250
    if (scale) free(scale);
 
251
    if (offset) free(offset);
 
252
    if (x) free(x);
 
253
    if (low) free(low);
 
254
    if (up) free(up);
 
255
 
 
256
    PyErr_SetString(PyExc_ValueError, "tnc: vector sizes must be equal.");
 
257
    return NULL;
 
258
  }
 
259
 
 
260
  py_state.py_function = py_function;
 
261
  py_state.n = n;
 
262
  py_state.failed = 0;
 
263
 
 
264
  Py_INCREF(py_function);
 
265
 
 
266
  rc = tnc(n, x, &f, NULL, function, &py_state, low, up, scale, offset, msg,
 
267
    maxCGit, maxnfeval, eta, stepmx, accuracy, fmin, ftol, xtol, pgtol, rescale,
 
268
    &nfeval);
 
269
 
 
270
  Py_DECREF(py_function);
 
271
 
 
272
  if (low) free(low);
 
273
  if (up) free(up);
 
274
  if (scale) free(scale);
 
275
  if (offset) free(offset);
 
276
 
 
277
  if (py_state.failed)
 
278
  {
 
279
    if (x) free(x);
 
280
    return NULL;
 
281
  }
 
282
 
 
283
  if (rc == TNC_ENOMEM)
 
284
  {
 
285
    PyErr_SetString(PyExc_MemoryError, "tnc: memory allocation failed.");
 
286
    if (x) free(x);
 
287
    return NULL;
 
288
  }
 
289
 
 
290
  py_list = PyDoubleArray_AsList(n, x);
 
291
  if (x) free(x);
 
292
  if (py_list == NULL)
 
293
  {
 
294
    PyErr_SetString(PyExc_MemoryError, "tnc: memory allocation failed.");
 
295
    return NULL;
 
296
  }
 
297
 
 
298
  return Py_BuildValue("(iiN)", rc, nfeval, py_list);;
 
299
}
 
300
 
 
301
static PyMethodDef moduleTNC_methods[] =
 
302
{
 
303
  {"minimize", moduleTNC_minimize, METH_VARARGS},
 
304
  {NULL, NULL}
 
305
};
 
306
 
 
307
PyMODINIT_FUNC initmoduleTNC(void)
 
308
{
 
309
  (void) Py_InitModule("moduleTNC", moduleTNC_methods);
 
310
}