예제 #1
0
파일: routing.c 프로젝트: alvarop/cwRoute
/*******************************************************************************
 * @fn    void *compute_routes_thread( void *rp_tables )
 *
 * @brief Thread that takes care of routing
 * ****************************************************************************/
void *compute_routes_thread( void *rp_tables )
{
  static uint32_t index;
  uint8_t node_index;
  uint8_t *route_table = &((uint8_t*)rp_tables)[0];
  uint8_t *power_table = &((uint8_t*)rp_tables)[MAX_DEVICES];
  
  
  // loop forever
  for (;;)
  {
    // Block until next table is ready
    pthread_mutex_lock ( &mutex_route_start );

    // Assuming rssi_table has been updated
    clean_table( rssi_table );

    add_links_from_table( rssi_table );

    // Run dijkstra's algorithm with 0 being the access point
    dijkstra( AP_NODE_ID, c_factor );

    // Display shortest paths and update energies
    for( node_index = 1; node_index < (MAX_DEVICES + 1); node_index++ )
    {
      compute_shortest_path( node_index );
      print_shortest_path( node_index );
    }

    // Compute routing table
    compute_rp_tables( route_table, link_powers );

    // Debug
    memcpy( previous_powers_debug, previous_powers, sizeof(previous_powers) );
    memcpy( route_table_debug, route_table, sizeof(route_table_debug) );

    // Compute power table
    compute_required_powers( link_powers, power_table );

    print_rssi_table();

    print_node_energy( AP_NODE_ID, fp_energies );

    index++;
    printf("\nRound %d\n", index);

    // Block until next table is ready
    pthread_mutex_unlock ( &mutex_route_done );

  }

  return NULL;
}
예제 #2
0
 auto replan(Cells const& cells_to_toggle = {})
 {
     reset_statistics();
     for (auto c : cells_to_toggle)
     {
         at(c).bad = !at(c).bad;
         if (!at(c).bad)
             update_vertex(at(c));
         else
             at(c).g = at(c).r = huge();
         update_neighbours_of(c);
     }
     compute_shortest_path();
 }
