igraph-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [igraph] Invalid (negative) vertex id, Invalid vertex id


From: Christian Gonzalez
Subject: Re: [igraph] Invalid (negative) vertex id, Invalid vertex id
Date: Thu, 06 Aug 2009 10:46:11 -0430
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1b3pre) Gecko/20090513 Fedora/3.0-2.3.beta2.fc11 Lightning/1.0pre Thunderbird/3.0b2

El 06/08/09 10:23, Tamas Nepusz escribió:
In the meanwhile, all that I can say without seeing your source code is that the error message you see is triggered in src/structure_generators.c, line 77, which is inside igraph_create. In igraph_create, we check whether the edge list you passed (in the second argument) contains negative vertex IDs or not. Weird things may happen if you pass an invalid pointer there, so please check the contents of the vector you are passing as the second argument.

Thanks Tamas,
This is I new Open Source project, I will publish this when a finished to solved this problem, is a little complicated to test it code, becouse you need to setup postgresql first. Later I will publish the project in the following path: http://pgroute.geomaticalibre.org

But if you only want to see the code, is it:


/*
 *dijkstra.h
 */

#ifndef _DIJKSTRA_H
#define _DIJKSTRA_H

#include "postgres.h"
#include "igraph.h"

// The number of tuples to fetch from the SPI cursor at each iteration
#define TUPLIMIT 1000
#define PGR_EMPTY (-1)

/*
 * Convert PostgreSQL text object to a C string
 */
#define PGR_TEXT_GET_CSTR(text) \
DatumGetCString(DirectFunctionCall1(textout,PointerGetDatum(text)))

/*
* Used for validating the query columns, in this we saved the query columns
 * numbers
 */
typedef struct
{
  int2 id;
  int2 source;
  int2 target;
  int2 cost;
  int2 bidirectional;
  int2 reverse_cost;
} pgr_edge_columns_t;

/*
 * Used for save the shortest path
 * Record structure holding the to be exposed cache data.
 */
typedef struct
{
  int32 step;
  int32 vertex_id;
  int32 edge_id;
  float8 cost;
} ShortestPathRec;

/*
 * Function context for data persisting over repeated calls.
 */
typedef struct
{
  TupleDesc tupdesc;
  ShortestPathRec *record;
} ShortestPathContext;


/*
 * FUNCTIONS PROTOTYPES
 */
Datum
pgr_sp_dijkstra( PG_FUNCTION_ARGS);

/*
 *
 */
static int finish(int code, int ret);

/*
 *
 */
static int fetch_edge_columns(SPITupleTable *tuptable, pgr_edge_columns_t *edge_columns, bool directed);

/*
 *
 */
static int fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc, long int i, pgr_edge_columns_t *edge_columns, igraph_vector_t *edges, igraph_vector_t *weights, igraph_vector_t *eids,
           igraph_vector_t *vertex, bool directed);

/*
 *
 */
static int compute_shortest_path(char *sql, int32 start_vertex, int32 end_vertex, bool directed, ShortestPathRec **path, uint32 *path_count);

/*
 *
 */
static igraph_integer_t search_eid(igraph_t *g, const igraph_real_t id1, const igraph_real_t id2,
                                   igraph_bool_t directed);

/*
 *
 */
static long int search_element(const igraph_real_t *id, igraph_vector_t *v);

/*
 *
 */
static int reenumerate(const igraph_real_t *source, const igraph_real_t *target, igraph_real_t *newsource,
                       igraph_real_t *newtarget, igraph_vector_t *v);

#endif /* _DIJKSTRA_H */




and

/*
* dijkstra.c
 */
#include "postgres.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "fmgr.h"
#include "dijkstra.h"
#include "igraph.h"

#undef DEBUG
#define DEBUG 1

#ifdef DEBUG
#define DBG(format, arg...) ereport(NOTICE, (errmsg_internal(format, ## arg)));
#else
#define DBG(format, arg...) do { ; } while (0);
#endif

/*
 * Necesary for PostgreSQL
 */
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

/*
 * Interface function to PostgreSQL
 */
PG_FUNCTION_INFO_V1(pgr_sp_dijkstra);

