PBeFS
Parallel Best-First Search
Loading...
Searching...
No Matches
AStar.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------------*/
2/*------------------------------ File AStar.h ------------------------------*/
3/*--------------------------------------------------------------------------*/
53/*--------------------------------------------------------------------------*/
54/*------------------------------ DEFINITIONS -------------------------------*/
55/*--------------------------------------------------------------------------*/
56
57#ifndef __PBeFS_AStar
58 #define __PBeFS_AStar
59 /* self-identification: #endif at the end of the file */
60
61/*--------------------------------------------------------------------------*/
62/*-------------------------------- INCLUDES --------------------------------*/
63/*--------------------------------------------------------------------------*/
64
65#include "PBeFS/astar/Domain.h"
66
67#include "PBeFS/astar/Node.h"
68
70
72
74
76
77/*--------------------------------------------------------------------------*/
78/*------------------------------- NAMESPACE --------------------------------*/
79/*--------------------------------------------------------------------------*/
80
83{
84
85/*--------------------------------------------------------------------------*/
86/*------------------------------ CLASS AStar -------------------------------*/
87/*--------------------------------------------------------------------------*/
89
98
99template< Domain D ,
100 class Open = std::conditional_t<
101 std::is_integral_v< cost_t< D > > ,
104class AStar {
105
106/*------------------------ PUBLIC PART OF THE CLASS ------------------------*/
107
108 public:
109
110/*------------------------------ PUBLIC TYPES ------------------------------*/
111
116
117/*------------------------------ CONSTRUCTOR -------------------------------*/
118
120
121 explicit AStar( const D & domain , const SearchOptions & options = {} )
122 : f_domain( domain ) , f_options( options ) {}
123
124/*-------------------------------- SOLVING ---------------------------------*/
126
127 [[nodiscard]] SolutionT solve( void ) const
128 {
129 Stopwatch clock;
130 SolutionT sol;
131 SearchStats & st = sol.stats;
133 NodeTable< NodeT > table( f_options.expected_nodes
135 f_options.expected_nodes )
136 : 1024 );
137 Open open;
138 std::vector< Kid > kids; // the successors of a node
139
140 const State s0 = f_domain.initial_state();
141 NodeT * root = table.find_or_insert( s0 , f_domain.hash( s0 ) , [ & ] {
142 NodeT * n = pool.allocate();
143 *n = NodeT{ s0 , Cost( 0 ) , Cost( f_domain.heuristic( s0 ) ) , nullptr ,
144 false , false };
145 return( n );
146 } ).first;
147 open.push( root );
148
149 while( ! open.empty() ) {
150 const OpenEntry< NodeT > e = open.pop();
151 if( e.stale() )
152 continue;
153
154 NodeT * n = e.node;
155 n->closed = true;
156 ++st.expanded;
157 if( n->expanded )
158 ++st.reexpanded;
159 n->expanded = true;
160
161 if( f_domain.is_goal( n->state ) ) {
162 sol.status = Status::solved;
163 sol.cost = n->g;
164 sol.path = trace_path( n );
165 break;
166 }
167
168 // first the successors, with the slots of their lookups prefetched,
169 // then the lookups, whose cache misses thus overlap
170 kids.clear();
171 const auto kid = [ & ]( const State & t , Cost c , Cost ht ,
172 std::uint8_t op ) {
173 const std::uint64_t hash = f_domain.hash( t );
174 table.prefetch( hash );
175 kids.push_back( Kid{ t , c , ht , hash , op } );
176 };
177 for_each_child( f_domain , n->state , n->h , n->op , kid );
178 st.generated += kids.size();
179 for( const Kid & k : kids ) {
180 const Cost g = n->g + k.c;
181 auto [ m , fresh ] = table.find_or_insert( k.s , k.hash , [ & ] {
182 NodeT * x = pool.allocate();
183 *x = NodeT{ k.s , g , k.h , n , false , false , k.op };
184 return( x );
185 } );
186 if( fresh )
187 open.push( m );
188 else
189 if( g < m->g ) { // a cheaper path: reopen
190 m->g = g;
191 m->parent = n;
192 m->op = k.op;
193 m->closed = false;
194 open.push( m );
195 }
196 else
197 ++st.duplicates;
198 }
199
200 if( f_options.node_limit && ( pool.size() >= f_options.node_limit ) ) {
201 sol.status = Status::node_limit;
202 break;
203 }
204 }
205
206 st.stored = pool.size();
207 st.expanded_by = { st.expanded };
208 st.stored_by = { st.stored };
209 st.seconds = clock.seconds();
210 return( sol );
211 }
212
213/*----------------------- PRIVATE PART OF THE CLASS ------------------------*/
214
215 private:
216
218 struct Kid {
219 State s;
220 Cost c;
221 Cost h;
222 std::uint64_t hash;
223 std::uint8_t op;
224 };
225
226 const D & f_domain;
227 SearchOptions f_options;
228
229 }; // end( class( AStar ) )
230
231/*--------------------------------------------------------------------------*/
232/*------------------------------- FUNCTIONS --------------------------------*/
233/*--------------------------------------------------------------------------*/
235
238
239template< Domain D >
241 const D & domain , OpenKind open = OpenKind::automatic ,
242 const SearchOptions & options = {} )
243{
244 using NodeT = Node< state_t< D > , cost_t< D > >;
245 if constexpr( std::is_integral_v< cost_t< D > > )
246 if( open != OpenKind::heap )
247 return( AStar< D , BucketOpenList< NodeT > >( domain , options ).solve()
248 );
249 return( AStar< D , HeapOpenList< NodeT > >( domain , options ).solve() );
250 }
251
252/*--------------------------------------------------------------------------*/
253
254} // end( namespace PBeFS_di_unipi_it )
255
256/*--------------------------------------------------------------------------*/
257
258#endif /* __PBeFS_AStar */
259
260/*--------------------------------------------------------------------------*/
261/*---------------------------- End File AStar.h ----------------------------*/
262/*--------------------------------------------------------------------------*/
Header file for the concepts a search problem has to satisfy in order to be searched by the algorithm...
Header file for the class template NodeTable, the closed list of the searches: a map from the generat...
Header file for the class template Node, a node of the search graph, for the class template NodePool,...
Header file for the priority queues of the OPEN list, taken from the set of data structures chosen [s...
Header file for the small helpers shared by the searches: a stopwatch, the placement of the workers o...
Header file for the outcome of a search: the class template Solution, the statistics SearchStats coll...
state_t< D > State
the state type
Definition AStar.h:112
Solution< State, Cost > SolutionT
the solution type
Definition AStar.h:115
Node< State, Cost > NodeT
the node type
Definition AStar.h:114
cost_t< D > Cost
the cost type
Definition AStar.h:113
AStar(const D &domain, const SearchOptions &options={})
constructor, taking the Domain (which must outlive the AStar)
Definition AStar.h:121
SolutionT solve(void) const
searches the Domain, returning the Solution
Definition AStar.h:127
the OPEN list on the BucketQueue of ADS, for integer costs
Definition OpenList.h:122
the OPEN list on the DaryHeap of ADS
Definition OpenList.h:52
the arena of the nodes, on the Arena of ADS, on huge pages
Definition NodePool.h:48
the closed list, on the PointerTable of ADS, on huge pages
Definition NodeTable.h:49
static std::size_t slots_for(std::size_t n) noexcept
the number of slots that holds n nodes without growing
Definition NodeTable.h:55
a wall-clock stopwatch, started at construction
Definition SearchUtils.h:175
a search domain
Definition Domain.h:103
namespace for the Parallel Best-First Search library
Definition AStar.h:83
void for_each_child(const D &d, const state_t< D > &s, cost_t< D > h, std::uint8_t op, F &&f)
the successors of s but its parent, when D knows the operators
Definition Domain.h:276
typename D::cost_type cost_t
the cost type of a Domain
Definition Domain.h:245
@ open
left open by a limit
Definition BranchAndBound.h:167
@ solved
an optimal path has been found
Definition Solution.h:47
@ node_limit
the limit on the stored nodes was reached first
Definition Solution.h:49
OpenKind
the kind of OPEN list a search uses
Definition OpenList.h:63
@ automatic
buckets for integer costs, heap otherwise
Definition OpenList.h:64
typename D::state_type state_t
the state type of a Domain
Definition Domain.h:241
Solution< state_t< D >, cost_t< D > > astar(const D &domain, OpenKind open=OpenKind::automatic, const SearchOptions &options={})
searches a Domain with A*, choosing the OPEN list at run time
Definition AStar.h:240
auto trace_path(const NodeT *goal)
the states from the root to goal, following the parent pointers
Definition Node.h:126
a node of the search graph
Definition Node.h:74
bool closed
true if expanded with the current g
Definition Node.h:80
an entry of the OPEN list: the node and the g it had when pushed
Definition OpenList.h:73
NodeT * node
the node
Definition OpenList.h:75
bool stale(void) const noexcept
true if the node has been closed or improved since it was pushed
Definition OpenList.h:79
the options shared by all the searches
Definition Solution.h:119
the counters of a search
Definition Solution.h:64
a path from the initial state to a goal, and its cost
Definition Solution.h:100
SearchStats stats
the counters of the search
Definition Solution.h:105