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 > 105900
58 #include <boost/type_traits/ice.hpp>
61 #include <boost/graph/adjacency_matrix.hpp>
62 #include <boost/graph/adjacency_list.hpp>
67 template <
typename Graph,
72 LPAstarOnGraph(std::size_t source, std::size_t target, Graph &graph, Heuristic &h)
73 : costEstimator_(h), graph_(graph)
76 double c = std::numeric_limits<double>::infinity();
77 source_ =
new Node(c, costEstimator_(source), 0, source);
79 target_ =
new Node(c, 0, c, target);
88 void insertEdge(std::size_t u, std::size_t v,
double c)
90 Node* n_u = getNode(u);
91 Node* n_v = getNode(v);
93 if (n_v->rhs() > n_u->costToCome() + c)
96 n_v->setRhs(n_u->costToCome() + c);
102 void removeEdge(std::size_t u, std::size_t v)
104 assert(v != source_->getId());
106 Node* n_u = getNode(u);
107 Node* n_v = getNode(v);
109 if (n_v->getParent() == n_u)
111 WeightMap weights = boost::get(boost::edge_weight_t(), graph_);
112 chooseBestIncomingNode(n_v, weights);
118 double computeShortestPath(std::list<std::size_t>& path)
120 WeightMap weights = boost::get(boost::edge_weight_t(), graph_);
123 return std::numeric_limits<double>::infinity();
125 while (topHead()->key() < target_->calculateKey() ||
126 target_->rhs() != target_->costToCome())
131 if (u->costToCome() > u->rhs())
133 u->setCostToCome(u->rhs());
137 typename boost::graph_traits<Graph>::out_edge_iterator ei, ei_end;
138 for (boost::tie(ei, ei_end) = boost::out_edges(u->getId(), graph_); ei != ei_end; ++ei)
140 std::size_t v = boost::target(*ei, graph_);
141 Node* n_v = getNode(v);
142 double c = boost::get(weights, *ei);
144 if (n_v->rhs() > u->costToCome() + c)
147 n_v->setRhs( u->costToCome() + c);
154 u->setCostToCome(std::numeric_limits<double>::infinity());
158 typename boost::graph_traits<Graph>::out_edge_iterator ei, ei_end;
159 for (boost::tie(ei, ei_end) = boost::out_edges(u->getId(), graph_); ei != ei_end; ++ei)
161 std::size_t v = boost::target(*ei, graph_);
162 Node* n_v = getNode(v);
164 if ( (n_v == source_) || (n_v->getParent() != u) )
167 chooseBestIncomingNode(n_v, weights);
177 Node* res = (target_->costToCome() == std::numeric_limits<double>::infinity() ?
nullptr : target_);
178 while (res !=
nullptr)
180 path.push_front(res->getId());
181 res = res->getParent();
184 return target_->costToCome();
190 IdNodeMapIter iter = idNodeMap_.find(u);
191 if (iter != idNodeMap_.end())
192 return iter->second->costToCome();
193 return std::numeric_limits<double>::infinity();
199 Key(
double first_ = -1,
double second_ = -1) : first(first_), second(second_)
202 bool operator<(
const Key& other)
204 return (first != other.first) ? (first < other.first) : (second < other.second);
206 double first, second;
212 Node (
double costToCome,
double costToGo,
double rhs,
213 std::size_t& dataId, Node* parentNode =
nullptr)
214 : g(costToCome), h(costToGo), r(rhs), isInQ(false), parent(parentNode), id(dataId)
219 double costToCome()
const
223 double costToGo()
const
237 k = Key(std::min(g, r + h), std::min(g, r));
241 double setCostToCome(
double val)
245 double setRhs(
double val)
250 bool isInQueue()
const
254 void inQueue(
bool in)
259 Node* getParent()
const
263 void setParent(Node *p)
268 std::size_t getId()
const
272 bool isConsistent()
const
289 bool operator()(
const Node *n1,
const Node *n2)
const
291 return n1->key() < n2->key();
297 std::size_t
operator()(
const std::size_t
id)
const
301 std::hash<std::size_t> h;
304 typedef std::multiset<Node*, LessThanNodeK> Queue;
305 typedef std::unordered_map<std::size_t, Node*, Hash> IdNodeMap;
306 typedef typename IdNodeMap::iterator IdNodeMapIter;
307 typedef typename boost::property_map<Graph, boost::edge_weight_t>::type WeightMap;
310 void updateVertex(Node *n)
312 if (!n->isConsistent())
319 else if (n->isInQueue())
328 queue_.erase(queue_.begin());
334 return *queue_.begin();
337 void insertQueue(Node* node)
339 assert(node->isInQueue() ==
false);
341 node->calculateKey();
347 void removeQueue(Node *node)
349 if (node->isInQueue())
351 node->inQueue(
false);
356 void updateQueue(Node *node)
363 void chooseBestIncomingNode(Node *n_v, WeightMap &weights)
366 double min = std::numeric_limits<double>::infinity();
367 Node* best =
nullptr;
369 typename boost::graph_traits<Graph>::in_edge_iterator ei, ei_end;
370 for (boost::tie(ei, ei_end) = boost::in_edges(n_v->getId(), graph_); ei != ei_end; ++ei)
372 std::size_t u = boost::source(*ei, graph_);
373 Node* n_u = getNode(u);
374 double c = boost::get(weights, *ei);
376 double curr = n_u->costToCome() + c;
385 n_v->setParent(best);
388 void addNewNode(Node *n)
390 idNodeMap_[n->getId()]=n;
393 Node* getNode(std::size_t
id)
395 IdNodeMapIter iter = idNodeMap_.find(
id);
396 if (iter != idNodeMap_.end())
399 double c = std::numeric_limits<double>::infinity();
400 Node *n =
new Node(c, costEstimator_(
id), c,
id);
408 for (IdNodeMapIter iter = idNodeMap_.begin(); iter != idNodeMap_.end(); ++iter)
410 Node* n= iter->second;
415 Heuristic &costEstimator_;
420 IdNodeMap idNodeMap_;
425 #endif //OMPL_DATASTRUCTURES_LPA_STAR_ON_G_H
double operator()(std::size_t u)
using LPA* to approximate costToCome