Datum pgr_sp_dijkstra(PG_FUNCTION_ARGS)
{
  FuncCallContext *funcctx;
  Datum result;
  MemoryContext oldcontext;
  HeapTuple tuple;
  ShortestPathContext *fctx;    /* User function context. */

  uint32 path_count = 0;
  int ret;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL())
  {
    /* create a function context for cross-call persistence */
    funcctx = SRF_FIRSTCALL_INIT();

    /* switch to memory context appropriate for multiple function calls */
    oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

    /* Create a user function context for cross-call persistence */
    fctx = (ShortestPathContext *) SPI_palloc(sizeof(ShortestPathContext));


    /*
     * typedef double igraph_integer_t
     * typedef double igraph_real_t
     */
    DBG("PostgreSQL data type sizes:");
    DBG("sizeof(int64)=%i ",sizeof(int64));
    DBG("sizeof(int32)=%i ",sizeof(int32));
    DBG("sizeof(int8)=%i ",sizeof(int8));
    DBG("sizeof(int4)=%i ",sizeof(int4));
    DBG("sizeof(int2)=%i ",sizeof(int2));
    DBG("sizeof(float8)=%i ",sizeof(float8));
    DBG("sizeof(long int)=%i ",sizeof(long int));
    DBG("sizeof(long long int)=%i ",sizeof(long long int));
    DBG("\n");
    DBG("IGRAH data type sizes:");
    DBG("sizeof(igraph_integer_t)=%i",sizeof(igraph_integer_t));
    DBG("sizeof(igraph_real_t)=%i",sizeof(igraph_real_t));
    DBG("\n");
    DBG("(igraph_integer_t) 12345678 = %f",(igraph_integer_t) 12345678)
    DBG("(long long int) 12345678 = %i",(long long int) 12345678)
DBG("(long long int) (igraph_integer_t) 12345678 = %i",(long long int) (igraph_integer_t) 12345678) DBG("(long long int) (igraph_real_t) 12345678 = %i",(long long int) (igraph_real_t) 12345678)
    DBG("(igraph_real_t) 12345678 = %f",(igraph_real_t) 12345678)
DBG("(int32) (igraph_integer_t) 12345678 = %i",(int32) (igraph_integer_t) 12345678)

    /*Getting tuple_desc  from our type 'pgr_pr_dijkstra'*/
fctx->tupdesc = BlessTupleDesc(RelationNameGetTupleDesc("pgr_pr_dijkstra"));

    /*
     * Check if functions arguments are NULLs
     */
if( PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2) || PG_ARGISNULL(3))
    {
      ereport(ERROR, (errmsg_internal("some function argument is NULL!")));
      PG_RETURN_NULL();
    }

    //TODO: validar la salida almacenada en la variable ret
ret = compute_shortest_path(PGR_TEXT_GET_CSTR(PG_GETARG_DATUM(0)), //sql string
                                PG_GETARG_INT32(1), //source id
                                PG_GETARG_INT32(2), //destination id
                                PG_GETARG_BOOL(3), //if is directed
&fctx->record, //for return the route
&path_count //number of returned routes
        );

    /* Set max calls and remember the user function context. */
    funcctx->max_calls = path_count;
    funcctx->user_fctx = fctx;

    /* Return to original context when allocating transient memory */
    MemoryContextSwitchTo(oldcontext);
  }

  /* stuff done on every call of the function */
  funcctx = SRF_PERCALL_SETUP();

  /* Get the saved state */
  fctx = funcctx->user_fctx;

  /*
   * do when there is more left to send
   */
  if (funcctx->call_cntr < funcctx->max_calls)
  {
    uint32    i = funcctx->call_cntr;
    Datum *values;
    bool *nulls;

    values = (Datum *) SPI_palloc(fctx->tupdesc->natts * sizeof(Datum));
    nulls = (bool *) SPI_palloc(fctx->tupdesc->natts * sizeof(bool));

    values[0] = Int32GetDatum(fctx->record[i].step);
    nulls[0] = false;

    values[1] = Int32GetDatum(fctx->record[i].vertex_id);
    nulls[1] = false;

    values[2] = Int32GetDatum(fctx->record[i].edge_id);
    nulls[2] = false;

    values[3] = Float8GetDatum(fctx->record[i].cost);
    nulls[3] = false;

    /* build tuple from datum array*/
    tuple = heap_form_tuple(fctx->tupdesc, values, nulls);

    /* clean up (this is not really necessary) */
    SPI_pfree(values);
    SPI_pfree(nulls);

    /* make the tuple into a datum */
    result = HeapTupleGetDatum(tuple);

    SRF_RETURN_NEXT(funcctx, result);

  }
  else /* do when there is no more left */
  {
    SRF_RETURN_DONE(funcctx);
  }
}

/*
 *
 */
