Logo Search packages:      
Sourcecode: python-biopython version File versions

cSVMmodule.c

/* Copyright 2000 by Jeffrey Chang.  All rights reserved.
 * This code is part of the Biopython distribution and governed by its
 * license.  Please see the LICENSE file that should have been included
 * as part of this package.
 *
 * cSVMmodule.c
 * Created 9 Apr 2000
 *
 * Optimized C routines that complement SVM.py.
 */

#include "Python.h"

#include "csupport.h"


/* Functions in this module. */

static char cSVM_classify__doc__[] = 
"classify(svm, x) -> num";

static PyObject *cSVM_classify(PyObject *self, PyObject *args)
{
    int i;
    PyObject *svm, *x;
    double sum;
    PyObject *ys, *alphas, *xs, *kernel_fn, *b;
    PyObject *ys_i, *alphas_i, *xs_i;
    PyObject *arglist, *retval;
    double y_value, alpha_value, kernel_value, b_value;
    
    if(!PyArg_ParseTuple(args, "OO", &svm, &x))
      return NULL;
    
    xs = PyObject_GetAttrString(svm, "xs");
    if(xs == NULL) {
      return NULL;
    }
    ys = PyObject_GetAttrString(svm, "ys");
    if(ys == NULL) {
      Py_DECREF(xs);
      return NULL;
    }
    alphas = PyObject_GetAttrString(svm, "alphas");
    if(alphas == NULL) {
      Py_DECREF(xs); Py_DECREF(ys);
      return NULL;
    }
    kernel_fn = PyObject_GetAttrString(svm, "kernel_fn");
    if(kernel_fn == NULL) {
      Py_DECREF(xs); Py_DECREF(ys); Py_DECREF(alphas);
      return NULL;
    }
    if(!PyCallable_Check(kernel_fn)) {
      PyErr_SetString(PyExc_TypeError, "kernel_fn is not callable");
      Py_DECREF(xs); Py_DECREF(ys); Py_DECREF(alphas); Py_DECREF(kernel_fn);
      return NULL;
    }
    b = PyObject_GetAttrString(svm, "b");
    if(b == NULL) {
      Py_DECREF(xs); Py_DECREF(ys); Py_DECREF(alphas); Py_DECREF(kernel_fn);
      return NULL;
    }
    
    sum = 0.0;
    for(i=0; ; i++) {
      xs_i = PySequence_GetItem(xs, i);
      if(xs_i == NULL) {
          PyErr_Clear();
          break;
      }
      
      alphas_i = PySequence_GetItem(alphas, i);
      if(alphas_i == NULL)
          break;
      alpha_value = PyNumber_AsDouble(alphas_i);
      if(PyErr_Occurred())
          break;
      if((alpha_value < 1E-5) && (alpha_value > -1E-5))
          continue;
      
      ys_i = PySequence_GetItem(ys, i);
      if(ys_i == NULL)
          break;
      y_value = PyNumber_AsDouble(ys_i);
      if(PyErr_Occurred())
          break;
      
      arglist = Py_BuildValue("(OO)", xs_i, x);
      retval = PyObject_CallObject(kernel_fn, arglist);
      Py_DECREF(arglist);
      if(retval == NULL)
          break;
      kernel_value = PyNumber_AsDouble(retval);
      Py_DECREF(retval);
      if(PyErr_Occurred())
          break;
      sum = sum + y_value*alpha_value*kernel_value;
    }
    
    if(!PyErr_Occurred()) {
      b_value = PyNumber_AsDouble(b);
      if(!PyErr_Occurred())
          sum = sum - b_value;
    }
    
    Py_DECREF(xs);
    Py_DECREF(ys);
    Py_DECREF(alphas);
    Py_DECREF(kernel_fn);
    Py_DECREF(b);
    
    if(PyErr_Occurred())
      return NULL;
    
    return PyFloat_FromDouble(sum);
}



static char cSVM__sparse_dot__doc__[] = 
"_sparse_dot(x, y) -> num";

static PyObject *cSVM__sparse_dot(PyObject *self, PyObject *args)
{
    int i;
    int size;
    PyObject *x, *y;
    PyObject *xkeys, *key, *xvalue, *yvalue;
    double sum, xdouble, ydouble;

    if(!PyArg_ParseTuple(args, "O!O!", &PyDict_Type, &x, &PyDict_Type, &y))
      return NULL;

    sum = 0.0;
    xkeys = PyDict_Keys(x);
    if(xkeys == NULL) {
      PyErr_SetString(PyExc_SystemError, "Could not get keys for x");
      return NULL;
    }
    size = PyList_Size(xkeys);
    for(i=0; i<size; i++) {
      key = PyList_GetItem(xkeys, i);
      if(key == NULL) {
          /* Checking for safety.  This will probably only occur if someone
             were doing something nasty with threads. */
          PyErr_SetString(PyExc_SystemError, "x dictionary has shrunk");
          break;
      }
      
      yvalue = PyDict_GetItem(y, key);
      if(yvalue == NULL)
          continue;
      xvalue = PyDict_GetItem(x, key);
      
      xdouble = PyNumber_AsDouble(xvalue);
      if(PyErr_Occurred())
          break;
      ydouble = PyNumber_AsDouble(yvalue);
      if(PyErr_Occurred())
          break;
      
      sum = sum + xdouble * ydouble;
    }
    
    Py_DECREF(xkeys);
    
    if(PyErr_Occurred()) {
      return NULL;
    }
    return PyFloat_FromDouble(sum);
}



static char cSVM__dot__doc__[] = 
"_dot(x, y) -> num";

static PyObject *cSVM__dot(PyObject *self, PyObject *args)
{
    int i;
    double sum;
    PyObject *x, *y, *xobj, *yobj;

    if(!PyArg_ParseTuple(args, "OO", &x, &y))
      return NULL;

    if(!PySequence_Check(x) || !PySequence_Check(y)) {
      PyErr_SetString(PyExc_ValueError, "x and y should be sequences");
      return NULL;
    }
    if(PySequence_Length(x) != PySequence_Length(y)) {
      PyErr_SetString(PyExc_ValueError, "x and y should be the same length");
      return NULL;
    }

    sum = 0.0;
    for(i=0; ; i++) {
      xobj = PySequence_GetItem(x, i);
      if(!xobj) {
          PyErr_Clear();
          break;
      }
      yobj = PySequence_GetItem(y, i);

      sum = sum + PyNumber_AsDouble(xobj) * PyNumber_AsDouble(yobj);
      Py_DECREF(xobj);
      Py_DECREF(yobj);
      if(PyErr_Occurred()) { /* Check if PyNumber_AsDouble failed */
          break;
      }
    }

    if(PyErr_Occurred()) {
      return NULL;
    }
    return PyFloat_FromDouble(sum);
}




/* Module definition stuff */

static PyMethodDef cSVMMethods[] = {
    {"_sparse_dot", cSVM__sparse_dot, METH_VARARGS, cSVM__sparse_dot__doc__},
    {"_dot", cSVM__dot, METH_VARARGS, cSVM__dot__doc__},
    {"classify", cSVM_classify, METH_VARARGS, cSVM_classify__doc__},
    {NULL, NULL}
};

static char cSVM__doc__[] =
"XXX document here\n\
\n\
";

void initcSVM(void)
{
    (void) Py_InitModule3("cSVM", cSVMMethods, cSVM__doc__);
}

Generated by  Doxygen 1.6.0   Back to index