Jeremy Siek wrote:

> ghost> vector< vertex > alternative_s ;
> ghost> iterator_property_map< vector<vertex>::iterator,
> ghost>       property_map<G, vertex_index_t> > alternative = ...
> ghost>
> ghost> The problem is that I have to pass alternative_s.begin() when
> ghost> constructig alternative, but I might want to add new vertices.
> ghost> In that case the iterator can be invalidated.
> ghost>
> ghost> Is there a solution to this problem, except for resorting to internal
> ghost> properties?


We currenly do not have a solution for this in the BGL (other than
internal properties). I seem to remember LEDA having a solution for this,
so you might want to look there for ideas.
Jeremy,
I've sketched some solution which works for me. It's merely a property map,
which uses vector for storage and will resize that vector as needed. I attach
the file. Can you take a look and say if you find the approach reasonable.
I might add it to the property map library in that case.

- Volodya
#line 396 "k_shortest.w"

// Copyright (C) 2003 Vladimir Prus

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/dag_shortest_paths.hpp>

#include "vector_property_map.hpp"

#include <iostream>

namespace boost {

    
#line 142 "k_shortest.w"
    
    template<class G>
    class Shortest_paths_finder {
    public:
        
#line 384 "k_shortest.w"
        
        typedef typename graph_traits<G>::vertex_descriptor vertex;
        typedef typename graph_traits<G>::edge_descriptor edge;
        typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
        typedef typename graph_traits<G>::in_edge_iterator in_edge_iterator;
        typedef typename graph_traits<G>::out_edge_iterator out_edge_iterator;
        
#line 146 "k_shortest.w"
    
    
        
#line 293 "k_shortest.w"
        
        template<class PredecessorMap>
        struct best_incoming_edge_recorder 
        : public base_visitor< best_incoming_edge_recorder<PredecessorMap> >
        {
            typedef on_edge_relaxed event_filter;
            best_incoming_edge_recorder(PredecessorMap pm)
            : pm(pm) 
            {}
            template<class Edge, class Graph>
            void operator()(Edge e, const Graph& g) const {
                put(pm, target(e, g), e);
            }
            PredecessorMap pm;
        };
        
#line 148 "k_shortest.w"
    
    
        Shortest_paths_finder(const G& g, vertex source, vertex sink)
        : g(g), m_source(source), m_sink(sink)
        {
          best_incoming_edge_recorder< vector_property_map<edge, index_map> > rec(best_incoming);
          dag_shortest_paths(this->g, source, 
              predecessor_map(predecessor).distance_map(distance)
              .visitor(make_dijkstra_visitor(rec))
              );
    
            vertex_iterator vi, ve;
            for (tie(vi, ve) = vertices(g); vi != ve; ++vi) {
              alternative[*vi] = *vi;
              root[*vi] = *vi;
            }
    
        }
    
        
#line 253 "k_shortest.w"
        
        bool find_alternative()
        {
            bool result = find_alternative(m_sink);
            m_sink = alternative[m_sink];
            cout << "new sink = " << m_sink << "\n";
            return result;
        }
        
        bool find_alternative(vertex v)
        {
            // Make sure alternative to 'vertex' is not computed yet.
            assert(alternative[v] == v);
        
            if (in_degree(root[v], g) == 0)
                return false;
        
            vertex pred = best_predecessor(v);
        
            // If the alternative is not computed, try to compute it now
            // The condition also handles the case where alternative does not
            // exists, in which case we better avoid recursive call... but anyway.
            cout << "at " << v << " pred = " << pred << "\n";
        
            // If there's alternative to the best predecessor, or we can compute it
            if (alternative[pred] != pred || find_alternative(pred)) {
                cout << "chaning best predecessor to " << alternative[pred] << "\n";
                change_best_predecessor(add_alternative(v), alternative[pred]);
            } else if (in_degree(root[v], g) > 1) {
                cout << "removing best predecessor\n";
                remove_best_predecessor(add_alternative(v));
            } else {
                return false;
            }
            return true;
        }
        
        
#line 167 "k_shortest.w"
    
    
        
#line 330 "k_shortest.w"
        