static int compute_shortest_path(char *sql, int32 start_vertex, int32 end_vertex, bool directed, ShortestPathRec **path, uint32 *path_count)
{

  int SPIcode;
  void *SPIplan;
  Portal SPIportal;

  bool moredata = TRUE;
  uint32 ntuples;
  long int total_tuples = 0;
  pgr_edge_columns_t edge_columns = { id: PGR_EMPTY,
                                  source: PGR_EMPTY,
                                  target: PGR_EMPTY,
                                  cost: PGR_EMPTY,
                                  bidirectional: PGR_EMPTY,
                                  reverse_cost: PGR_EMPTY };

  int ret = -1;

  igraph_t graph;
  igraph_vector_t weights;
  igraph_vector_t eids;
  igraph_vector_t edges;
  igraph_vector_t vertex;

  igraph_integer_t from = (igraph_integer_t) start_vertex;
  igraph_integer_t to = (igraph_integer_t) end_vertex;

  /* turn on attribute handling from igraph library */
  igraph_i_set_attribute_table(&igraph_cattribute_table);

  DBG("\n");
DBG("start_vertex=%i, end_vertex=%i --> from=%f, to=%f", start_vertex, end_vertex,from,to);
  DBG("\n");

  DBG("#---- executing function 'compute_shortest_path' ----#\n");


  if ((SPIcode = SPI_connect()) != SPI_OK_CONNECT)
  {
ereport(ERROR, (errmsg_internal("shortest_path: couldn't open a connection to SPI")));
    return -1;
  }

  if ((SPIplan = SPI_prepare(sql, 0, NULL)) == NULL)
  {
ereport(ERROR, (errmsg_internal("shortest_path: couldn't create query plan via SPI")));
    return -1;
  }

if ((SPIportal = SPI_cursor_open(NULL, SPIplan, NULL, NULL, true)) == NULL)
  {
ereport(ERROR, (errmsg_internal("shortest_path: SPI_cursor_open('%s') returns NULL", sql)));
    return -1;
  }

  /*
   * Initializing igraph vectors
   */
  if (igraph_vector_init(&edges, total_tuples * 2) == IGRAPH_ENOMEM)
  {
    ereport(ERROR, (errmsg_internal("No memory for edges igraph array")));
    return finish(SPIcode, ret);
  }

  /* Initialazing the vector weights*/
  if (igraph_vector_init(&eids, total_tuples) == IGRAPH_ENOMEM)
  {
    ereport(ERROR, (errmsg_internal("No memory for eids igraph array")));
    return finish(SPIcode, ret);
  }

  /* Initialazing the vector weights*/
  if (igraph_vector_init(&weights, total_tuples) == IGRAPH_ENOMEM)
  {
ereport(ERROR, (errmsg_internal("No memory for weights igraph array")));
    return finish(SPIcode, ret);
  }

  /* Initialazing the vector vertex*/
  if (igraph_vector_init(&vertex, total_tuples) == IGRAPH_ENOMEM)
  {
    ereport(ERROR, (errmsg_internal("No memory for vertex igraph array")));
    return finish(SPIcode, ret);
  }

  DBG("Valores iniciales de los vectores");
  DBG("igraph_vector_size(&edges) = %li", igraph_vector_size(&edges));
  DBG("igraph_vector_size(&eids) = %li", igraph_vector_size(&eids));
  DBG("igraph_vector_size(&weights) = %li", igraph_vector_size(&weights));
  DBG("igraph_vector_size(&vertex) = %li", igraph_vector_size(&vertex));
  DBG("");

  /*
   * getting the data from the query
   */
  while (moredata == TRUE)
  {
    SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

    /*
     * Verificamos que las columnas pasadas en el query sean las correctas
     */
    if (edge_columns.id == PGR_EMPTY)
    {
      if (fetch_edge_columns(SPI_tuptable, &edge_columns, directed) == -1)
      {
        return finish(SPIcode, ret);
      }
    }

    ntuples = SPI_processed;
    total_tuples += ntuples;

    /*
     * Initializing igraph vectors
     */
    if (igraph_vector_resize(&edges, total_tuples * 2) == IGRAPH_ENOMEM)
    {
ereport(ERROR, (errmsg_internal("No memory for edges igraph array")));
      return finish(SPIcode, ret);
    }

    /* Initialazing the vector weights*/
    if (igraph_vector_resize(&eids, total_tuples) == IGRAPH_ENOMEM)
    {
      ereport(ERROR, (errmsg_internal("No memory for eids igraph array")));
      return finish(SPIcode, ret);
    }

    /* Initialazing the vector weights*/
    if (igraph_vector_resize(&weights, total_tuples) == IGRAPH_ENOMEM)
    {
ereport(ERROR, (errmsg_internal("No memory for weights igraph array")));
      return finish(SPIcode, ret);
    }

    DBG("Valores redimensionados de los vectores");
    DBG("igraph_vector_size(&edges) = %li", igraph_vector_size(&edges));
    DBG("igraph_vector_size(&eids) = %li", igraph_vector_size(&eids));
DBG("igraph_vector_size(&weights) = %li", igraph_vector_size(&weights));
    DBG("igraph_vector_size(&vertex) = %li", igraph_vector_size(&vertex));
    DBG("");

    /*
     * load data into igraph arrays
     */
    if (ntuples > 0)
    {
      SPITupleTable *tuptable = SPI_tuptable;
      TupleDesc tupdesc = SPI_tuptable->tupdesc;
      int fret = 0;

      DBG("#---- Executing function 'fetch_edge' ----#\n");

      for (register long int i = 0; i < (long int) ntuples; i++)
      {
        HeapTuple tuple = tuptable->vals[i];
fret = fetch_edge(&tuple, &tupdesc, i, &edge_columns, &edges, &weights, &eids, &vertex, directed);
      }

      SPI_freetuptable(tuptable);

      if (fret == -1)
      {
        ereport(ERROR, (errmsg_internal("Nulls values in the data!")));
        return finish(SPIcode, ret);
      }

    }
    else
    {
      moredata = FALSE;
    }
  }

  DBG("Total tuples loaded %li", total_tuples);
  /*
   *checking: from and to in the graph, and assing the new id
   */
  /*
  DBG("nuevo FROM = %i",search_element(&from, &vertex));
  if ((from = search_element(&from, &vertex)) == -1)
  {
    igraph_vector_destroy(&weights);
    igraph_vector_destroy(&edges);
    igraph_vector_destroy(&eids);
    igraph_vector_destroy(&vertex);

    ereport(ERROR, (errmsg_internal("the source id is not in the graph")));
    return finish(SPIcode, ret);
  }

  if ((to = search_element(&to, &vertex)) == -1)
  {
    igraph_vector_destroy(&weights);
    igraph_vector_destroy(&edges);
    igraph_vector_destroy(&eids);
    igraph_vector_destroy(&vertex);

    ereport(ERROR, (errmsg_internal("the target id is not in the graph")));
    return finish(SPIcode, ret);
  }
*/
DBG("source_id = %i, target_id = %i --> from = %li, to = %li", start_vertex,end_vertex,(long int) from,(long int) to);

  /*Create the graph*/
  if (directed)
  {
    DBG("************************************");
    DBG("El grafo es dirigido");
    DBG("************************************");
    ret = igraph_create(&graph, &edges, 0, IGRAPH_DIRECTED);
    if ((ret == IGRAPH_EINVEVECTOR) || (ret == IGRAPH_EINVVID))
    {
      igraph_vector_destroy(&weights);
      igraph_vector_destroy(&edges);
      igraph_vector_destroy(&eids);
      igraph_vector_destroy(&vertex);
ereport(ERROR, (errmsg_internal("Problems creating the graph, check your edges vector!")));
      return finish(SPIcode, ret);
    }
  }
  else
  {
    DBG("************************************");
    DBG("El grafo es no-dirigido");
    DBG("************************************");
    ret = igraph_create(&graph, &edges, 0, IGRAPH_UNDIRECTED);
    if ((ret == IGRAPH_EINVEVECTOR) || (ret == IGRAPH_EINVVID))
    {
      igraph_vector_destroy(&weights);
      igraph_vector_destroy(&edges);
      igraph_vector_destroy(&eids);
      igraph_vector_destroy(&vertex);
ereport(ERROR, (errmsg_internal("Problems creating the graph, check your edges vector!")));
      return finish(SPIcode, ret);
    }
  }
  // filling the graph attr
  for (register long int i = 0; i <  (long int) igraph_ecount(&graph); i++)
  {
    //filling the my own edges ids
    SETEAN(&graph, "id", (igraph_integer_t) i, VECTOR(eids)[i]);

    DBG("i=%li",i);
DBG("VECTOR(edges)[2*i]=%li, VECTOR(edges)[(2*i)+1]=%li",(long int) VECTOR(edges)[2*i], (long int) VECTOR(edges)[(2*i)+1]);
    DBG("VECTOR(eids)[i]=%d", (long int) VECTOR(eids)[i]);
    DBG("VECTOR(weights)[i]=%f", (double) VECTOR(weights)[i]);

  }

DBG("Number of: vertex = %li, edges = %li \n", (long int) igraph_vcount(&graph), (long int) igraph_ecount(&graph));

  /* vectors for results*/
  igraph_vector_t result;
  igraph_vector_ptr_t result_vector;
  igraph_vector_init(&result, 0);
  igraph_vector_ptr_init(&result_vector, 1);
  VECTOR(result_vector)[0] = &result;

  /* Calculating shortest paths*/
ret = igraph_get_shortest_paths_dijkstra(&graph, &result_vector, from, igraph_vss_1(to),
&weights, IGRAPH_OUT);

  DBG("valor devuelto por igraph_get_shortest_paths_dijkstra %i",ret);

if ((ret == IGRAPH_ENOMEM) || (ret == IGRAPH_EINVVID) || (ret == IGRAPH_EINVMODE))
  {
    igraph_vector_destroy(&weights);
    igraph_vector_destroy(&edges);
    igraph_vector_destroy(&eids);
    igraph_vector_destroy(&vertex);
    igraph_destroy(&graph);
    igraph_vector_destroy(&result);
    igraph_vector_ptr_destroy(&result_vector);
ereport(ERROR, (errmsg_internal("Problems calculating igraph_get_shortest_paths_dijkstra, check yours vectors data!")));
    return finish(SPIcode, ret);
  }

  //dot not exist shortest path from --> to
  /*
  if(igraph_vector_size(&result) == 0)
  {
    printf("dot not exist shortest path from --> to \n\n");
    igraph_vector_destroy(&weights);
    igraph_vector_destroy(&edges);
    igraph_vector_destroy(&eids);
    igraph_vector_destroy(&vertex);
    igraph_destroy(&graph);
    igraph_vector_destroy(&result);
    igraph_vector_ptr_destroy(&result_vector);
    return EXIT_FAILURE;
  }
   */
/*tamaño del vector resultados, numero de elementos que vienen en el resultado*/
  long int stpr_count = igraph_vector_size(&result);
  *path_count = (uint32) stpr_count;

DBG("Numero de resultados devueltos igraph_get_shortest_paths_dijkstra= %i",*path_count);

if ( ((*path) = (ShortestPathRec *) SPI_palloc( sizeof(ShortestPathRec) * (*path_count) )) == NULL )
   {
     igraph_vector_destroy(&weights);
     igraph_vector_destroy(&edges);
     igraph_vector_destroy(&eids);
     igraph_vector_destroy(&vertex);
     igraph_destroy(&graph);
     igraph_vector_destroy(&result);
     igraph_vector_ptr_destroy(&result_vector);
ereport(ERROR, (errmsg_internal("problems allocating memory for path pointer")));
     return finish(SPIcode, ret);
   }

  DBG("*** Resultado de igraph_get_shortest_paths_dijkstra ****");

  /*Putting the result in my own structure*/
  for (register long int i = 0; i < stpr_count; i++)
  {

    DBG("Vertex id = %li",(long int) VECTOR(result)[i]);

    (*path)[i].step = ((int32) i)+1;

//(*path)[i].vertex_id = (int32) VECTOR(vertex)[(long int) VECTOR(result)[(long int) i]];
    (*path)[i].vertex_id = (int32) VECTOR(result)[i];

    if (i < (stpr_count - 1))
    {
      (*path)[i].edge_id = (int32) EAN(&graph,"id",search_eid(&graph,
VECTOR(result)[i], VECTOR(result)[i+1], igraph_is_directed(&graph))
                                       );
      //for the future
      (*path)[i].cost = (float8) 0.0;
    }
    else
    {
      (*path)[i].edge_id = (int32) -1;
      //for the future
      (*path)[i].cost = (float8) -1;
    }
  }

  DBG("Number of result  %i\n",*path_count);
  DBG("ret = %i\n", ret);

  /*free memory*/
  igraph_destroy(&graph);
  igraph_vector_destroy(&result);
  igraph_vector_destroy(&weights);
  igraph_vector_destroy(&eids);
  igraph_vector_destroy(&vertex);
  igraph_vector_ptr_destroy(&result_vector);
  igraph_vector_destroy(&edges);

  return finish(SPIcode, ret);
}