예제 #3
0
    // e - supply(positive) and demand(negative).
    // c[i] - edges that goes from node i. first is the second nod
    // x - the flow is returned in it
    NUM_T operator()(std::vector<NUM_T>& e,
                     const std::vector< std::list< edge<NUM_T> > >& c,
                     std::vector< std::list<  edge0<NUM_T>  > >& x) {

        //for (NODE_T i=0; i<e.size(); ++i) cout << e[i]<< " ";
        //cout << endl;
        //tictoc_all_function.tic();
                
        assert(e.size()==c.size());
        assert(x.size()==c.size());
        
        _num_nodes= (NODE_T)e.size();
        _nodes_to_Q.resize(_num_nodes);
        
        // init flow
        {for (NODE_T from=0; from<_num_nodes; ++from) {
            {for (typename std::list< edge<NUM_T> >::const_iterator it= c[from].begin(); it!=c[from].end(); ++it) {
                x[from].push_back(  edge0<NUM_T> (it->_to, it->_cost, 0) );
                x[it->_to].push_back(  edge0<NUM_T> (from, -it->_cost,0) );
            }} // it
        }} // from
        
        // reduced costs for forward edges (c[i,j]-pi[i]+pi[j])
        // Note that for forward edges the residual capacity is infinity
        std::vector< std::list< edge1<NUM_T> > > r_cost_forward(_num_nodes);
        {for (NODE_T from=0; from<_num_nodes; ++from) {
            {for (typename std::list<  edge<NUM_T>  >::const_iterator it= c[from].begin(); it!=c[from].end(); ++it) {
                    r_cost_forward[from].push_back( edge1<NUM_T>(it->_to,it->_cost) );
            }}
        }}
        
        // reduced costs and capacity for backward edges (c[j,i]-pi[j]+pi[i])
        // Since the flow at the beginning is 0, the residual capacity is also zero
        std::vector< std::list< edge2<NUM_T> > > r_cost_cap_backward(_num_nodes);
        {for (NODE_T from=0; from<_num_nodes; ++from) {
            {for (typename std::list<  edge<NUM_T>  >::const_iterator it= c[from].begin(); it!=c[from].end(); ++it) {
                    r_cost_cap_backward[ it->_to ].push_back( edge2<NUM_T>(from,-it->_cost,0) );
            }} // it
        }} // from
        
        // Max supply TODO:demand?, given U?, optimization-> min out of demand,supply
        NUM_T U= 0;
        {for (NODE_T i=0; i<_num_nodes; ++i) {
            if (e[i]>U) U= e[i];
        }}
        NUM_T delta= static_cast<NUM_T>(pow(2.0l,ceil(log(static_cast<long double>(U))/log(2.0))));

        

        std::vector< NUM_T > d(_num_nodes);
        std::vector< NODE_T > prev(_num_nodes);
        delta= 1;
        //while (delta>=1) {
        
            // delta-scaling phase
            //cout << "delta==" << delta << endl;
        
        //tictoc_while_true.tic();
        while (true) { //until we break when S or T is empty
                
                NUM_T maxSupply= 0;
                NODE_T k=0;
                for (NODE_T i=0; i<_num_nodes; ++i) {
                    if (e[i]>0) {
                        if (maxSupply<e[i]) {
                            maxSupply= e[i];
                            k= i; 
                        }
                    }
                }
                if (maxSupply==0) break;
                delta= maxSupply;

                NODE_T l;
                //tictoc_shortest_path.tic();
                compute_shortest_path(d,prev, k,r_cost_forward,r_cost_cap_backward , e,l); 
                //tictoc_shortest_path.toc(); 
                

                
                //---------------------------------------------------------------
                // find delta (minimum on the path from k to l)
                //delta= e[k];
                //if (-e[l]<delta) delta= e[k];
                NODE_T to= l;
                do {
                    NODE_T from= prev[to];
                    assert(from!=to);
                                        
                    // residual
                    typename std::list< edge2<NUM_T> >::iterator itccb= r_cost_cap_backward[from].begin();
                    while ( (itccb!=r_cost_cap_backward[from].end()) && (itccb->_to!=to) ) {
                        ++itccb;
                    }
                    if (itccb!=r_cost_cap_backward[from].end()) {
                        if (itccb->_residual_capacity<delta) delta= itccb->_residual_capacity;
                    }
                    
                    to= from;
                } while (to!=k);
                //---------------------------------------------------------------

                //---------------------------------------------------------------
                // augment delta flow from k to l (backwards actually...)
                to= l;
                do {
                    NODE_T from= prev[to];
                    assert(from!=to);
                                        
                    // TODO - might do here O(n) can be done in O(1)
                    typename std::list<  edge0<NUM_T>  >::iterator itx= x[from].begin();
                    while (itx->_to!=to) {
                        ++itx;
                    }
                    itx->_flow+= delta;
                                        
                    // update residual for backward edges
                    typename std::list< edge2<NUM_T> >::iterator itccb= r_cost_cap_backward[to].begin();
                    while ( (itccb!=r_cost_cap_backward[to].end()) && (itccb->_to!=from) ) {
                        ++itccb;
                    }
                    if (itccb!=r_cost_cap_backward[to].end()) {
                        itccb->_residual_capacity+= delta;
                    }
                    itccb= r_cost_cap_backward[from].begin();
                    while ( (itccb!=r_cost_cap_backward[from].end()) && (itccb->_to!=to) ) {
                        ++itccb;
                    }
                    if (itccb!=r_cost_cap_backward[from].end()) {
                        itccb->_residual_capacity-= delta;
                    }

                    // update e
                    e[to]+= delta;
                    e[from]-= delta;
                        
                    to= from;
                } while (to!=k);
                //---------------------------------------------------------------------------------

                
                
            } // while true (until we break when S or T is empty)
            //tictoc_while_true.toc();
            //cout << "while true== " << tictoc_while_true.totalTimeSec() << endl;
            
            //delta= delta/2;
            //} // (delta-scaling phase)
            
            
            // compute distance from x
            //cout << endl << endl;
            NUM_T dist= 0;
            {for (NODE_T from=0; from<_num_nodes; ++from) {
                {for (typename std::list<  edge0<NUM_T>  >::const_iterator it= x[from].begin(); it!=x[from].end(); ++it) {
//                        if (it->_flow!=0) cout << from << "->" << it->_to << ": " << it->_flow << "x" << it->_cost << endl;
                        dist+= (it->_cost*it->_flow);
                }} // it
            }} // from
            
            
            //tictoc_all_function.toc();
            //cout << "operator() time==" << tictoc_all_function.totalTimeSec() << endl;
            //cout << "compute_shortest_path_time==" << tictoc_shortest_path.totalTimeSec() << endl;
            //cout << "tmp_tic_toc== " << tmp_tic_toc.totalTimeSec() << endl;
            return dist;
    } // operator()