        template<class OutputIterator>
        void shortest_path(OutputIterator result) const
        {
          vector<vertex> path;
        
          for(vertex v = m_sink;; v = predecessor[v]) {
            path.push_back(root[v]);
            if (predecessor[v] == v)
                break;
          }
          copy(path.rbegin(), path.rend(), result);
        
        }
        
#line 169 "k_shortest.w"
    
       
    private:
       G g;
       vertex m_source;
       vertex m_sink; 
    
       
#line 188 "k_shortest.w"
       
       typedef property_map<G, vertex_index_t>::type index_map;
       
       vector_property_map<vertex, index_map> predecessor;
       vector_property_map<edge, index_map> best_incoming;
       vector_property_map<int, index_map> distance;
       
       vector_property_map<vertex, index_map> alternative, root;
       
       // Creates an alternative to v. Updates 'alternative' and 'root'
       // maps, but does nothing about predecessor and distance.
       vertex add_alternative(vertex v);
       
       vertex best_predecessor(vertex v) 
       {
       assert(predecessor[v] == source(best_incoming[v], g));
           return predecessor[v];
       }
       
       void change_best_predecessor(vertex v, vertex n)
       {
           int weight = get(edge_weight, g, best_incoming[v]);
           remove_edge(best_incoming[v], g);   
           edge e = add_edge(n, root[v], g).first;
       
           put(edge_weight, g, e, weight);
       
           adjust(v);
       }
       
       void remove_best_predecessor(vertex v)
       {
           remove_edge(best_predecessor(v), root[v], g);
           adjust(v);
       }
       
       void adjust(vertex v)
       {
           vertex r = root[v];
       
           typename graph_traits<G>::in_edge_iterator ii, ie;
           tie(ii, ie) = in_edges(r, g);
           if (ii == ie)
               return;
           distance[v] = distance[source(*ii, g)] + get(edge_weight, g, *ii);
           predecessor[v] = source(*ii, g);
           best_incoming[v] = *ii;
       
           while(++ii != ie) {
               int nd = distance[source(*ii, g)] + get(edge_weight, g, *ii);
               if (nd < distance[v]) {
                   distance[v] = nd;
                   predecessor[v] = source(*ii, g);
                   best_incoming[v] = *ii;
               }
           }
           cout << "best predecessor of " << v << "(root " << root[v] << ") is " 
                << predecessor[v] << "\n";
       }
       
       
#line 176 "k_shortest.w"
    
    
    };
    
#line 409 "k_shortest.w"


    
#line 311 "k_shortest.w"
    
    template<class G>
    Shortest_paths_finder<G>::vertex
    Shortest_paths_finder<G>::add_alternative(vertex v)
    {
        // Create the alternative vertex
        typename graph_traits<G>::vertex_descriptor alt = add_vertex(g);
        alternative[alt] = alt;
        alternative[v] = alt;
        root[alt] = root[v];
        // We duplicate all prec-related data now
        predecessor[alt] = predecessor[v];
        best_incoming[alt] = best_incoming[v];
        distance[alt] = distance[v];
        return alt;
    }
    
#line 411 "k_shortest.w"


    
#line 348 "k_shortest.w"
    
    template<class G>
    void k_shortest(const G& g, int k)
    {
        
#line 384 "k_shortest.w"
        
        typedef typename graph_traits<G>::vertex_descriptor vertex;
        typedef typename graph_traits<G>::edge_descriptor edge;
        typedef typename graph_traits<G>::vertex_iterator vertex_iterator;
        typedef typename graph_traits<G>::in_edge_iterator in_edge_iterator;
        typedef typename graph_traits<G>::out_edge_iterator out_edge_iterator;
        
#line 352 "k_shortest.w"
    
        
#line 377 "k_shortest.w"
        
        function_requires< BidirectionalGraphConcept<G> >() ;
        function_requires< ReadablePropertyGraphConcept<G, edge, edge_weight_t> >();
        
#line 353 "k_shortest.w"
    
       
        if (num_vertices(g) == 0)
            return;
    
        Shortest_paths_finder<G> f(g, *vertices(g).first, *prior(vertices(g).second));
    
        do {
          vector<vertex> p;
          f.shortest_path(back_inserter(p));
    cout << "---------__";
          for (size_t i = 0; i < p.size(); ++i)
            cout << p[i] << " ";
           cout << "\n";
          for (size_t i = 0; i < p.size(); ++i)
            cout << p[i]+1 << " ";
          cout << "\n";
        } while(f.find_alternative());        
    }
    
#line 413 "k_shortest.w"


}
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to