/*
 *
 */
static int finish(int code, int ret)
{
  DBG("#---- executing function 'finish' ----#\n");

  code = SPI_finish();
  if (code != SPI_OK_FINISH)
  {
    ereport(ERROR, (errmsg_internal("couldn't disconnect from SPI")));
    return -1;
  }
  return ret;
}

/*
 * verify if the "mandatory and additional columns" were passed to query
 */
static int fetch_edge_columns(SPITupleTable *tuptable, pgr_edge_columns_t *edge_columns, bool directed)
{

  DBG("#---- executing function 'fetch_edge_columns' ----#\n");
  /*
   * Getting the column number from the query
   */
  edge_columns->id = SPI_fnumber(tuptable->tupdesc, "id");
  edge_columns->source = SPI_fnumber(tuptable->tupdesc, "source");
  edge_columns->target = SPI_fnumber(tuptable->tupdesc, "target");
  edge_columns->cost = SPI_fnumber(tuptable->tupdesc, "cost");

  /*
   *Additional columns
   */
edge_columns->bidirectional = SPI_fnumber(tuptable->tupdesc, "bidirectional"); edge_columns->reverse_cost = SPI_fnumber(tuptable->tupdesc, "reverse_cost");

  /*
* verify if the "mandatory columns" were passed to query string really exists
   */
if (edge_columns->id == SPI_ERROR_NOATTRIBUTE || edge_columns->source == SPI_ERROR_NOATTRIBUTE || edge_columns->target == SPI_ERROR_NOATTRIBUTE || edge_columns->cost == SPI_ERROR_NOATTRIBUTE)
  {
ereport(ERROR, (errmsg_internal("Error!: Query must return columns 'id', 'source', 'target' and 'cost'")));
    return -1;
  }

  /*
   * verify if the "mandatory columns" data type are corrects
   */
  if (SPI_gettypeid(tuptable->tupdesc, edge_columns->id) != INT4OID
      || SPI_gettypeid(tuptable->tupdesc, edge_columns->source) != INT4OID
      || SPI_gettypeid(tuptable->tupdesc, edge_columns->target) != INT4OID
      || SPI_gettypeid(tuptable->tupdesc, edge_columns->cost) != FLOAT8OID)
  {
ereport(ERROR, (errmsg_internal("Error, columns 'id', 'source', 'target' must be of type integer and 'cost' must be of type float8")));
    return -1;
  }

  DBG("Query columns numbers");

  DBG("id = %i", edge_columns->id);
  DBG("source = %i",edge_columns->source);
  DBG("target = %i",edge_columns->target);
  DBG("cost = %i",edge_columns->cost);
  DBG("");

  /*
* verify if the "additional column bidirectional" were passed to query string
   */

  if (edge_columns->bidirectional == SPI_ERROR_NOATTRIBUTE)
  {
    edge_columns->bidirectional = PGR_EMPTY;
  }
  else
  {
DBG("Additional column number: bidirectional=%i", edge_columns->bidirectional);

    if (directed)
    {
if (SPI_gettypeid(tuptable->tupdesc, edge_columns->bidirectional) != BOOLOID)
      {
ereport(ERROR, (errmsg_internal("Error, columns 'bidirectional' must be of type bool")));
        return -1;
      }
    }
    else
    {
DBG("Additional column 'bidirectional' exists in the query, but it is not used because the 'directed' parameter is false");
    }
  }

  /*
   * verify if the "additional column reverse_cost" were passed to query
   */
  if (edge_columns->reverse_cost == SPI_ERROR_NOATTRIBUTE)
  {
    edge_columns->reverse_cost = PGR_EMPTY;
  }
  else
  {
DBG("Additional column number: reverse_cost=%i", edge_columns->reverse_cost);

    if (directed)
    {
if (SPI_gettypeid(tuptable->tupdesc, edge_columns->reverse_cost) != FLOAT8OID)
      {
ereport(ERROR, (errmsg_internal("Error, columns 'reverse_cost' must be of type float8")));
        return -1;
      }
    }
    else
    {
DBG("Additional column 'reverse_cost' exists in the query, but it is not used because the 'directed' parameter is false");
    }
  }
  return 0;
}

