示例#1
0
/**
 * \ingroup python_interface_vertexseq
 * \brief Copies a vertex sequence object
 * \return the copied PyObject
 */
igraphmodule_VertexSeqObject*
igraphmodule_VertexSeq_copy(igraphmodule_VertexSeqObject* o) {
  igraphmodule_VertexSeqObject *copy;

  copy=(igraphmodule_VertexSeqObject*)PyType_GenericNew(Py_TYPE(o), 0, 0);
  if (copy == NULL) return NULL;
 
  if (igraph_vs_type(&o->vs) == IGRAPH_VS_VECTOR) {
    igraph_vector_t v;
    if (igraph_vector_copy(&v, o->vs.data.vecptr)) {
      igraphmodule_handle_igraph_error();
      return 0;
    }
    if (igraph_vs_vector_copy(&copy->vs, &v)) {
      igraphmodule_handle_igraph_error();
      igraph_vector_destroy(&v);
      return 0;
    }
    igraph_vector_destroy(&v);
  } else {
    copy->vs = o->vs;
  }

  copy->gref = o->gref;
  if (o->gref) Py_INCREF(o->gref);
  RC_ALLOC("VertexSeq(copy)", copy);

  return copy;
}
/*
 * Converts a Java VertexSet to an igraph_vs_t
 * @return:  zero if everything went fine, 1 if a null pointer was passed
 */
int Java_net_sf_igraph_VertexSet_to_igraph_vs(JNIEnv *env, jobject jobj, igraph_vs_t *result) {
  jint typeHint;
  jobject idArray;

  if (jobj == 0) {
    IGRAPH_CHECK(igraph_vs_all(result));
	return IGRAPH_SUCCESS;
  }

  typeHint = (*env)->CallIntMethod(env, jobj, net_sf_igraph_VertexSet_getTypeHint_mid);
  if (typeHint != 1 && typeHint != 2) {
    IGRAPH_CHECK(igraph_vs_all(result));
    return IGRAPH_SUCCESS;
  }
  
  idArray = (*env)->CallObjectMethod(env, jobj, net_sf_igraph_VertexSet_getIdArray_mid);
  if ((*env)->ExceptionCheck(env)) {
	return IGRAPH_EINVAL;
  }

  if (typeHint == 1) {
    /* Single vertex */
	jlong id[1];
	(*env)->GetLongArrayRegion(env, idArray, 0, 1, id);
	IGRAPH_CHECK(igraph_vs_1(result, (igraph_integer_t)id[0]));
  } else if (typeHint == 2) {
    /* List of vertices */
	jlong* ids;
	igraph_vector_t vec;
	long i, n;

	ids = (*env)->GetLongArrayElements(env, idArray, 0);
	n = (*env)->GetArrayLength(env, idArray);

	IGRAPH_VECTOR_INIT_FINALLY(&vec, n);
	for (i = 0; i < n; i++)
		VECTOR(vec)[i] = ids[i];
	IGRAPH_CHECK(igraph_vs_vector_copy(result, &vec));
	igraph_vector_destroy(&vec);
	IGRAPH_FINALLY_CLEAN(1);

	(*env)->ReleaseLongArrayElements(env, idArray, ids, JNI_ABORT);
  }

  (*env)->DeleteLocalRef(env, idArray);

  return IGRAPH_SUCCESS;
}
示例#3
0
/**
 * \ingroup python_interface_vertexseq
 * \brief Initialize a new vertex sequence object for a given graph
 * \return the initialized PyObject
 */
