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