/*
 *
 */
static int fetch_edge(HeapTuple *tuple, TupleDesc *tupdesc, long int i, pgr_edge_columns_t *edge_columns, igraph_vector_t *edges, igraph_vector_t *weights, igraph_vector_t *eids,
           igraph_vector_t *vertex, bool directed)
{

  Datum id_binval;
  Datum s_binval;
  Datum t_binval;
  Datum c_binval;
  Datum d_binval;
  Datum rc_binval;

  bool isnull;
  bool hasrc = false;
  int32 nsp = -1;
  int32 ntp = -1;

  //getting the id value
  id_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->id, &isnull);
  if (isnull)
  {
    ereport(ERROR, (errmsg_internal("id colummn contains a null value")));
    return -1;
  }
  //getting the source value
s_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->source, &isnull);
  if (isnull)
  {
ereport(ERROR, (errmsg_internal("source colummn contains a null value")));
    return -1;
  }
  //getting the target value
t_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->target, &isnull);
  if (isnull)
  {
ereport(ERROR, (errmsg_internal("target colummn contains a null value")));
    return -1;
  }
  //getting the cost value
  c_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->cost, &isnull);
  if (isnull)
  {
    ereport(ERROR, (errmsg_internal("cost contains a null value")));
    return -1;
  }

  /*
   * re-enumerate the source and target ids
   */
  /*
  int32 s = DatumGetInt32(s_binval);
  int32 t = DatumGetInt32(t_binval);

  if(reenumerate(&s, &t, &nsp, &ntp, vertex) == -1)
  {
ereport(ERROR, (errmsg_internal("problem allocating memory in reenumerate function")));
    return -1;
  }
*/
  /*
  VECTOR(*eids)[i] = DatumGetInt32(id_binval);
  VECTOR(*edges)[(2* i )] = nsp;
  VECTOR(*edges)[(2* i ) + 1] = ntp;
  VECTOR(*weights)[i] = DatumGetFloat8(c_binval);
*/

  VECTOR(*eids)[i] = DatumGetInt32(id_binval);
  VECTOR(*edges)[(2*i)] = DatumGetInt32(s_binval);
  VECTOR(*edges)[(2*i) + 1] = DatumGetInt32(t_binval);
  VECTOR(*weights)[i] = DatumGetFloat8(c_binval);

