示例#1
0
void r_c_shortest_paths_dispatch
( const Graph& g, 
  const VertexIndexMap& vertex_index_map, 
  const EdgeIndexMap& /*edge_index_map*/, 
  typename graph_traits<Graph>::vertex_descriptor s, 
  typename graph_traits<Graph>::vertex_descriptor t, 
  // each inner vector corresponds to a pareto-optimal path
  std::vector
    <std::vector
      <typename graph_traits
        <Graph>::edge_descriptor> >& pareto_optimal_solutions, 
  std::vector
    <Resource_Container>& pareto_optimal_resource_containers, 
  bool b_all_pareto_optimal_solutions, 
  // to initialize the first label/resource container 
  // and to carry the type information
  const Resource_Container& rc, 
  Resource_Extension_Function& ref, 
  Dominance_Function& dominance, 
  // to specify the memory management strategy for the labels
  Label_Allocator /*la*/, 
  Visitor vis )
{
  pareto_optimal_resource_containers.clear();
  pareto_optimal_solutions.clear();

  unsigned long i_label_num = 0;
  typedef 
    typename 
      Label_Allocator::template rebind
        <r_c_shortest_paths_label
          <Graph, Resource_Container> >::other LAlloc;
  LAlloc l_alloc;
  typedef 
    ks_smart_pointer
      <r_c_shortest_paths_label<Graph, Resource_Container> > Splabel;
  std::priority_queue<Splabel, std::vector<Splabel>, std::greater<Splabel> > 
    unprocessed_labels;

  bool b_feasible = true;
  r_c_shortest_paths_label<Graph, Resource_Container>* first_label = 
    l_alloc.allocate( 1 );
  l_alloc.construct
    ( first_label, 
      r_c_shortest_paths_label
        <Graph, Resource_Container>( i_label_num++, 
                                     rc, 
                                     0, 
                                     typename graph_traits<Graph>::
                                       edge_descriptor(), 
                                     s ) );

  Splabel splabel_first_label = Splabel( first_label );
  unprocessed_labels.push( splabel_first_label );
  std::vector<std::list<Splabel> > vec_vertex_labels( num_vertices( g ) );
  vec_vertex_labels[vertex_index_map[s]].push_back( splabel_first_label );
  std::vector<typename std::list<Splabel>::iterator> 
    vec_last_valid_positions_for_dominance( num_vertices( g ) );
  for( int i = 0; i < static_cast<int>( num_vertices( g ) ); ++i )
    vec_last_valid_positions_for_dominance[i] = vec_vertex_labels[i].begin();
  std::vector<int> vec_last_valid_index_for_dominance( num_vertices( g ), 0 );
  std::vector<bool> 
    b_vec_vertex_already_checked_for_dominance( num_vertices( g ), false );
  while( !unprocessed_labels.empty()  && vis.on_enter_loop(unprocessed_labels, g) )
  {
    Splabel cur_label = unprocessed_labels.top();
    unprocessed_labels.pop();
    vis.on_label_popped( *cur_label, g );
    // an Splabel object in unprocessed_labels and the respective Splabel 
    // object in the respective list<Splabel> of vec_vertex_labels share their 
    // embedded r_c_shortest_paths_label object
    // to avoid memory leaks, dominated 
    // r_c_shortest_paths_label objects are marked and deleted when popped 
    // from unprocessed_labels, as they can no longer be deleted at the end of 
    // the function; only the Splabel object in unprocessed_labels still 
    // references the r_c_shortest_paths_label object
    // this is also for efficiency, because the else branch is executed only 
    // if there is a chance that extending the 
    // label leads to new undominated labels, which in turn is possible only 
    // if the label to be extended is undominated
    if( !cur_label->b_is_dominated )
    {
      int i_cur_resident_vertex_num = cur_label->resident_vertex;
      std::list<Splabel>& list_labels_cur_vertex = 
        vec_vertex_labels[i_cur_resident_vertex_num];
      if( static_cast<int>( list_labels_cur_vertex.size() ) >= 2 
          && vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] 
               < static_cast<int>( list_labels_cur_vertex.size() ) )
      {
        typename std::list<Splabel>::iterator outer_iter = 
          list_labels_cur_vertex.begin();
        bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = false;
        while( outer_iter != list_labels_cur_vertex.end() )
        {
          Splabel cur_outer_splabel = *outer_iter;
          typename std::list<Splabel>::iterator inner_iter = outer_iter;
          if( !b_outer_iter_at_or_beyond_last_valid_pos_for_dominance 
              && outer_iter == 
                   vec_last_valid_positions_for_dominance
                     [i_cur_resident_vertex_num] )
            b_outer_iter_at_or_beyond_last_valid_pos_for_dominance = true;
          if( !b_vec_vertex_already_checked_for_dominance
                [i_cur_resident_vertex_num] 
              || b_outer_iter_at_or_beyond_last_valid_pos_for_dominance )
          {
            ++inner_iter;
          }
          else
          {
            inner_iter = 
              vec_last_valid_positions_for_dominance
                [i_cur_resident_vertex_num];
            ++inner_iter;
          }
          bool b_outer_iter_erased = false;
          while( inner_iter != list_labels_cur_vertex.end() )
          {
            Splabel cur_inner_splabel = *inner_iter;
            if( dominance( cur_outer_splabel->
                             cumulated_resource_consumption, 
                           cur_inner_splabel->
                             cumulated_resource_consumption ) )
            {
              typename std::list<Splabel>::iterator buf = inner_iter;
              ++inner_iter;
              list_labels_cur_vertex.erase( buf );
              if( cur_inner_splabel->b_is_processed )
              {
                l_alloc.destroy( cur_inner_splabel.get() );
                l_alloc.deallocate( cur_inner_splabel.get(), 1 );
              }
              else
                cur_inner_splabel->b_is_dominated = true;
              continue;
            }
            else
              ++inner_iter;
            if( dominance( cur_inner_splabel->
                             cumulated_resource_consumption, 
                           cur_outer_splabel->
                             cumulated_resource_consumption ) )
            {
              typename std::list<Splabel>::iterator buf = outer_iter;
              ++outer_iter;
              list_labels_cur_vertex.erase( buf );
              b_outer_iter_erased = true;
              if( cur_outer_splabel->b_is_processed )
              {
                l_alloc.destroy( cur_outer_splabel.get() );
                l_alloc.deallocate( cur_outer_splabel.get(), 1 );
              }
              else
                cur_outer_splabel->b_is_dominated = true;
              break;
            }
          }
          if( !b_outer_iter_erased )
            ++outer_iter;
        }
        if( static_cast<int>( list_labels_cur_vertex.size() ) > 1 )
          vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = 
            (--(list_labels_cur_vertex.end()));
        else
          vec_last_valid_positions_for_dominance[i_cur_resident_vertex_num] = 
            list_labels_cur_vertex.begin();
        b_vec_vertex_already_checked_for_dominance
          [i_cur_resident_vertex_num] = true;
        vec_last_valid_index_for_dominance[i_cur_resident_vertex_num] = 
          static_cast<int>( list_labels_cur_vertex.size() ) - 1;
      }
    }
    if( !b_all_pareto_optimal_solutions && cur_label->resident_vertex == t )
    {
      // the devil don't sleep
      if( cur_label->b_is_dominated )
      {
        l_alloc.destroy( cur_label.get() );
        l_alloc.deallocate( cur_label.get(), 1 );
      }
      while( unprocessed_labels.size() )
      {
        Splabel l = unprocessed_labels.top();
        unprocessed_labels.pop();
        // delete only dominated labels, because nondominated labels are 
        // deleted at the end of the function
        if( l->b_is_dominated )
        {
          l_alloc.destroy( l.get() );
          l_alloc.deallocate( l.get(), 1 );
        }
      }
      break;
    }
    if( !cur_label->b_is_dominated )
    {
      cur_label->b_is_processed = true;
      vis.on_label_not_dominated( *cur_label, g );
      typename graph_traits<Graph>::vertex_descriptor cur_vertex = 
        cur_label->resident_vertex;
      typename graph_traits<Graph>::out_edge_iterator oei, oei_end;
      for( boost::tie( oei, oei_end ) = out_edges( cur_vertex, g ); 
           oei != oei_end; 
           ++oei )
      {
        b_feasible = true;
        r_c_shortest_paths_label<Graph, Resource_Container>* new_label = 
          l_alloc.allocate( 1 );
        l_alloc.construct( new_label, 
                           r_c_shortest_paths_label
                             <Graph, Resource_Container>
                               ( i_label_num++, 
                                 cur_label->cumulated_resource_consumption, 
                                 cur_label.get(), 
                                 *oei, 
                                 target( *oei, g ) ) );
        b_feasible = 
          ref( g, 
               new_label->cumulated_resource_consumption, 
               new_label->p_pred_label->cumulated_resource_consumption, 
               new_label->pred_edge );

        if( !b_feasible )
        {
          vis.on_label_not_feasible( *new_label, g );
          l_alloc.destroy( new_label );
          l_alloc.deallocate( new_label, 1 );
        }
        else
        {
          const r_c_shortest_paths_label<Graph, Resource_Container>& 
            ref_new_label = *new_label;
          vis.on_label_feasible( ref_new_label, g );
          Splabel new_sp_label( new_label );
          vec_vertex_labels[vertex_index_map[new_sp_label->resident_vertex]].
            push_back( new_sp_label );
          unprocessed_labels.push( new_sp_label );
        }
      }
    }
    else
    {
      vis.on_label_dominated( *cur_label, g );
      l_alloc.destroy( cur_label.get() );
      l_alloc.deallocate( cur_label.get(), 1 );
    }
  }
  std::list<Splabel> dsplabels = vec_vertex_labels[vertex_index_map[t]];
  typename std::list<Splabel>::const_iterator csi = dsplabels.begin();
  typename std::list<Splabel>::const_iterator csi_end = dsplabels.end();
  // if d could be reached from o
  if( !dsplabels.empty() )
  {
    for( ; csi != csi_end; ++csi )
    {
      std::vector<typename graph_traits<Graph>::edge_descriptor> 
        cur_pareto_optimal_path;
      const r_c_shortest_paths_label<Graph, Resource_Container>* p_cur_label = 
        (*csi).get();
      pareto_optimal_resource_containers.
        push_back( p_cur_label->cumulated_resource_consumption );
      while( p_cur_label->num != 0 )
      {
        cur_pareto_optimal_path.push_back( p_cur_label->pred_edge );
        p_cur_label = p_cur_label->p_pred_label;
      }
      pareto_optimal_solutions.push_back( cur_pareto_optimal_path );
      if( !b_all_pareto_optimal_solutions )
        break;
    }
  }

  int i_size = static_cast<int>( vec_vertex_labels.size() );
  for( int i = 0; i < i_size; ++i )
  {
    const std::list<Splabel>& list_labels_cur_vertex = vec_vertex_labels[i];
    csi_end = list_labels_cur_vertex.end();
    for( csi = list_labels_cur_vertex.begin(); csi != csi_end; ++csi )
    {
      l_alloc.destroy( (*csi).get() );
      l_alloc.deallocate( (*csi).get(), 1 );
    }
  }
} // r_c_shortest_paths_dispatch