41 #ifndef OMPL_DATASTRUCTURES_LPA_STAR_ON_G_H
42 #define OMPL_DATASTRUCTURES_LPA_STAR_ON_G_H
49 #include <unordered_map>
56 #include <boost/version.hpp>
57 #if BOOST_VERSION == 106000
58 #include <boost/type_traits/ice.hpp>
61 #include <boost/functional/hash.hpp>
62 #include <boost/graph/adjacency_matrix.hpp>
63 #include <boost/graph/adjacency_list.hpp>
68 template <
typename Graph,
73 LPAstarOnGraph(std::size_t source, std::size_t target, Graph &graph, Heuristic &h)
74 : costEstimator_(h), graph_(graph)
77 double c = std::numeric_limits<double>::infinity();
78 source_ =
new Node(c, costEstimator_(source), 0, source);
80 target_ =
new Node(c, 0, c, target);
89 void insertEdge(std::size_t u, std::size_t v,
double c)
91 Node *n_u = getNode(u);
92 Node *n_v = getNode(v);
94 if (n_v->rhs() > n_u->costToCome() + c)
97 n_v->setRhs(n_u->costToCome() + c);
101 void removeEdge(std::size_t u, std::size_t v)
103 assert(v != source_->getId());
105 Node *n_u = getNode(u);
106 Node *n_v = getNode(v);
108 if (n_v->getParent() == n_u)
110 WeightMap weights = boost::get(boost::edge_weight_t(), graph_);
111 chooseBestIncomingNode(n_v, weights);
116 double computeShortestPath(std::list<std::size_t> &path)
118 WeightMap weights = boost::get(boost::edge_weight_t(), graph_);
121 return std::numeric_limits<double>::infinity();
123 while (topHead()->key() < target_->calculateKey() || target_->rhs() != target_->costToCome())
128 if (u->costToCome() > u->rhs())
130 u->setCostToCome(u->rhs());
134 typename boost::graph_traits<Graph>::out_edge_iterator ei, ei_end;
135 for (boost::tie(ei, ei_end) = boost::out_edges(u->getId(), graph_); ei != ei_end; ++ei)
137 std::size_t v = boost::target(*ei, graph_);
138 Node *n_v = getNode(v);
139 double c = boost::get(weights, *ei);
141 if (n_v->rhs() > u->costToCome() + c)
144 n_v->setRhs(u->costToCome() + c);
151 u->setCostToCome(std::numeric_limits<double>::infinity());
155 typename boost::graph_traits<Graph>::out_edge_iterator ei, ei_end;
156 for (boost::tie(ei, ei_end) = boost::out_edges(u->getId(), graph_); ei != ei_end; ++ei)
158 std::size_t v = boost::target(*ei, graph_);
159 Node *n_v = getNode(v);
161 if ((n_v == source_) || (n_v->getParent() != u))
164 chooseBestIncomingNode(n_v, weights);
174 Node *res = (target_->costToCome() == std::numeric_limits<double>::infinity() ? nullptr : target_);
175 while (res !=
nullptr)
177 path.push_front(res->getId());
178 res = res->getParent();
181 return target_->costToCome();
187 auto iter = idNodeMap_.find(u);
188 if (iter != idNodeMap_.end())
189 return iter->second->costToCome();
190 return std::numeric_limits<double>::infinity();
196 Key(
double first_ = -1,
double second_ = -1) : first(first_), second(second_)
199 bool operator<(
const Key &other)
201 return (first != other.first) ? (first < other.first) : (second < other.second);
203 double first, second;
209 Node(
double costToCome,
double costToGo,
double rhs, std::size_t &dataId, Node *parentNode =
nullptr)
210 : g(costToCome), h(costToGo), r(rhs), isInQ(false), parent(parentNode), id(dataId)
215 double costToCome()
const
219 double costToGo()
const
233 k = Key(std::min(g, r + h), std::min(g, r));
237 double setCostToCome(
double val)
241 double setRhs(
double val)
246 bool isInQueue()
const
250 void inQueue(
bool in)
255 Node *getParent()
const
259 void setParent(Node *p)
264 std::size_t getId()
const
268 bool isConsistent()
const
285 bool operator()(
const Node *n1,
const Node *n2)
const
287 return n1->key() < n2->key();
293 std::size_t
operator()(
const std::size_t
id)
const
297 std::hash<std::size_t> h;
300 using Queue = std::multiset<Node *, LessThanNodeK>;
301 using IdNodeMap = std::unordered_map<std::size_t, Node *, Hash>;
302 using IdNodeMapIter =
typename IdNodeMap::iterator;
303 using WeightMap =
typename boost::property_map<Graph, boost::edge_weight_t>::type;
306 void updateVertex(Node *n)
308 if (!n->isConsistent())
315 else if (n->isInQueue())
323 queue_.erase(queue_.begin());
329 return *queue_.begin();
332 void insertQueue(Node *node)
334 assert(node->isInQueue() ==
false);
336 node->calculateKey();
340 void removeQueue(Node *node)
342 if (node->isInQueue())
344 node->inQueue(
false);
348 void updateQueue(Node *node)
354 void chooseBestIncomingNode(Node *n_v, WeightMap &weights)
357 double min = std::numeric_limits<double>::infinity();
358 Node *best =
nullptr;
360 typename boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
361 for (boost::tie(ei, ei_end) = boost::in_edges(n_v->getId(), graph_); ei != ei_end; ++ei)
363 std::size_t u = boost::source(*ei, graph_);
364 Node *n_u = getNode(u);
365 double c = boost::get(weights, *ei);
367 double curr = n_u->costToCome() + c;
376 n_v->setParent(best);
379 void addNewNode(Node *n)
381 idNodeMap_[n->getId()] = n;
384 Node *getNode(std::size_t
id)
386 auto iter = idNodeMap_.find(
id);
387 if (iter != idNodeMap_.end())
390 double c = std::numeric_limits<double>::infinity();
391 auto *n =
new Node(c, costEstimator_(
id), c,
id);
399 for (
auto &
id : idNodeMap_)
403 Heuristic &costEstimator_;
408 IdNodeMap idNodeMap_;
413 #endif // OMPL_DATASTRUCTURES_LPA_STAR_ON_G_H