DBG("edges values = edge %li: id=%i source=%i target=%i cost=%f ---> edge %li: id=%li source=%li target=%li cost=%f",
      i,
      DatumGetInt32(id_binval),
      DatumGetInt32(s_binval),
      DatumGetInt32(t_binval),
      DatumGetFloat8(c_binval),
      i,
      (long int) VECTOR(*eids)[i],
      (long int) VECTOR(*edges)[(2* i)],
      (long int) VECTOR(*edges)[(2* i) + 1],
      VECTOR(*weights)[i]
  );

  DBG("Valores en la iteracion de los vectores");
  DBG("igraph_vector_size(edges) = %li", igraph_vector_size(edges));
  DBG("igraph_vector_size(eids) = %li", igraph_vector_size(eids));
  DBG("igraph_vector_size(weights) = %li", igraph_vector_size(weights));
  DBG("igraph_vector_size(vertex) = %li", igraph_vector_size(vertex));
  DBG("");

  if (directed)
  {
    /*
     * Get values from additional columns
     */
d_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->bidirectional, &isnull);
    if (isnull)
    {
ereport(ERROR, (errmsg_internal("bidirectional contains a null value")));
      return -1;
    }

    if (edge_columns->reverse_cost != PGR_EMPTY)
    {
rc_binval = SPI_getbinval(*tuple, *tupdesc, edge_columns->reverse_cost, &isnull);
      if (isnull)
      {
ereport(ERROR, (errmsg_internal("reverse_cost contains a null value")));
        return -1;
      }

      hasrc = true;

    }