예제 #4
0
 auto plan()
 {
     reset_statistics();
     initialize();
     compute_shortest_path();
 }
예제 #5
0
static int compute_shortest_path(char* sql, int start_vertex, 
                                 int end_vertex, bool directed, 
                                 bool has_reverse_cost, 
                                 path_element_t **path, int *path_count) 
{

  int SPIcode;
  void *SPIplan;
  Portal SPIportal;
  bool moredata = TRUE;
  int ntuples;
  edge_t *edges = NULL;
  int total_tuples = 0;
  edge_columns_t edge_columns = {id: -1, source: -1, target: -1, 
                                 cost: -1, reverse_cost: -1};
  int v_max_id=0;
  int v_min_id=INT_MAX;

  int s_count = 0;
  int t_count = 0;

  char *err_msg;
  int ret = -1;
  register int z;

  DBG("start shortest_path\n");
        
  SPIcode = SPI_connect();
  if (SPIcode  != SPI_OK_CONNECT)
    {
      elog(ERROR, "shortest_path: couldn't open a connection to SPI");
      return -1;
    }

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

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

  while (moredata == TRUE)
    {
      SPI_cursor_fetch(SPIportal, TRUE, TUPLIMIT);

      if (edge_columns.id == -1) 
        {
          if (fetch_edge_columns(SPI_tuptable, &edge_columns, 
                                 has_reverse_cost) == -1)
	    return finish(SPIcode, ret);
        }

      ntuples = SPI_processed;
      total_tuples += ntuples;
      if (!edges)
        edges = palloc(total_tuples * sizeof(edge_t));
      else
        edges = repalloc(edges, total_tuples * sizeof(edge_t));

      if (edges == NULL) 
        {
          elog(ERROR, "Out of memory");
	    return finish(SPIcode, ret);	  
        }

      if (ntuples > 0) 
        {
          int t;
          SPITupleTable *tuptable = SPI_tuptable;
          TupleDesc tupdesc = SPI_tuptable->tupdesc;
                
          for (t = 0; t < ntuples; t++) 
            {
              HeapTuple tuple = tuptable->vals[t];
              fetch_edge(&tuple, &tupdesc, &edge_columns, 
                         &edges[total_tuples - ntuples + t]);
            }
          SPI_freetuptable(tuptable);
        } 
      else 
        {
          moredata = FALSE;
        }
    }

  //defining min and max vertex id
      
  DBG("Total %i tuples", total_tuples);
    
  for(z=0; z<total_tuples; z++)
  {
    if(edges[z].source<v_min_id)
    v_min_id=edges[z].source;
  
    if(edges[z].source>v_max_id)
      v_max_id=edges[z].source;
		            
    if(edges[z].target<v_min_id)
      v_min_id=edges[z].target;

    if(edges[z].target>v_max_id)
      v_max_id=edges[z].target;      
								        
    DBG("%i <-> %i", v_min_id, v_max_id);
							
  }

  //::::::::::::::::::::::::::::::::::::  
  //:: reducing vertex id (renumbering)
  //::::::::::::::::::::::::::::::::::::
  for(z=0; z<total_tuples; z++)
  {
    //check if edges[] contains source and target
    if(edges[z].source == start_vertex || edges[z].target == start_vertex)
      ++s_count;
    if(edges[z].source == end_vertex || edges[z].target == end_vertex)
      ++t_count;

    edges[z].source-=v_min_id;
    edges[z].target-=v_min_id;
    DBG("%i - %i", edges[z].source, edges[z].target);      
  }

  DBG("Total %i tuples", total_tuples);

  if(s_count == 0)
  {
    elog(ERROR, "Source vertex: %d was not found as vertex of any of the input edges.", start_vertex);
    return -1;
  }
      
  if(t_count == 0)
  {
    elog(ERROR, "Target vertex: %d was not found as vertex of any of the input edges.", end_vertex);
    return -1;
  }
  
  DBG("Calling boost_dijkstra\n");
        
  start_vertex -= v_min_id;
  end_vertex   -= v_min_id;

  ret = boost_dijkstra(edges, total_tuples, start_vertex, end_vertex,
                       directed, has_reverse_cost,
                       path, path_count, &err_msg);

  DBG("SIZE %i\n",*path_count);

  //::::::::::::::::::::::::::::::::
  //:: restoring original vertex id
  //::::::::::::::::::::::::::::::::
  for(z=0;z<*path_count;z++)
  {
    //DBG("vetex %i\n",(*path)[z].vertex_id);
    (*path)[z].vertex_id+=v_min_id;
  }

  DBG("ret = %i\n", ret);

  DBG("*path_count = %i\n", *path_count);

  DBG("ret = %i\n", ret);
  
  if (ret < 0)
    {
      //elog(ERROR, "Error computing path: %s", err_msg);
      ereport(ERROR, (errcode(ERRCODE_E_R_E_CONTAINING_SQL_NOT_PERMITTED), 
        errmsg("Error computing path: %s", err_msg)));
    } 

  if (edges) {
    /* clean up input egdes */
    pfree (edges);
  }
    
  return finish(SPIcode, ret);
}