int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self,
  PyObject *args, PyObject *kwds) {
  static char *kwlist[] = { "graph", "vertices", NULL };
  PyObject *g, *vsobj=Py_None;
  igraph_vs_t vs;

  if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist,
    &igraphmodule_GraphType, &g, &vsobj))
      return -1;

  if (vsobj == Py_None) {
    /* If vs is None, we are selecting all the vertices */
    igraph_vs_all(&vs);
  } else if (PyInt_Check(vsobj)) {
    /* We selected a single vertex */
    long int idx = PyInt_AsLong(vsobj);
    if (idx < 0 || idx >= igraph_vcount(&((igraphmodule_GraphObject*)g)->g)) {
      PyErr_SetString(PyExc_ValueError, "vertex index out of range");
      return -1;
    }
    igraph_vs_1(&vs, (igraph_integer_t)idx);
  } else {
    igraph_vector_t v;
    igraph_integer_t n = igraph_vcount(&((igraphmodule_GraphObject*)g)->g);
    if (igraphmodule_PyObject_to_vector_t(vsobj, &v, 1))
      return -1;
    if (!igraph_vector_isininterval(&v, 0, n-1)) {
      igraph_vector_destroy(&v);
      PyErr_SetString(PyExc_ValueError, "vertex index out of range");
      return -1;
    }
    if (igraph_vs_vector_copy(&vs, &v)) {
      igraphmodule_handle_igraph_error();
      igraph_vector_destroy(&v);
      return -1;
    }
    igraph_vector_destroy(&v);
  }

  self->vs = vs;
  Py_INCREF(g);
  self->gref = (igraphmodule_GraphObject*)g;

  return 0;
}
示例#4
0
/**
 * \ingroup python_interface_vertexseq
 * \brief Selects a subset of the vertex sequence based on some criteria
 */