//Si el lado es bidirecional es cargado en el otro sentido para los grafos dirigidos
    if (DatumGetBool(d_binval))
    {
      long int dta_edges = igraph_vector_size(edges);
      long int dta_weights = igraph_vector_size(weights);
      long int dta_eids = igraph_vector_size(eids);

      if ((igraph_vector_resize(edges, dta_edges + 2)) == IGRAPH_ENOMEM)
      {
        printf("problems allocating memory for edges vector");
        igraph_vector_destroy(weights);
        igraph_vector_destroy(edges);
        igraph_vector_destroy(eids);
        igraph_vector_destroy(vertex);
        return -1;
      }

//reservamos mas memoria para el vector, ya que vemos a añadir otro lado if ((igraph_vector_resize(weights, dta_weights + 1)) == IGRAPH_ENOMEM)
      {
        printf("problems allocating memory for weights vector");
        igraph_vector_destroy(weights);
        igraph_vector_destroy(edges);
        igraph_vector_destroy(eids);
        igraph_vector_destroy(vertex);
        return -1;
      }

//reservamos mas memoria para el vector, ya que vemos a añadir otro lado
      if ((igraph_vector_resize(eids, dta_eids + 1)) == IGRAPH_ENOMEM)
      {
        printf("problems allocating memory for eids vector");
        igraph_vector_destroy(weights);
        igraph_vector_destroy(edges);
        igraph_vector_destroy(eids);
        igraph_vector_destroy(vertex);
        return -1;
      }
/*
      VECTOR(*eids)[dta_eids] = DatumGetInt32(id_binval);
      VECTOR(*edges)[dta_edges] = ntp;
      VECTOR(*edges)[dta_edges + 1] = nsp;
*/

      VECTOR(*eids)[dta_eids] = DatumGetInt32(id_binval);
      VECTOR(*edges)[dta_edges] = DatumGetInt32(t_binval);
      VECTOR(*edges)[dta_edges + 1] = DatumGetInt32(s_binval);

DBG("Valores de los vectores redimensionados por el parametro directed");
      DBG("igraph_vector_size(edges) = %li", igraph_vector_size(edges));
      DBG("igraph_vector_size(eids) = %li", igraph_vector_size(eids));
DBG("igraph_vector_size(weights) = %li", igraph_vector_size(weights));
      DBG("igraph_vector_size(vertex) = %li", igraph_vector_size(vertex));
      DBG("");

      if(hasrc)
      {
VECTOR(*weights)[dta_weights] = (igraph_real_t) DatumGetFloat8(rc_binval);
      }
      else
      {
VECTOR(*weights)[dta_weights] = (igraph_real_t) DatumGetFloat8(c_binval);
      }
/*
DBG("edges values = edge %i: id=%i source=%i target=%i cost=%f ---> edge %f: id=%f source=%f target=%f cost=%f",
          i,
          DatumGetInt32(id_binval),
          DatumGetInt32(s_binval),
          DatumGetInt32(t_binval),
          DatumGetFloat8(c_binval),
          i,
          VECTOR(*eids)[dta_eids],
          VECTOR(*edges)[dta_edges],
          VECTOR(*edges)[dta_edges + 1],
          VECTOR(*weights)[dta_weights]
      );
      */
    }
  }
  return 0;
}
/*
 *
 */
