15 template <
class state>
24 template <
class state,
class action,
class environment,
bool DFS = true>
27 EBSearch(uint64_t minGrow, uint64_t maxGrow, uint64_t expEpsilon, uint64_t scale = 1)
29 void GetPath(environment *
env, state from, state to,
30 std::vector<action> &thePath);
32 std::vector<action> &thePath);
50 uint64_t
GCost(
const state &s1,
const state &s2)
52 uint64_t
GCost(
const state &s,
const action &a)
58 searchData &sd, uint64_t nodeLimit, action forbidden);
86 template <
class state,
class action,
class environment,
bool DFS>
88 std::vector<action> &thePath)
90 GetPath(env, env, from, to, thePath);
93 template <
class state,
class action,
class environment,
bool DFS>
95 std::vector<action> &thePath)
101 solutionPath.clear();
102 solutionCost = -1ull;
105 printf(
"EBIS: Baseline search: f: %llu\n", HCost(from));
106 searchData base = LowLevelSearch(HCost(from), -1);
107 while (solutionCost > base.
f)
109 printf(
"EBIS: First search: f: %1llu target: (%llu, %llu]\n",
112 if (solutionCost <= base.
nextF)
118 printf(
"EBIS: %llu under target %llu, initiate EXP search\n", curr.
nodes, uint64_t(c1*base.
nodes));
119 curr = ExponentialSearch(curr, base.
nodes);
124 printf(
"EBIS: %llu over target %llu, initiate BIN search\n", curr.
nodes, uint64_t(c2*base.
nodes));
125 curr = BinarySearch(curr, base.
nodes);
128 if (solutionCost <= curr.
f)
132 thePath = solutionPath;
133 printf(
"Found solution cost %llu\n", solutionCost);
136 template <
class state,
class action,
class environment,
bool DFS>
139 uint64_t lowNodes = c1*nodeLimit;
140 uint64_t highNodes = c2*nodeLimit;
141 uint64_t delta =
std::max(
d.nextF -
d.f, initialGap);
146 uint64_t bound =
d.f + delta*pow(2, i);
147 searchData curr = LowLevelSearch(bound, highNodes);
148 if (solutionCost <= bound && curr.
nodes < highNodes)
150 printf(
"***EBIS:->EXP: Solution proven below window; done\n");
151 curr.
f = solutionCost;
155 if (lowNodes <= curr.
nodes && curr.
nodes < highNodes)
157 printf(
"EBIS:->EXP: in node window [%llu <= %llu < %llu]\n", lowNodes, curr.
nodes, highNodes);
160 else if (curr.
nodes >= highNodes)
162 printf(
"EBIS:->EXP: over node window\n");
168 printf(
"EBIS:->EXP: below node window\n");
172 if (
d.f + delta*pow(2, i) < curr.
nextF)
173 printf(
"EBIS:->EXP: delta too small, increasing growth past nextf\n");
174 while (
d.f + delta*pow(2, i) < curr.
nextF)
181 template <
class state,
class action,
class environment,
bool DFS>
184 uint64_t lowNodes = c1*nodeLimit;
185 uint64_t highNodes = c2*nodeLimit;
186 uint64_t middlef = (
d.failedF +
d.f)/2.0;
188 if (middlef <=
d.nextF)
191 curr = LowLevelSearch(middlef, -1);
192 if (solutionCost <= middlef)
194 if (curr.
nodes >= lowNodes)
198 curr = LowLevelSearch(middlef, highNodes);
201 if (solutionCost <= middlef && curr.
nodes < highNodes)
203 printf(
"***EBIS:->BIN: Solution proven below window; done\n");
208 if (lowNodes <= curr.
nodes && curr.
nodes < highNodes)
210 printf(
"EBIS:->BIN: in node window [%llu <= %llu < %llu]\n", lowNodes, curr.
nodes, highNodes);
213 else if (curr.
nodes >= highNodes)
215 printf(
"EBIS:->BIN: over node window\n");
216 d.failedF =
std::min(middlef, solutionCost);
217 return BinarySearch(
d, nodeLimit);
220 printf(
"EBIS:->BIN: below node window\n");
222 return BinarySearch(curr, nodeLimit);
226 template <
class state,
class action,
class environment,
bool DFS>
229 state currState = start;
231 printf(
" --+DFBnB f: %llu; nodes: %llu; ", costLimit, nodeLimit);
233 printf(
" --+DFBnB f: %llu; nodes: ∞; ", costLimit);
240 sd = DFBNBHelper(currState, 0, costLimit, sd, nodeLimit, a);
241 totalNodesExpanded += sd.
nodes;
244 if (sd.
nextF == -1ull)
247 sd = DFBNBHelper(currState, 0, costLimit, sd, -1ull, a);
248 totalNodesExpanded += sd.
nodes;
250 printf(
"%llu (new) %llu (total), maxf: %llu, nextf: %llu\n", sd.
nodes, totalNodesExpanded, sd.
f, sd.
nextF);
254 template <
class state,
class action,
class environment,
bool DFS>
256 searchData &sd, uint64_t nodeLimit, action forbidden)
258 uint64_t currF = pathCost+HCost(currState);
269 if (sd.
nodes >= nodeLimit)
271 if (env->GoalTest(currState, goal))
273 if (
fless(currF, solutionCost))
275 solutionPath = currPath;
276 solutionCost = currF;
281 std::vector<action> &acts = *actCache.getItem();
282 env->GetActions(currState, acts);
284 totalNodesTouched+=acts.size();
286 for (
size_t x = 0; x < acts.size(); x++)
288 if (acts[x] == forbidden && currPath.size() > 0)
290 uint64_t edgeCost = GCost(currState, acts[x]);
291 env->ApplyAction(currState, acts[x]);
292 currPath.push_back(acts[x]);
293 action rev = acts[x];
294 env->InvertAction(rev);
295 sd = DFBNBHelper(currState, pathCost+edgeCost, costLimit, sd, nodeLimit, rev);
297 env->UndoAction(currState, acts[x]);
299 actCache.returnItem(&acts);
303 template <
class state,
class action,
class environment,
bool DFS>
307 printf(
"EBIS Validation:\n");
308 LowLevelSearch(solutionCost, -1);
311 template <
class state,
class action,
class environment,
bool DFS>
314 if (nodeLimit == -1ull && costLimit == -1ull)
315 printf(
" --+BFHS f: ∞; nodes: ∞; ");
316 else if (nodeLimit == -1)
317 printf(
" --+BFHS f: %llu; nodes: ∞; ", costLimit);
319 printf(
" --+BFHS f: %llu; nodes: %llu; ", costLimit, nodeLimit);
321 q.Reset(env->GetMaxHash());
323 q.AddOpenNode(start, env->GetStateHash(start), 0.0, 0.0, (uint64_t)0);
324 uint64_t nextCost = -1, maxFExpanded = 0;
325 uint64_t nodesExpanded = 0;
326 while (nodesExpanded < nodeLimit && q.OpenSize() > 0)
332 uint64_t nodeid = q.Close();
334 totalNodesExpanded++;
336 maxFExpanded =
std::max(maxFExpanded,
static_cast<uint64_t
>(q.Lookup(nodeid).g+HCost(q.Lookup(nodeid).data)));
338 if (env->GoalTest(q.Lookup(nodeid).data, goal))
340 solutionCost = q.Lookup(nodeid).g;
341 ExtractPathToStartFromID(nodeid, solutionStates);
343 reverse(solutionStates.begin(), solutionStates.end());
345 if(solutionStates.size() > 0) {
346 for (
size_t x = 0; x < solutionStates.size()-1; x++)
348 solutionPath.push_back(env->GetAction(solutionStates[x], solutionStates[x+1]));
351 return {
static_cast<uint64_t
>(q.Lookup(nodeid).g),
static_cast<uint64_t
>(q.Lookup(nodeid).g), -1ull, nodesExpanded};
356 neighborID.resize(0);
357 neighborLoc.resize(0);
362 env->GetSuccessors(q.Lookup(nodeid).data, neighbors);
365 for (
size_t x = 0; x < neighbors.size(); x++)
368 neighborLoc.push_back(q.Lookup(env->GetStateHash(neighbors[x]), theID));
369 neighborID.push_back(theID);
370 edgeCosts.push_back(GCost(q.Lookup(nodeid).data, neighbors[x]));
374 for (
size_t x = 0; x < neighbors.size(); x++)
378 switch (neighborLoc[x])
383 if (
fless(q.Lookup(nodeid).g+edgeCosts[x], q.Lookup(neighborID[x]).g))
385 q.Lookup(neighborID[x]).parentID = nodeid;
386 q.Lookup(neighborID[x]).g = q.Lookup(nodeid).g+edgeCosts[x];
387 q.KeyChanged(neighborID[x]);
392 uint64_t fcost = q.Lookup(nodeid).g+edgeCosts[x]+HCost(neighbors[x]);
394 if (fcost > costLimit)
396 nextCost =
std::min(nextCost, fcost);
399 q.AddOpenNode(neighbors[x],
400 env->GetStateHash(neighbors[x]),
401 q.Lookup(nodeid).g+edgeCosts[x],
411 if (nextCost == -1ull)
412 printf(
"%llu (new) %llu (total), maxf: %llu, nextf: ∞\n", nodesExpanded, totalNodesExpanded, maxFExpanded);
414 printf(
"%llu (new) %llu (total), maxf: %llu, nextf: %llu\n", nodesExpanded, totalNodesExpanded, maxFExpanded, nextCost);
417 if (nodesExpanded == nodeLimit)
419 return {maxFExpanded, nextCost, maxFExpanded, nodesExpanded};
424 return {maxFExpanded, nextCost, -1ull, nodesExpanded};
426 assert(!
"Shouldn't get here");
429 template <
class state,
class action,
class environment,
bool DFS>
431 std::vector<state> &thePath)
435 thePath.push_back(q.Lookup(
node).data);
437 }
while (q.Lookup(
node).parentID !=
node);
438 thePath.push_back(q.Lookup(
node).data);
442 template <
class state,
class action,
class environment,
bool DFS>
446 return DFBNB(costLimit, nodeLimit);
448 return BFHS(costLimit, nodeLimit);