PG_FUNCTION_INFO_V1(shortest_path);
Datum
shortest_path(PG_FUNCTION_ARGS)
{
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  path_element_t      *path = NULL;
  char                *sql = NULL;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL())
    {
      MemoryContext   oldcontext;
      int path_count = 0;
      int ret;

      /* 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);

      /* edge sql query */
      sql = text2char(PG_GETARG_TEXT_P(0));

      ret = compute_shortest_path(sql,
                                  PG_GETARG_INT32(1),
                                  PG_GETARG_INT32(2),
                                  PG_GETARG_BOOL(3),
                                  PG_GETARG_BOOL(4), &path, &path_count);

      /* clean up sql query string */
      if (sql) {
        pfree (sql);
      }

#ifdef DEBUG
      DBG("Ret is %i", ret);
      if (ret >= 0) 
        {
          int i;
          for (i = 0; i < path_count; i++) 
            {
              DBG("Step %i vertex_id  %i ", i, path[i].vertex_id);
              DBG("        edge_id    %i ", path[i].edge_id);
              DBG("        cost       %f ", path[i].cost);
            }
        }
#endif

      /* total number of tuples to be returned */
      funcctx->max_calls = path_count;
      funcctx->user_fctx = path;

      funcctx->tuple_desc = 
        BlessTupleDesc(RelationNameGetTupleDesc("path_result"));

      MemoryContextSwitchTo(oldcontext);
    }

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

  call_cntr = funcctx->call_cntr;
  max_calls = funcctx->max_calls;
  tuple_desc = funcctx->tuple_desc;
  path = (path_element_t*) funcctx->user_fctx;

  if (call_cntr < max_calls)    /* do when there is more left to send */
    {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      char* nulls;

      /* This will work for some compilers. If it crashes with segfault, try to change the following block with this one    
 
      values = palloc(4 * sizeof(Datum));
      nulls = palloc(4 * sizeof(char));
  
      values[0] = call_cntr;
      nulls[0] = ' ';
      values[1] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[1] = ' ';
      values[2] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[2] = ' ';
      values[3] = Float8GetDatum(path[call_cntr].cost);
      nulls[3] = ' ';
      */
    
      values = palloc(3 * sizeof(Datum));
      nulls = palloc(3 * sizeof(char));

      values[0] = Int32GetDatum(path[call_cntr].vertex_id);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(path[call_cntr].edge_id);
      nulls[1] = ' ';
      values[2] = Float8GetDatum(path[call_cntr].cost);
      nulls[2] = ' ';
		      
      tuple = heap_formtuple(tuple_desc, values, nulls);

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

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

      SRF_RETURN_NEXT(funcctx, result);
    }
  else    /* do when there is no more left */
    {
      if (path) {
        /* clean up returned edge paths
           must be a free because it's malloc'd */
        free (path);
        path = NULL;
      }

      SRF_RETURN_DONE(funcctx);
    }
}
예제 #6
0
Datum
shortest_path(PG_FUNCTION_ARGS) {
  FuncCallContext     *funcctx;
  int                  call_cntr;
  int                  max_calls;
  TupleDesc            tuple_desc;
  pgr_path_element3_t  *ret_path = 0;

  /* stuff done only on the first call of the function */
  if (SRF_IS_FIRSTCALL()) {
      MemoryContext   oldcontext;
      int path_count = 0;

      /* 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);


      compute_shortest_path(pgr_text2char(PG_GETARG_TEXT_P(0)),
                                  PG_GETARG_INT64(1),
                                  PG_GETARG_INT64(2),
                                  PG_GETARG_BOOL(3),
                                  PG_GETARG_BOOL(4), &ret_path, &path_count);

      /* total number of tuples to be returned */
      funcctx->max_calls = path_count;
      funcctx->user_fctx = ret_path;
      if (get_call_result_type(fcinfo, NULL, &tuple_desc) != TYPEFUNC_COMPOSITE)
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("function returning record called in context "
                            "that cannot accept type record")));

      funcctx->tuple_desc = tuple_desc;

      MemoryContextSwitchTo(oldcontext);
  }

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

  call_cntr = funcctx->call_cntr;
  max_calls = funcctx->max_calls;
  tuple_desc = funcctx->tuple_desc;
  ret_path = (pgr_path_element3_t*) funcctx->user_fctx;

  /* do when there is more left to send */
  if (call_cntr < max_calls) {
      HeapTuple    tuple;
      Datum        result;
      Datum *values;
      char* nulls;

      values = palloc(6 * sizeof(Datum));
      nulls = palloc(6 * sizeof(char));

      values[0] = Int32GetDatum(ret_path[call_cntr].seq);
      nulls[0] = ' ';
      values[1] = Int32GetDatum(ret_path[call_cntr].seq);
      nulls[1] = ' ';
      values[2] = Int64GetDatum(ret_path[call_cntr].vertex);
      nulls[2] = ' ';
      values[3] = Int64GetDatum(ret_path[call_cntr].edge);
      nulls[3] = ' ';
      values[4] = Float8GetDatum(ret_path[call_cntr].cost);
      nulls[4] = ' ';
      values[5] = Float8GetDatum(ret_path[call_cntr].tot_cost);
      nulls[5] = ' ';

      tuple = heap_formtuple(tuple_desc, values, nulls);

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

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

      SRF_RETURN_NEXT(funcctx, result);
  } else {
      /* do when there is no more left */
      if (ret_path) free(ret_path);
      SRF_RETURN_DONE(funcctx);
  }
}