Defend against Dijkstra returning reverse paths

This commit is contained in:
John Wiegley 2012-03-09 03:26:11 -06:00
parent ca8f702a1b
commit ef478079e7
2 changed files with 43 additions and 19 deletions

View file

@ -204,11 +204,13 @@ commodity_history_t::find_price(const commodity_t& source,
DEBUG("history.find", "sv commodity = " << get(namemap, sv)->symbol()); DEBUG("history.find", "sv commodity = " << get(namemap, sv)->symbol());
DEBUG("history.find", "tv commodity = " << get(namemap, tv)->symbol()); DEBUG("history.find", "tv commodity = " << get(namemap, tv)->symbol());
std::vector<vertex_descriptor> predecessors(num_vertices(fg)); std::size_t vector_len(num_vertices(fg));
std::vector<long> distances(num_vertices(fg)); std::vector<vertex_descriptor> predecessors(vector_len);
std::vector<long> distances(vector_len);
PredecessorMap predecessorMap(&predecessors[0]);
DistanceMap distanceMap(&distances[0]); FIndexMap indexMap(get(vertex_index, fg));
FPredecessorMap predecessorMap(&predecessors[0], indexMap);
FDistanceMap distanceMap(&distances[0], indexMap);
dijkstra_shortest_paths(fg, /* start= */ sv, dijkstra_shortest_paths(fg, /* start= */ sv,
predecessor_map(predecessorMap) predecessor_map(predecessorMap)
@ -217,10 +219,15 @@ commodity_history_t::find_price(const commodity_t& source,
// Extract the shortest path and performance the calculations // Extract the shortest path and performance the calculations
datetime_t least_recent = moment; datetime_t least_recent = moment;
amount_t price; amount_t price;
const commodity_t * last_target = &target; const commodity_t * last_target = &target;
typedef tuple<const commodity_t *, const commodity_t *,
const price_point_t *> results_tuple;
std::vector<results_tuple> results;
bool results_reversed = false;
vertex_descriptor v = tv; vertex_descriptor v = tv;
for (vertex_descriptor u = predecessorMap[v]; for (vertex_descriptor u = predecessorMap[v];
u != v; u != v;
@ -229,8 +236,24 @@ commodity_history_t::find_price(const commodity_t& source,
std::pair<Graph::edge_descriptor, bool> edgePair = edge(u, v, fg); std::pair<Graph::edge_descriptor, bool> edgePair = edge(u, v, fg);
Graph::edge_descriptor edge = edgePair.first; Graph::edge_descriptor edge = edgePair.first;
const commodity_t * u_comm = get(namemap, u);
const commodity_t * v_comm = get(namemap, v);
const price_point_t& point(get(pricemap, edge)); const price_point_t& point(get(pricemap, edge));
if (v == tv && u_comm != last_target && v_comm != last_target)
results_reversed = true;
results.push_back(results_tuple(u_comm, v_comm, &point));
}
if (results_reversed)
std::reverse(results.begin(), results.end());
foreach (const results_tuple& edge, results) {
const commodity_t * u_comm = edge.get<0>();
const commodity_t * v_comm = edge.get<1>();
const price_point_t& point(*edge.get<2>());
bool first_run = false; bool first_run = false;
if (price.is_null()) { if (price.is_null()) {
least_recent = point.when; least_recent = point.when;
@ -240,8 +263,8 @@ commodity_history_t::find_price(const commodity_t& source,
least_recent = point.when; least_recent = point.when;
} }
DEBUG("history.find", "u commodity = " << get(namemap, u)->symbol()); DEBUG("history.find", "u commodity = " << u_comm->symbol());
DEBUG("history.find", "v commodity = " << get(namemap, v)->symbol()); DEBUG("history.find", "v commodity = " << v_comm->symbol());
DEBUG("history.find", "last target = " << last_target->symbol()); DEBUG("history.find", "last target = " << last_target->symbol());
// Determine which direction we are converting in // Determine which direction we are converting in
@ -250,12 +273,12 @@ commodity_history_t::find_price(const commodity_t& source,
if (! first_run) { if (! first_run) {
DEBUG("history.find", "price was = " << price.unrounded()); DEBUG("history.find", "price was = " << price.unrounded());
if (pprice.commodity() != *last_target) if (pprice.commodity_ptr() != last_target)
price *= pprice.inverted(); price *= pprice.inverted();
else else
price *= pprice; price *= pprice;
} }
else if (pprice.commodity() != *last_target) { else if (pprice.commodity_ptr() != last_target) {
price = pprice.inverted(); price = pprice.inverted();
} }
else { else {
@ -263,10 +286,10 @@ commodity_history_t::find_price(const commodity_t& source,
} }
DEBUG("history.find", "price is = " << price.unrounded()); DEBUG("history.find", "price is = " << price.unrounded());
if (*last_target == *get(namemap, v)) if (last_target == v_comm)
last_target = get(namemap, u); last_target = u_comm;
else else
last_target = get(namemap, v); last_target = v_comm;
DEBUG("history.find", "last target now = " << last_target->symbol()); DEBUG("history.find", "last target now = " << last_target->symbol());
} }

View file

@ -156,13 +156,8 @@ public:
typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor; typedef graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef graph_traits<Graph>::edge_descriptor edge_descriptor; typedef graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef property_map<Graph, vertex_index_t>::type IndexMap;
typedef property_map<Graph, vertex_name_t>::type NameMap; typedef property_map<Graph, vertex_name_t>::type NameMap;
typedef property_map<Graph, vertex_index_t>::type IndexMap;
typedef iterator_property_map<vertex_descriptor*, IndexMap,
vertex_descriptor,
vertex_descriptor&> PredecessorMap;
typedef iterator_property_map<long*, IndexMap, long, long&> DistanceMap;
typedef property_map<Graph, edge_weight_t>::type EdgeWeightMap; typedef property_map<Graph, edge_weight_t>::type EdgeWeightMap;
typedef property_map<Graph, edge_price_point_t>::type PricePointMap; typedef property_map<Graph, edge_price_point_t>::type PricePointMap;
@ -175,7 +170,13 @@ public:
typedef filtered_graph<Graph, recent_edge_weight<EdgeWeightMap, typedef filtered_graph<Graph, recent_edge_weight<EdgeWeightMap,
PricePointMap, PricePointMap,
PriceRatioMap> > FGraph; PriceRatioMap> > FGraph;
typedef property_map<FGraph, vertex_name_t>::type FNameMap; typedef property_map<FGraph, vertex_name_t>::type FNameMap;
typedef property_map<FGraph, vertex_index_t>::type FIndexMap;
typedef iterator_property_map<vertex_descriptor*, FIndexMap,
vertex_descriptor,
vertex_descriptor&> FPredecessorMap;
typedef iterator_property_map<long*, FIndexMap, long, long&> FDistanceMap;
commodity_history_t() commodity_history_t()
: indexmap(get(vertex_index, price_graph)), : indexmap(get(vertex_index, price_graph)),