PyObject* igraphmodule_VertexSeq_select(igraphmodule_VertexSeqObject *self,
  PyObject *args) {
  igraphmodule_VertexSeqObject *result;
  igraphmodule_GraphObject *gr;
  long i, j, n, m;

  gr=self->gref;
  result=igraphmodule_VertexSeq_copy(self);
  if (result==0)
    return NULL;

  /* First, filter by positional arguments */
  n = PyTuple_Size(args);

  for (i=0; i<n; i++) {
    PyObject *item = PyTuple_GET_ITEM(args, i);

    if (item == Py_None) {
      /* None means: select nothing */
      igraph_vs_destroy(&result->vs);
      igraph_vs_none(&result->vs);
      /* We can simply bail out here */
      return (PyObject*)result;
    } else if (PyCallable_Check(item)) {
      /* Call the callable for every vertex in the current sequence to
       * determine what's up */
      igraph_bool_t was_excluded = 0;
      igraph_vector_t v;

      if (igraph_vector_init(&v, 0)) {
        igraphmodule_handle_igraph_error();
        return 0;
      }

      m = PySequence_Size((PyObject*)result);
      for (j=0; j<m; j++) {
        PyObject *vertex = PySequence_GetItem((PyObject*)result, j);
        PyObject *call_result;
        if (vertex == 0) {
          Py_DECREF(result);
          igraph_vector_destroy(&v);
          return NULL;
        }
        call_result = PyObject_CallFunctionObjArgs(item, vertex, NULL);
        if (call_result == 0) {
          Py_DECREF(vertex); Py_DECREF(result);
          igraph_vector_destroy(&v);
          return NULL;
        }
        if (PyObject_IsTrue(call_result))
          igraph_vector_push_back(&v,
            igraphmodule_Vertex_get_index_long((igraphmodule_VertexObject*)vertex));
        else was_excluded=1;
        Py_DECREF(call_result);
        Py_DECREF(vertex);
      }

      if (was_excluded) {
        igraph_vs_destroy(&result->vs);
        if (igraph_vs_vector_copy(&result->vs, &v)) {
          Py_DECREF(result);
          igraph_vector_destroy(&v);
          igraphmodule_handle_igraph_error();
          return NULL;
        }
      }

      igraph_vector_destroy(&v);
    } else if (PyInt_Check(item)) {
      /* Integers are treated specially: from now on, all remaining items
       * in the argument list must be integers and they will be used together
       * to restrict the vertex set. Integers are interpreted as indices on the
       * vertex set and NOT on the original, untouched vertex sequence of the
       * graph */
      igraph_vector_t v, v2;
      if (igraph_vector_init(&v, 0)) {
        igraphmodule_handle_igraph_error();
        return 0;
      }
      if (igraph_vector_init(&v2, 0)) {
        igraph_vector_destroy(&v);
        igraphmodule_handle_igraph_error();
        return 0;
      }
      if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) {
        igraph_vector_destroy(&v);
        igraph_vector_destroy(&v2);
        igraphmodule_handle_igraph_error();
        return 0;
      }
      m = igraph_vector_size(&v2);
      for (; i<n; i++) {
        PyObject *item2 = PyTuple_GET_ITEM(args, i);
        long idx;
        if (!PyInt_Check(item2)) {
          Py_DECREF(result);
          PyErr_SetString(PyExc_TypeError, "vertex indices expected");
          igraph_vector_destroy(&v);
          igraph_vector_destroy(&v2);
          return NULL;
        }
        idx = PyInt_AsLong(item2);
        if (idx >= m || idx < 0) {
          PyErr_SetString(PyExc_ValueError, "vertex index out of range");
          igraph_vector_destroy(&v);
          igraph_vector_destroy(&v2);
          return NULL;
        }
        if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) {
          Py_DECREF(result);
          igraphmodule_handle_igraph_error();
          igraph_vector_destroy(&v);
          igraph_vector_destroy(&v2);
          return NULL;
        }
      }
      igraph_vector_destroy(&v2);
      igraph_vs_destroy(&result->vs);
      if (igraph_vs_vector_copy(&result->vs, &v)) {
        Py_DECREF(result);
        igraphmodule_handle_igraph_error();
        igraph_vector_destroy(&v);
        return NULL;
      }
      igraph_vector_destroy(&v);
    } else {
      /* Iterators, slices and everything that was not handled directly */
      PyObject *iter=0, *item2;
      igraph_vector_t v, v2;

      /* Allocate stuff */
      if (igraph_vector_init(&v, 0)) {
        igraphmodule_handle_igraph_error();
        Py_DECREF(result);
        return 0;
      }
      if (igraph_vector_init(&v2, 0)) {
        igraph_vector_destroy(&v);
        Py_DECREF(result);
        igraphmodule_handle_igraph_error();
        return 0;
      }
      if (igraph_vs_as_vector(&gr->g, self->vs, &v2)) {
        igraph_vector_destroy(&v);
        igraph_vector_destroy(&v2);
        Py_DECREF(result);
        igraphmodule_handle_igraph_error();
        return 0;
      }
      m = igraph_vector_size(&v2);

      /* Create an appropriate iterator */
      if (PySlice_Check(item)) {
        /* Create an iterator from the slice (which is not iterable by default) */
        Py_ssize_t start, stop, step, sl;
        PyObject* range;
        igraph_bool_t ok;

        /* Casting to void* because Python 2.x expects PySliceObject*
         * but Python 3.x expects PyObject* */
        ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2),
              &start, &stop, &step, &sl) == 0);

        if (ok) {
          range = igraphmodule_PyRange_create(start, stop, step);
          ok = (range != 0);
        }
        if (ok) {
          iter = PyObject_GetIter(range);
          Py_DECREF(range);
          ok = (iter != 0);
        }
        if (!ok) {
          igraph_vector_destroy(&v);
          igraph_vector_destroy(&v2);
          PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator");
          Py_DECREF(result);
          return 0;
        }
      } else {
        /* Simply create the iterator corresponding to the object */
        iter = PyObject_GetIter(item);
      }

      /* Did we manage to get an iterator? */
      if (iter == 0) {
        igraph_vector_destroy(&v);
        igraph_vector_destroy(&v2);
        PyErr_SetString(PyExc_TypeError, "invalid vertex filter among positional arguments");
        Py_DECREF(result);
        return 0;
      }
      /* Do the iteration */
      while ((item2=PyIter_Next(iter)) != 0) {
        if (PyInt_Check(item2)) {
          long idx = PyInt_AsLong(item2);
          Py_DECREF(item2);
          if (idx >= m || idx < 0) {
            PyErr_SetString(PyExc_ValueError, "vertex index out of range");
            Py_DECREF(result);
            Py_DECREF(iter);
            igraph_vector_destroy(&v);
            igraph_vector_destroy(&v2);
            return NULL;
          }
          if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) {
            Py_DECREF(result);
            Py_DECREF(iter);
            igraphmodule_handle_igraph_error();
            igraph_vector_destroy(&v);
            igraph_vector_destroy(&v2);
            return NULL;
          }
        } else {
          /* We simply ignore elements that we don't know */
          Py_DECREF(item2);
        }
      }
      /* Deallocate stuff */
      igraph_vector_destroy(&v2);
      Py_DECREF(iter);
      if (PyErr_Occurred()) {
        igraph_vector_destroy(&v);
        Py_DECREF(result);
        return 0;
      }
      igraph_vs_destroy(&result->vs);
      if (igraph_vs_vector_copy(&result->vs, &v)) {
        Py_DECREF(result);
        igraphmodule_handle_igraph_error();
        igraph_vector_destroy(&v);
        return NULL;
      }
      igraph_vector_destroy(&v);
    }
  }

  return (PyObject*)result;
}