void OLCTriangle::AddFinishEdges(const ScanTaskPoint origin) { assert(IsFinal(origin.GetStageNumber() + 1)); if (predict) { // dummy just to close the triangle Link(ScanTaskPoint(origin.GetStageNumber() + 1, n_points - 1), origin, 0); } else { const ScanTaskPoint start = FindStart(origin); const TracePoint &start_point = GetPoint(start); const TracePoint &origin_point = GetPoint(origin); const unsigned max_range = trace_master.ProjectRange(origin_point.GetLocation(), max_distance); /* check all remaining points, see which ones match the conditions */ const ScanTaskPoint begin(origin.GetStageNumber() + 1, 0); const ScanTaskPoint end(origin.GetStageNumber() + 1, origin.GetPointIndex()); for (ScanTaskPoint i = begin; i != end; i.IncrementPointIndex()) if (CalcEdgeDistance(start, i) <= max_range && start_point.GetLocation().Distance(GetPoint(i).GetLocation()) < max_distance) Link(i, origin, CalcEdgeDistance(origin, i)); } }
bool OLCDijkstra::solve() { if (m_dijkstra.empty()) { set_weightings(); n_points = olc.get_trace_points(m_full_trace).size(); } if (n_points < num_stages) return false; if (m_dijkstra.empty()) { m_dijkstra.reset(ScanTaskPoint(0, 0)); add_start_edges(); if (m_dijkstra.empty()) // no processing to perform! // @todo // problem with this is it will immediately ask // OnlineContest for new data, which will be expensive // instead, new data should arrive only when preconditions // are satisfied (significant difference and valid) return true; } return solve_inner(); }
void OLCTriangle::AddEdges(const ScanTaskPoint origin) { assert(origin.GetPointIndex() < n_points); switch (origin.GetStageNumber()) { case 0: // add points up to finish for (ScanTaskPoint destination(origin.GetStageNumber() + 1, 0), end(origin.GetStageNumber() + 1, origin.GetPointIndex()); destination != end; destination.IncrementPointIndex()) { const unsigned d = CalcEdgeDistance(origin, destination); if (!is_fai || 4 * d >= best_d) /* no reason to add candidate if worse than 25% rule for FAI tasks */ Link(destination, origin, GetStageWeight(origin.GetStageNumber()) * d); } break; case 1: { ScanTaskPoint previous = dijkstra.GetPredecessor(origin); // give first leg points to penultimate node TriangleSecondLeg sl(is_fai, GetPoint(previous), GetPoint(origin)); for (ScanTaskPoint destination(origin.GetStageNumber() + 1, origin.GetPointIndex() + 1), end(origin.GetStageNumber() + 1, n_points - 1); destination != end; destination.IncrementPointIndex()) { TriangleSecondLeg::Result result = sl.Calculate(GetPoint(destination), best_d); const unsigned d = result.leg_distance; if (d > 0) { best_d = result.total_distance; Link(destination, origin, GetStageWeight(origin.GetStageNumber()) * d); // we have an improved solution is_complete = true; // need to scan again whether path is closed is_closed = false; first_tp = origin.GetPointIndex(); } } } break; case 2: // dummy just to close the triangle Link(ScanTaskPoint(origin.GetStageNumber() + 1, n_points - 1), origin, 0); break; default: assert(false); } }
bool TaskDijkstraMax::DistanceMax() { if (!RefreshTask()) return false; dijkstra.Reserve(256); dijkstra.Clear(); LinkStart(ScanTaskPoint(0, 0)); return Run(); }
bool ContestDijkstra::Solve(bool exhaustive) { if (dijkstra.empty()) { set_weightings(); dijkstra.reserve(CONTEST_QUEUE_SIZE); } assert(num_stages <= MAX_STAGES); if (dijkstra.empty()) { update_trace(); if (n_points < num_stages) return true; // don't re-start search unless we have had new data appear if (!trace_dirty) { return true; } } else if (exhaustive) { update_trace(); if (n_points < num_stages) return true; } else if (n_points < num_stages) { update_trace(); return true; } if (trace_dirty) { trace_dirty = false; dijkstra.restart(ScanTaskPoint(0, 0)); start_search(); add_start_edges(); if (dijkstra.empty()) { return true; } } #ifdef INSTRUMENT_TASK count_olc_solve++; count_olc_size = max(count_olc_size, dijkstra.queue_size()); #endif if (distance_general(exhaustive ? 0 - 1 : 25)) { SaveSolution(); update_trace(); return true; } return !dijkstra.empty(); }
bool TaskDijkstraMin::DistanceMin(const SearchPoint ¤tLocation) { if (!RefreshTask()) return false; dijkstra.Reserve(256); dijkstra.Clear(); if (active_stage > 0) { AddStartEdges(currentLocation); } else { LinkStart(ScanTaskPoint(0, 0)); } return Run(); }
OLCDijkstra::OLCDijkstra(OnlineContest& _olc, const unsigned n_legs, const unsigned finish_alt_diff, const bool full_trace): NavDijkstra<TracePoint>(n_legs + 1), m_dijkstra(ScanTaskPoint(0, 0), false), olc(_olc), m_finish_alt_diff(finish_alt_diff), solution_found(false), best_distance(fixed_zero), best_speed(fixed_zero), best_time(fixed_zero), m_full_trace(full_trace) { m_weightings.reserve(n_legs); best_solution.reserve(num_stages); reset(); }
/** * Returns the solution point for the specified task point. Call * this after run() has returned true. */ const SearchPoint &GetSolution(unsigned stage) const { assert(stage < num_stages); return GetPoint(ScanTaskPoint(stage, solution[stage])); }