static int reenumerate(const igraph_real_t *source, const igraph_real_t *target, igraph_real_t *newsource,
                       igraph_real_t *newtarget, igraph_vector_t *v)
{
  long int i = 0, *ind = NULL;
  ind = &i;
  /*
  igraph_bool_t igraph_vector_search(const igraph_vector_t *v,
  long int from, igraph_real_t what,
  long int *pos);
  */
  if (igraph_vector_search(v, 0, *source, ind))
  {
    *newsource =  (igraph_real_t) (*ind);
  }
  else
  {
    if ((igraph_vector_push_back(v, *source)) == IGRAPH_ENOMEM)
    {
      printf("problems allocating memory for v vector");
      return -1;
    }
    *newsource = (igraph_real_t) (igraph_vector_size(v) - 1);
  }

  if (igraph_vector_search(v, 0, *target, ind))
  {
    *newtarget = (igraph_real_t) (*ind);
  }
  else
  {
    if ((igraph_vector_push_back(v, *target)) == IGRAPH_ENOMEM)
    {
      printf("problems allocating memory for v vector");
      return -1;
    }
    *newtarget = (igraph_real_t) (igraph_vector_size(v) - 1);
  }
DBG("s=%i t=%i --> ns=%i nt=%i ", *source, *target,*newsource,*newtarget);
  return 0;
}

/*
 *
 */
static long int search_element(const igraph_real_t *id, igraph_vector_t *v)
{
  long int i = 0, *ind = NULL;
  ind = &i;

  DBG("valor de *id=%i",igraph_vector_search(v, 0, *id, ind));

  if (igraph_vector_search(v, 0, *id, ind))
  {
    return *ind;
  }
  else
  {
    return -1;
  }
}

/*
 *
 */
static igraph_integer_t search_eid(igraph_t *g, const igraph_real_t id1, const igraph_real_t id2, igraph_bool_t directed)
{
  igraph_vector_t pair;
  igraph_vector_init(&pair, 2);
  igraph_vector_t out;
  igraph_vector_init(&out, 0);
  igraph_integer_t value = -1;

  VECTOR(pair)[0] = id1;
  VECTOR(pair)[1] = id2;

  igraph_get_eids(g, &out, &pair, directed);

  value = (igraph_integer_t) VECTOR(out)[0];
  igraph_vector_destroy(&out);
  igraph_vector_destroy(&pair);

  return value;
}







reply via email to

[Prev in Thread] Current Thread [Next in Thread]