Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 1 | #include "y2018/control_loops/superstructure/arm/graph.h" |
| 2 | |
| 3 | #include <assert.h> |
| 4 | #include <algorithm> |
| 5 | |
| 6 | namespace y2018 { |
| 7 | namespace control_loops { |
| 8 | namespace superstructure { |
| 9 | namespace arm { |
| 10 | |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 11 | SearchGraph::SearchGraph(size_t num_vertexes, std::initializer_list<Edge> edges) |
Michael Schuh | 150f576 | 2018-05-30 09:06:25 -1000 | [diff] [blame] | 12 | : SearchGraph(num_vertexes, ::std::vector<Edge>(edges)) {} |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 13 | |
| 14 | SearchGraph::SearchGraph(size_t num_vertexes, std::vector<Edge> &&edges) |
| 15 | : edges_(::std::move(edges)) { |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 16 | vertexes_.resize(num_vertexes); |
| 17 | size_t i = 0; |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 18 | for (const auto &edge : edges_) { |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 19 | assert(edge.start < num_vertexes); |
| 20 | assert(edge.end < num_vertexes); |
| 21 | assert(edge.start != edge.end); |
| 22 | assert(edge.cost > 0); |
| 23 | vertexes_[edge.start].forward.emplace_back(HalfEdge{edge.end, i}); |
| 24 | vertexes_[edge.end].reverse.emplace_back(HalfEdge{edge.start, i}); |
| 25 | ++i; |
| 26 | } |
| 27 | for (auto &vertex : vertexes_) { |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 28 | ::std::sort(vertex.forward.begin(), vertex.forward.end()); |
| 29 | ::std::sort(vertex.reverse.begin(), vertex.reverse.end()); |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 30 | } |
| 31 | vertex_heap_.Reserve(num_vertexes); |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 32 | SetGoal(0); |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | SearchGraph::~SearchGraph() {} |
| 36 | |
| 37 | void SearchGraph::SetGoal(size_t vertex) { |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 38 | if (last_searched_vertex_ == vertex) { |
| 39 | return; |
| 40 | } |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 41 | assert(vertex < vertexes_.size()); |
| 42 | vertex_heap_.Clear(); |
| 43 | |
| 44 | for (auto &vertex : vertexes_) { |
| 45 | vertex.cached_distance = std::numeric_limits<double>::infinity(); |
| 46 | } |
| 47 | |
| 48 | vertexes_[vertex].cached_distance = 0.0; |
| 49 | vertex_heap_.InsertOrDecrease(&vertexes_[vertex]); |
| 50 | |
| 51 | while (!vertex_heap_.Empty()) { |
| 52 | Vertex *vertex = vertex_heap_.PopMin(); |
| 53 | for (const auto &half_edge : vertex->reverse) { |
| 54 | Vertex *to_adjust = &vertexes_[half_edge.dest]; |
| 55 | double adjust_cost = vertex->cached_distance + GetCost(half_edge); |
| 56 | if (adjust_cost < to_adjust->cached_distance) { |
| 57 | to_adjust->cached_distance = adjust_cost; |
| 58 | vertex_heap_.InsertOrDecrease(to_adjust); |
| 59 | } |
| 60 | } |
| 61 | } |
Austin Schuh | cb09171 | 2018-02-21 20:01:55 -0800 | [diff] [blame] | 62 | last_searched_vertex_ = vertex; |
Parker Schuh | be36c5b | 2018-02-19 01:06:50 -0800 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | double SearchGraph::GetCostToGoal(size_t vertex) { |
| 66 | assert(vertex < vertexes_.size()); |
| 67 | return vertexes_[vertex].cached_distance; |
| 68 | } |
| 69 | |
| 70 | } // namespace arm |
| 71 | } // namespace superstructure |
| 72 | } // namespace control_loops |
| 73 | } // namespace y2018 |