$search
00001 /* 00002 * Copyright (c) 2008, Maxim Likhachev 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of the University of Pennsylvania nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 #include <iostream> 00030 using namespace std; 00031 00032 #include "../../sbpl/headers.h" 00033 00034 00035 00036 00037 //----------------------------------------------------------------------------------------------------- 00038 00039 ADPlanner::ADPlanner(DiscreteSpaceInformation* environment, bool bForwardSearch) 00040 { 00041 environment_ = environment; 00042 00043 bforwardsearch = bForwardSearch; 00044 00045 bsearchuntilfirstsolution = false; 00046 finitial_eps = AD_DEFAULT_INITIAL_EPS; 00047 searchexpands = 0; 00048 MaxMemoryCounter = 0; 00049 00050 #ifndef ROS 00051 const char* debug = "debug.txt"; 00052 #endif 00053 fDeb = SBPL_FOPEN(debug, "w"); 00054 if(fDeb == NULL){ 00055 SBPL_ERROR("ERROR: could not open planner debug file\n"); 00056 throw new SBPL_Exception(); 00057 } 00058 SBPL_PRINTF("debug on\n"); 00059 00060 pSearchStateSpace_ = new ADSearchStateSpace_t; 00061 00062 00063 //create the AD planner 00064 if(CreateSearchStateSpace(pSearchStateSpace_) != 1) 00065 { 00066 SBPL_ERROR("ERROR: failed to create statespace\n"); 00067 return; 00068 } 00069 00070 //set the start and goal states 00071 if(InitializeSearchStateSpace(pSearchStateSpace_) != 1) 00072 { 00073 SBPL_ERROR("ERROR: failed to create statespace\n"); 00074 return; 00075 } 00076 00077 finitial_eps_planning_time = -1.0; 00078 final_eps_planning_time = -1.0; 00079 num_of_expands_initial_solution = 0; 00080 final_eps = -1.0; 00081 } 00082 00083 ADPlanner::~ADPlanner() 00084 { 00085 00086 //delete the statespace 00087 DeleteSearchStateSpace(pSearchStateSpace_); 00088 delete pSearchStateSpace_; 00089 00090 SBPL_FCLOSE(fDeb); 00091 } 00092 00093 00094 void ADPlanner::Initialize_searchinfo(CMDPSTATE* state, ADSearchStateSpace_t* pSearchStateSpace) 00095 { 00096 00097 ADState* searchstateinfo = (ADState*)state->PlannerSpecificData; 00098 00099 searchstateinfo->MDPstate = state; 00100 InitializeSearchStateInfo(searchstateinfo, pSearchStateSpace); 00101 } 00102 00103 00104 CMDPSTATE* ADPlanner::CreateState(int stateID, ADSearchStateSpace_t* pSearchStateSpace) 00105 { 00106 CMDPSTATE* state = NULL; 00107 00108 #if DEBUG 00109 if(environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND] != -1) 00110 { 00111 SBPL_ERROR("ERROR in CreateState: state already created\n"); 00112 throw new SBPL_Exception(); 00113 } 00114 #endif 00115 00116 //adds to the tail a state 00117 state = pSearchStateSpace->searchMDP.AddState(stateID); 00118 00119 //remember the index of the state 00120 environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND] = pSearchStateSpace->searchMDP.StateArray.size()-1; 00121 00122 #if DEBUG 00123 if(state != pSearchStateSpace->searchMDP.StateArray[environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND]]) 00124 { 00125 SBPL_ERROR("ERROR in CreateState: invalid state index\n"); 00126 throw new SBPL_Exception(); 00127 } 00128 #endif 00129 00130 00131 //create search specific info 00132 state->PlannerSpecificData = (ADState*)malloc(sizeof(ADState)); 00133 Initialize_searchinfo(state, pSearchStateSpace); 00134 MaxMemoryCounter += sizeof(ADState); 00135 00136 return state; 00137 00138 } 00139 00140 00141 CMDPSTATE* ADPlanner::GetState(int stateID, ADSearchStateSpace_t* pSearchStateSpace) 00142 { 00143 00144 if(stateID >= (int)environment_->StateID2IndexMapping.size()) 00145 { 00146 SBPL_ERROR("ERROR int GetState: stateID is invalid\n"); 00147 throw new SBPL_Exception(); 00148 } 00149 00150 if(environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND] == -1) 00151 return CreateState(stateID, pSearchStateSpace); 00152 else 00153 return pSearchStateSpace->searchMDP.StateArray[environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND]]; 00154 00155 } 00156 00157 00158 00159 //----------------------------------------------------------------------------------------------------- 00160 00161 00162 CKey ADPlanner::ComputeKey(ADState* state) 00163 { 00164 CKey key; 00165 00166 if(state->v >= state->g) 00167 { 00168 key.key[0] = state->g + (int)(pSearchStateSpace_->eps*state->h); 00169 key.key[1] = 1; 00170 } 00171 else 00172 { 00173 key.key[0] = state->v + state->h; 00174 key.key[1] = 0; 00175 } 00176 00177 return key; 00178 } 00179 00180 00181 int ADPlanner::ComputeHeuristic(CMDPSTATE* MDPstate, ADSearchStateSpace_t* pSearchStateSpace) 00182 { 00183 //compute heuristic for search 00184 if(bforwardsearch) 00185 { 00186 00187 #if MEM_CHECK == 1 00188 //int WasEn = DisableMemCheck(); 00189 #endif 00190 00191 //forward search: heur = distance from state to searchgoal which is Goal ADState 00192 int retv = environment_->GetGoalHeuristic(MDPstate->StateID); 00193 00194 #if MEM_CHECK == 1 00195 //if (WasEn) 00196 // EnableMemCheck(); 00197 #endif 00198 00199 return retv; 00200 } 00201 else 00202 { 00203 //backward search: heur = distance from searchgoal to state 00204 return environment_->GetStartHeuristic(MDPstate->StateID); 00205 } 00206 00207 } 00208 00209 00210 //initialization of a state 00211 void ADPlanner::InitializeSearchStateInfo(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00212 { 00213 state->g = INFINITECOST; 00214 state->v = INFINITECOST; 00215 state->iterationclosed = 0; 00216 state->callnumberaccessed = pSearchStateSpace->callnumber; 00217 state->bestnextstate = NULL; 00218 state->costtobestnextstate = INFINITECOST; 00219 state->heapindex = 0; 00220 state->listelem[AD_INCONS_LIST_ID] = NULL; 00221 state->numofexpands = 0; 00222 state->bestpredstate = NULL; 00223 00224 //compute heuristics 00225 #if USE_HEUR 00226 if(pSearchStateSpace->searchgoalstate != NULL) 00227 state->h = ComputeHeuristic(state->MDPstate, pSearchStateSpace); 00228 else 00229 state->h = 0; 00230 #else 00231 state->h = 0; 00232 #endif 00233 00234 00235 } 00236 00237 00238 00239 //re-initialization of a state 00240 void ADPlanner::ReInitializeSearchStateInfo(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00241 { 00242 state->g = INFINITECOST; 00243 state->v = INFINITECOST; 00244 state->iterationclosed = 0; 00245 state->callnumberaccessed = pSearchStateSpace->callnumber; 00246 state->bestnextstate = NULL; 00247 state->costtobestnextstate = INFINITECOST; 00248 state->heapindex = 0; 00249 state->listelem[AD_INCONS_LIST_ID] = NULL; 00250 state->numofexpands = 0; 00251 state->bestpredstate = NULL; 00252 00253 //compute heuristics 00254 #if USE_HEUR 00255 00256 if(pSearchStateSpace->searchgoalstate != NULL) 00257 { 00258 state->h = ComputeHeuristic(state->MDPstate, pSearchStateSpace); 00259 } 00260 else 00261 state->h = 0; 00262 00263 #else 00264 00265 state->h = 0; 00266 00267 #endif 00268 00269 00270 } 00271 00272 00273 00274 void ADPlanner::DeleteSearchStateData(ADState* state) 00275 { 00276 //no memory was allocated 00277 MaxMemoryCounter = 0; 00278 return; 00279 } 00280 00281 00282 void ADPlanner::UpdateSetMembership(ADState* state) 00283 { 00284 CKey key; 00285 00286 if(state->v != state->g) 00287 { 00288 if(state->iterationclosed != pSearchStateSpace_->searchiteration) 00289 { 00290 key = ComputeKey(state); 00291 if(state->heapindex == 0) 00292 { 00293 //need to remove it because it can happen when updating edge costs and state is in incons 00294 if(state->listelem[AD_INCONS_LIST_ID] != NULL) 00295 pSearchStateSpace_->inconslist->remove(state, AD_INCONS_LIST_ID); 00296 00297 pSearchStateSpace_->heap->insertheap(state, key); 00298 00299 } 00300 else 00301 pSearchStateSpace_->heap->updateheap(state, key); 00302 } 00303 else if(state->listelem[AD_INCONS_LIST_ID] == NULL) 00304 { 00305 pSearchStateSpace_->inconslist->insert(state, AD_INCONS_LIST_ID); 00306 } 00307 } 00308 else 00309 { 00310 if(state->heapindex != 0) 00311 pSearchStateSpace_->heap->deleteheap(state); 00312 else if(state->listelem[AD_INCONS_LIST_ID] != NULL) 00313 pSearchStateSpace_->inconslist->remove(state, AD_INCONS_LIST_ID); 00314 } 00315 } 00316 00317 00318 void ADPlanner::Recomputegval(ADState* state) 00319 { 00320 vector<int> searchpredsIDV; //these are predecessors if search is done forward and successors otherwise 00321 vector<int> costV; 00322 CKey key; 00323 ADState *searchpredstate; 00324 00325 if(bforwardsearch) 00326 environment_->GetPreds(state->MDPstate->StateID, &searchpredsIDV, &costV); 00327 else 00328 environment_->GetSuccs(state->MDPstate->StateID, &searchpredsIDV, &costV); 00329 00330 //iterate through predecessors of s and pick the best 00331 state->g = INFINITECOST; 00332 for(int pind = 0; pind < (int)searchpredsIDV.size(); pind++) 00333 { 00334 if(environment_->StateID2IndexMapping[searchpredsIDV[pind]][ADMDP_STATEID2IND] == -1) 00335 continue; //skip the states that do not exist - they can not be used to improve g-value anyway 00336 00337 CMDPSTATE* predMDPState = GetState(searchpredsIDV[pind], pSearchStateSpace_); 00338 int cost = costV[pind]; 00339 searchpredstate = (ADState*)(predMDPState->PlannerSpecificData); 00340 00341 //see if it can be used to improve 00342 if(searchpredstate->callnumberaccessed == pSearchStateSpace_->callnumber && state->g > searchpredstate->v + cost) 00343 { 00344 if(bforwardsearch) 00345 { 00346 state->g = searchpredstate->v + cost; 00347 state->bestpredstate = predMDPState; 00348 } 00349 else 00350 { 00351 state->g = searchpredstate->v + cost; 00352 state->bestnextstate = predMDPState; 00353 state->costtobestnextstate = cost; 00354 } 00355 } 00356 } //over preds 00357 } 00358 00359 00360 00361 //used for backward search 00362 void ADPlanner::UpdatePredsofOverconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00363 { 00364 vector<int> PredIDV; 00365 vector<int> CostV; 00366 CKey key; 00367 ADState *predstate; 00368 00369 environment_->GetPreds(state->MDPstate->StateID, &PredIDV, &CostV); 00370 00371 //iterate through predecessors of s 00372 for(int pind = 0; pind < (int)PredIDV.size(); pind++) 00373 { 00374 CMDPSTATE* PredMDPState = GetState(PredIDV[pind], pSearchStateSpace); 00375 predstate = (ADState*)(PredMDPState->PlannerSpecificData); 00376 if(predstate->callnumberaccessed != pSearchStateSpace->callnumber) 00377 ReInitializeSearchStateInfo(predstate, pSearchStateSpace); 00378 00379 //see if we can improve the value of predstate 00380 if(predstate->g > state->v + CostV[pind]) 00381 { 00382 00383 #if DEBUG 00384 if(predstate->MDPstate->StateID == 679256) 00385 { 00386 SBPL_FPRINTF(fDeb, "updating pred %d of overcons exp\n", predstate->MDPstate->StateID); 00387 PrintSearchState(predstate, fDeb); 00388 SBPL_FPRINTF(fDeb, "\n"); 00389 } 00390 #endif 00391 00392 00393 predstate->g = state->v + CostV[pind]; 00394 predstate->bestnextstate = state->MDPstate; 00395 predstate->costtobestnextstate = CostV[pind]; 00396 00397 //update set membership 00398 UpdateSetMembership(predstate); 00399 00400 #if DEBUG 00401 if(predstate->MDPstate->StateID == 679256) 00402 { 00403 SBPL_FPRINTF(fDeb, "updated pred %d of overcons exp\n", predstate->MDPstate->StateID); 00404 PrintSearchState(predstate, fDeb); 00405 SBPL_FPRINTF(fDeb, "\n"); 00406 } 00407 #endif 00408 00409 } 00410 } //for predecessors 00411 00412 } 00413 00414 //used for forward search 00415 void ADPlanner::UpdateSuccsofOverconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00416 { 00417 vector<int> SuccIDV; 00418 vector<int> CostV; 00419 CKey key; 00420 ADState *succstate; 00421 00422 environment_->GetSuccs(state->MDPstate->StateID, &SuccIDV, &CostV); 00423 00424 //iterate through predecessors of s 00425 for(int sind = 0; sind < (int)SuccIDV.size(); sind++) 00426 { 00427 CMDPSTATE* SuccMDPState = GetState(SuccIDV[sind], pSearchStateSpace); 00428 int cost = CostV[sind]; 00429 00430 succstate = (ADState*)(SuccMDPState->PlannerSpecificData); 00431 if(succstate->callnumberaccessed != pSearchStateSpace->callnumber) 00432 ReInitializeSearchStateInfo(succstate, pSearchStateSpace); 00433 00434 //see if we can improve the value of succstate 00435 //taking into account the cost of action 00436 if(succstate->g > state->v + cost) 00437 { 00438 succstate->g = state->v + cost; 00439 succstate->bestpredstate = state->MDPstate; 00440 00441 //update set membership 00442 UpdateSetMembership(succstate); 00443 00444 } //check for cost improvement 00445 00446 } //for actions 00447 } 00448 00449 00450 00451 //used for backward search 00452 void ADPlanner::UpdatePredsofUnderconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00453 { 00454 vector<int> PredIDV; 00455 vector<int> CostV; 00456 CKey key; 00457 ADState *predstate; 00458 00459 environment_->GetPreds(state->MDPstate->StateID, &PredIDV, &CostV); 00460 00461 //iterate through predecessors of s 00462 for(int pind = 0; pind < (int)PredIDV.size(); pind++) 00463 { 00464 00465 CMDPSTATE* PredMDPState = GetState(PredIDV[pind], pSearchStateSpace); 00466 predstate = (ADState*)(PredMDPState->PlannerSpecificData); 00467 if(predstate->callnumberaccessed != pSearchStateSpace->callnumber) 00468 ReInitializeSearchStateInfo(predstate, pSearchStateSpace); 00469 00470 if(predstate->bestnextstate == state->MDPstate) 00471 { 00472 Recomputegval(predstate); 00473 UpdateSetMembership(predstate); 00474 00475 #if DEBUG 00476 if(predstate->MDPstate->StateID == 679256) 00477 { 00478 SBPL_FPRINTF(fDeb, "updated pred %d of undercons exp\n", predstate->MDPstate->StateID); 00479 PrintSearchState(predstate, fDeb); 00480 SBPL_FPRINTF(fDeb, "\n"); 00481 } 00482 #endif 00483 00484 } 00485 } //for predecessors 00486 00487 } 00488 00489 00490 00491 //used for forward search 00492 void ADPlanner::UpdateSuccsofUnderconsState(ADState* state, ADSearchStateSpace_t* pSearchStateSpace) 00493 { 00494 vector<int> SuccIDV; 00495 vector<int> CostV; 00496 CKey key; 00497 ADState *succstate; 00498 00499 environment_->GetSuccs(state->MDPstate->StateID, &SuccIDV, &CostV); 00500 00501 //iterate through predecessors of s 00502 for(int sind = 0; sind < (int)SuccIDV.size(); sind++) 00503 { 00504 CMDPSTATE* SuccMDPState = GetState(SuccIDV[sind], pSearchStateSpace); 00505 succstate = (ADState*)(SuccMDPState->PlannerSpecificData); 00506 00507 if(succstate->callnumberaccessed != pSearchStateSpace->callnumber) 00508 ReInitializeSearchStateInfo(succstate, pSearchStateSpace); 00509 00510 if(succstate->bestpredstate == state->MDPstate) 00511 { 00512 Recomputegval(succstate); 00513 UpdateSetMembership(succstate); 00514 } 00515 00516 } //for actions 00517 } 00518 00519 00520 00521 int ADPlanner::GetGVal(int StateID, ADSearchStateSpace_t* pSearchStateSpace) 00522 { 00523 CMDPSTATE* cmdp_state = GetState(StateID, pSearchStateSpace); 00524 ADState* state = (ADState*)cmdp_state->PlannerSpecificData; 00525 return state->g; 00526 } 00527 00528 //returns 1 if the solution is found, 0 if the solution does not exist and 2 if it ran out of time 00529 int ADPlanner::ComputePath(ADSearchStateSpace_t* pSearchStateSpace, double MaxNumofSecs) 00530 { 00531 int expands; 00532 ADState *state, *searchgoalstate; 00533 CKey key, minkey; 00534 CKey goalkey; 00535 00536 expands = 0; 00537 00538 if(pSearchStateSpace->searchgoalstate == NULL) 00539 { 00540 SBPL_ERROR("ERROR searching: no goal state is set\n"); 00541 throw new SBPL_Exception(); 00542 } 00543 00544 //goal state 00545 searchgoalstate = (ADState*)(pSearchStateSpace->searchgoalstate->PlannerSpecificData); 00546 if(searchgoalstate->callnumberaccessed != pSearchStateSpace->callnumber) 00547 ReInitializeSearchStateInfo(searchgoalstate, pSearchStateSpace); 00548 00549 //set goal key 00550 goalkey = ComputeKey(searchgoalstate); 00551 00552 //expand states until done 00553 minkey = pSearchStateSpace->heap->getminkeyheap(); 00554 CKey oldkey = minkey; 00555 while(!pSearchStateSpace->heap->emptyheap() && minkey.key[0] < INFINITECOST && (goalkey > minkey || searchgoalstate->g > searchgoalstate->v) && 00556 (clock()-TimeStarted) < MaxNumofSecs*(double)CLOCKS_PER_SEC) 00557 { 00558 00559 //get the state 00560 state = (ADState*)pSearchStateSpace->heap->deleteminheap(); 00561 00562 00563 #if DEBUG 00564 CKey debkey = ComputeKey(state); 00565 //SBPL_FPRINTF(fDeb, "expanding state(%d): g=%u v=%u h=%d key=[%d %d] iterc=%d callnuma=%d expands=%d (g(goal)=%u)\n", 00566 // state->MDPstate->StateID, state->g, state->v, state->h, (int)debkey[0], (int)debkey[1], 00567 // state->iterationclosed, state->callnumberaccessed, state->numofexpands, searchgoalstate->g); 00568 if(state->MDPstate->StateID == 679256) 00569 { 00570 SBPL_FPRINTF(fDeb, "expanding state %d with key=[%d %d]:\n", state->MDPstate->StateID, (int)debkey[0], (int)debkey[1]); 00571 PrintSearchState(state, fDeb); 00572 environment_->PrintState(state->MDPstate->StateID, true, fDeb); 00573 } 00574 //SBPL_FFLUSH(fDeb); 00575 if(state->listelem[AD_INCONS_LIST_ID] != NULL) 00576 { 00577 SBPL_ERROR("ERROR: expanding state from INCONS list\n"); 00578 throw new SBPL_Exception(); 00579 } 00580 #endif 00581 00582 00583 #if DEBUG 00584 if(minkey.key[0] < oldkey.key[0] && fabs(this->finitial_eps - 1.0) < ERR_EPS) 00585 { 00586 SBPL_PRINTF("WARN in search: the sequence of keys decreases in an optimal search\n"); 00587 //throw new SBPL_Exception(); 00588 } 00589 oldkey = minkey; 00590 #endif 00591 00592 00593 if(state->v == state->g) 00594 { 00595 SBPL_ERROR("ERROR: consistent state is being expanded\n"); 00596 throw new SBPL_Exception(); 00597 } 00598 00599 //new expand 00600 expands++; 00601 state->numofexpands++; 00602 00603 if(state->v > state->g) 00604 { 00605 //overconsistent expansion 00606 00607 //recompute state value 00608 state->v = state->g; 00609 state->iterationclosed = pSearchStateSpace->searchiteration; 00610 00611 if(!bforwardsearch) 00612 { 00613 UpdatePredsofOverconsState(state, pSearchStateSpace); 00614 } 00615 else 00616 { 00617 UpdateSuccsofOverconsState(state, pSearchStateSpace); 00618 } 00619 } 00620 else 00621 { 00622 //underconsistent expansion 00623 00624 //force the state to be overconsistent 00625 state->v = INFINITECOST; 00626 00627 //update state membership 00628 UpdateSetMembership(state); 00629 00630 00631 if(!bforwardsearch) 00632 { 00633 UpdatePredsofUnderconsState(state, pSearchStateSpace); 00634 } 00635 else 00636 UpdateSuccsofUnderconsState(state, pSearchStateSpace); 00637 00638 } 00639 00640 00641 //recompute minkey 00642 minkey = pSearchStateSpace->heap->getminkeyheap(); 00643 00644 //recompute goalkey if necessary 00645 goalkey = ComputeKey(searchgoalstate); 00646 00647 if(expands%100000 == 0 && expands > 0) 00648 { 00649 SBPL_PRINTF("expands so far=%u\n", expands); 00650 } 00651 00652 } 00653 00654 int retv = 1; 00655 if(searchgoalstate->g == INFINITECOST && pSearchStateSpace->heap->emptyheap()) 00656 { 00657 SBPL_PRINTF("solution does not exist: search exited because heap is empty\n"); 00658 00659 #if DEBUG 00660 SBPL_FPRINTF(fDeb, "solution does not exist: search exited because heap is empty\n"); 00661 #endif 00662 00663 retv = 0; 00664 } 00665 else if(!pSearchStateSpace->heap->emptyheap() && (goalkey > minkey || searchgoalstate->g > searchgoalstate->v)) 00666 { 00667 SBPL_PRINTF("search exited because it ran out of time\n"); 00668 #if DEBUG 00669 SBPL_FPRINTF(fDeb, "search exited because it ran out of time\n"); 00670 #endif 00671 retv = 2; 00672 } 00673 else if(searchgoalstate->g == INFINITECOST && !pSearchStateSpace->heap->emptyheap()) 00674 { 00675 SBPL_PRINTF("solution does not exist: search exited because all candidates for expansion have infinite heuristics\n"); 00676 #if DEBUG 00677 SBPL_FPRINTF(fDeb, "solution does not exist: search exited because all candidates for expansion have infinite heuristics\n"); 00678 #endif 00679 retv = 0; 00680 } 00681 else 00682 { 00683 SBPL_PRINTF("search exited with a solution for eps=%.3f\n", pSearchStateSpace->eps); 00684 #if DEBUG 00685 SBPL_FPRINTF(fDeb, "search exited with a solution for eps=%.3f\n", pSearchStateSpace->eps); 00686 #endif 00687 retv = 1; 00688 } 00689 00690 //SBPL_FPRINTF(fDeb, "expanded=%d\n", expands); 00691 00692 searchexpands += expands; 00693 00694 return retv; 00695 } 00696 00697 00698 void ADPlanner::BuildNewOPENList(ADSearchStateSpace_t* pSearchStateSpace) 00699 { 00700 ADState *state; 00701 CKey key; 00702 CHeap* pheap = pSearchStateSpace->heap; 00703 CList* pinconslist = pSearchStateSpace->inconslist; 00704 00705 //move incons into open 00706 while(pinconslist->firstelement != NULL) 00707 { 00708 state = (ADState*)pinconslist->firstelement->liststate; 00709 00710 //compute f-value 00711 key = ComputeKey(state); 00712 00713 //insert into OPEN 00714 if(state->heapindex == 0) 00715 pheap->insertheap(state, key); 00716 else 00717 pheap->updateheap(state, key); //should never happen, but sometimes it does - somewhere there is a bug TODO 00718 //remove from INCONS 00719 pinconslist->remove(state, AD_INCONS_LIST_ID); 00720 } 00721 00722 pSearchStateSpace->bRebuildOpenList = false; 00723 00724 } 00725 00726 00727 void ADPlanner::Reevaluatefvals(ADSearchStateSpace_t* pSearchStateSpace) 00728 { 00729 CKey key; 00730 int i; 00731 CHeap* pheap = pSearchStateSpace->heap; 00732 00733 #if DEBUG 00734 SBPL_FPRINTF(fDeb, "re-computing heap priorities\n"); 00735 #endif 00736 00737 //recompute priorities for states in OPEN and reorder it 00738 for (i = 1; i <= pheap->currentsize; ++i) 00739 { 00740 ADState* state = (ADState*)pheap->heap[i].heapstate; 00741 pheap->heap[i].key = ComputeKey(state); 00742 } 00743 pheap->makeheap(); 00744 00745 pSearchStateSpace->bReevaluatefvals = false; 00746 } 00747 00748 00749 00750 00751 //creates (allocates memory) search state space 00752 //does not initialize search statespace 00753 int ADPlanner::CreateSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace) 00754 { 00755 00756 //create a heap 00757 pSearchStateSpace->heap = new CHeap; 00758 pSearchStateSpace->inconslist = new CList; 00759 MaxMemoryCounter += sizeof(CHeap); 00760 MaxMemoryCounter += sizeof(CList); 00761 00762 pSearchStateSpace->searchgoalstate = NULL; 00763 pSearchStateSpace->searchstartstate = NULL; 00764 00765 searchexpands = 0; 00766 00767 00768 pSearchStateSpace->bReinitializeSearchStateSpace = false; 00769 00770 return 1; 00771 } 00772 00773 //deallocates memory used by SearchStateSpace 00774 void ADPlanner::DeleteSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace) 00775 { 00776 if(pSearchStateSpace->heap != NULL) 00777 { 00778 pSearchStateSpace->heap->makeemptyheap(); 00779 delete pSearchStateSpace->heap; 00780 pSearchStateSpace->heap = NULL; 00781 } 00782 00783 if(pSearchStateSpace->inconslist != NULL) 00784 { 00785 pSearchStateSpace->inconslist->makeemptylist(AD_INCONS_LIST_ID); 00786 delete pSearchStateSpace->inconslist; 00787 pSearchStateSpace->inconslist = NULL; 00788 } 00789 00790 //delete the states themselves 00791 int iend = (int)pSearchStateSpace->searchMDP.StateArray.size(); 00792 for(int i=0; i < iend; i++) 00793 { 00794 CMDPSTATE* state = pSearchStateSpace->searchMDP.StateArray[i]; 00795 DeleteSearchStateData((ADState*)state->PlannerSpecificData); 00796 free(state->PlannerSpecificData); // allocated with malloc() on line 199 of revision 19485 00797 state->PlannerSpecificData = NULL; 00798 } 00799 pSearchStateSpace->searchMDP.Delete(); 00800 environment_->StateID2IndexMapping.clear(); 00801 } 00802 00803 00804 00805 //reset properly search state space 00806 //needs to be done before deleting states 00807 int ADPlanner::ResetSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace) 00808 { 00809 pSearchStateSpace->heap->makeemptyheap(); 00810 pSearchStateSpace->inconslist->makeemptylist(AD_INCONS_LIST_ID); 00811 00812 return 1; 00813 } 00814 00815 //initialization before each search 00816 void ADPlanner::ReInitializeSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace) 00817 { 00818 CKey key; 00819 00820 //increase callnumber 00821 pSearchStateSpace->callnumber++; 00822 00823 //reset iteration 00824 pSearchStateSpace->searchiteration = 0; 00825 00826 00827 #if DEBUG 00828 SBPL_FPRINTF(fDeb, "reinitializing search state-space (new call number=%d search iter=%d)\n", 00829 pSearchStateSpace->callnumber,pSearchStateSpace->searchiteration ); 00830 #endif 00831 00832 00833 00834 pSearchStateSpace->heap->makeemptyheap(); 00835 pSearchStateSpace->inconslist->makeemptylist(AD_INCONS_LIST_ID); 00836 00837 //reset 00838 pSearchStateSpace->eps = this->finitial_eps; 00839 pSearchStateSpace->eps_satisfied = INFINITECOST; 00840 00841 //initialize start state 00842 ADState* startstateinfo = (ADState*)(pSearchStateSpace->searchstartstate->PlannerSpecificData); 00843 if(startstateinfo->callnumberaccessed != pSearchStateSpace->callnumber) 00844 ReInitializeSearchStateInfo(startstateinfo, pSearchStateSpace); 00845 00846 startstateinfo->g = 0; 00847 00848 //insert start state into the heap 00849 key = ComputeKey(startstateinfo); 00850 pSearchStateSpace->heap->insertheap(startstateinfo, key); 00851 00852 pSearchStateSpace->bReinitializeSearchStateSpace = false; 00853 pSearchStateSpace->bReevaluatefvals = false; 00854 pSearchStateSpace->bRebuildOpenList = false; 00855 } 00856 00857 //very first initialization 00858 int ADPlanner::InitializeSearchStateSpace(ADSearchStateSpace_t* pSearchStateSpace) 00859 { 00860 00861 if(pSearchStateSpace->heap->currentsize != 0 || 00862 pSearchStateSpace->inconslist->currentsize != 0) 00863 { 00864 SBPL_ERROR("ERROR in InitializeSearchStateSpace: heap or list is not empty\n"); 00865 throw new SBPL_Exception(); 00866 } 00867 00868 pSearchStateSpace->eps = this->finitial_eps; 00869 pSearchStateSpace->eps_satisfied = INFINITECOST; 00870 pSearchStateSpace->searchiteration = 0; 00871 pSearchStateSpace->callnumber = 0; 00872 pSearchStateSpace->bReevaluatefvals = false; 00873 pSearchStateSpace->bRebuildOpenList = false; 00874 00875 00876 //create and set the search start state 00877 pSearchStateSpace->searchgoalstate = NULL; 00878 //pSearchStateSpace->searchstartstate = GetState(SearchStartStateID, pSearchStateSpace); 00879 pSearchStateSpace->searchstartstate = NULL; 00880 00881 00882 pSearchStateSpace->bReinitializeSearchStateSpace = true; 00883 00884 return 1; 00885 00886 } 00887 00888 00889 int ADPlanner::SetSearchGoalState(int SearchGoalStateID, ADSearchStateSpace_t* pSearchStateSpace) 00890 { 00891 00892 if(pSearchStateSpace->searchgoalstate == NULL || 00893 pSearchStateSpace->searchgoalstate->StateID != SearchGoalStateID) 00894 { 00895 pSearchStateSpace->searchgoalstate = GetState(SearchGoalStateID, pSearchStateSpace); 00896 00897 //current solution may be invalid 00898 pSearchStateSpace->eps_satisfied = INFINITECOST; 00899 pSearchStateSpace_->eps = this->finitial_eps; 00900 00901 //recompute heuristic for the heap if heuristics is used 00902 #if USE_HEUR 00903 int i; 00904 //TODO - should get rid of and instead use iteration to re-compute h-values online as needed 00905 for(i = 0; i < (int)pSearchStateSpace->searchMDP.StateArray.size(); i++) 00906 { 00907 CMDPSTATE* MDPstate = pSearchStateSpace->searchMDP.StateArray[i]; 00908 ADState* state = (ADState*)MDPstate->PlannerSpecificData; 00909 state->h = ComputeHeuristic(MDPstate, pSearchStateSpace); 00910 } 00911 #if DEBUG 00912 SBPL_PRINTF("re-evaluated heuristic values for %d states\n", i); 00913 #endif 00914 00915 pSearchStateSpace->bReevaluatefvals = true; 00916 #endif 00917 } 00918 00919 00920 return 1; 00921 00922 } 00923 00924 00925 int ADPlanner::SetSearchStartState(int SearchStartStateID, ADSearchStateSpace_t* pSearchStateSpace) 00926 { 00927 CMDPSTATE* MDPstate = GetState(SearchStartStateID, pSearchStateSpace); 00928 00929 if(MDPstate != pSearchStateSpace->searchstartstate) 00930 { 00931 pSearchStateSpace->searchstartstate = MDPstate; 00932 pSearchStateSpace->bReinitializeSearchStateSpace = true; 00933 pSearchStateSpace->bRebuildOpenList = true; 00934 } 00935 00936 return 1; 00937 00938 } 00939 00940 00941 00942 int ADPlanner::ReconstructPath(ADSearchStateSpace_t* pSearchStateSpace) 00943 { 00944 00945 //nothing to do, if search is backward 00946 if(bforwardsearch) 00947 { 00948 00949 CMDPSTATE* MDPstate = pSearchStateSpace->searchgoalstate; 00950 CMDPSTATE* PredMDPstate; 00951 ADState *predstateinfo, *stateinfo; 00952 00953 int steps = 0; 00954 const int max_steps = 100000; 00955 while(MDPstate != pSearchStateSpace->searchstartstate && steps < max_steps) 00956 { 00957 steps++; 00958 00959 stateinfo = (ADState*)MDPstate->PlannerSpecificData; 00960 00961 if(stateinfo->g == INFINITECOST) 00962 { 00963 //SBPL_ERROR("ERROR in ReconstructPath: g of the state on the path is INFINITE\n"); 00964 //throw new SBPL_Exception(); 00965 return -1; 00966 } 00967 00968 if(stateinfo->bestpredstate == NULL) 00969 { 00970 SBPL_ERROR("ERROR in ReconstructPath: bestpred is NULL\n"); 00971 throw new SBPL_Exception(); 00972 } 00973 00974 //get the parent state 00975 PredMDPstate = stateinfo->bestpredstate; 00976 predstateinfo = (ADState*)PredMDPstate->PlannerSpecificData; 00977 00978 //set its best next info 00979 predstateinfo->bestnextstate = MDPstate; 00980 00981 //check the decrease of g-values along the path 00982 if(predstateinfo->v >= stateinfo->g) 00983 { 00984 SBPL_ERROR("ERROR in ReconstructPath: g-values are non-decreasing\n"); 00985 throw new SBPL_Exception(); 00986 } 00987 00988 //transition back 00989 MDPstate = PredMDPstate; 00990 } 00991 00992 if(MDPstate != pSearchStateSpace->searchstartstate){ 00993 SBPL_ERROR("ERROR: Failed to reconstruct path (compute bestnextstate pointers): steps processed=%d\n", steps); 00994 return 0; 00995 } 00996 } 00997 00998 return 1; 00999 } 01000 01001 01002 void ADPlanner::PrintSearchState(ADState* searchstateinfo, FILE* fOut) 01003 { 01004 01005 CKey key = ComputeKey(searchstateinfo); 01006 SBPL_FPRINTF(fOut, "g=%d v=%d h = %d heapindex=%d inconslist=%d key=[%d %d] iterc=%d callnuma=%d expands=%d (current callnum=%d iter=%d)", 01007 searchstateinfo->g, searchstateinfo->v, searchstateinfo->h, searchstateinfo->heapindex, (searchstateinfo->listelem[AD_INCONS_LIST_ID] != NULL), 01008 (int)key[0], (int)key[1], searchstateinfo->iterationclosed, searchstateinfo->callnumberaccessed, searchstateinfo->numofexpands, 01009 this->pSearchStateSpace_->callnumber, this->pSearchStateSpace_->searchiteration); 01010 01011 } 01012 01013 void ADPlanner::PrintSearchPath(ADSearchStateSpace_t* pSearchStateSpace, FILE* fOut) 01014 { 01015 ADState* searchstateinfo; 01016 CMDPSTATE* state = pSearchStateSpace->searchgoalstate; 01017 CMDPSTATE* nextstate = NULL; 01018 01019 if(fOut == NULL) 01020 fOut = stdout; 01021 01022 int PathCost = ((ADState*)pSearchStateSpace->searchgoalstate->PlannerSpecificData)->g; 01023 01024 SBPL_FPRINTF(fOut, "Printing a path from state %d to the search start state %d\n", 01025 state->StateID, pSearchStateSpace->searchstartstate->StateID); 01026 SBPL_FPRINTF(fOut, "Path cost = %d:\n", PathCost); 01027 01028 environment_->PrintState(state->StateID, true, fOut); 01029 01030 int costFromStart = 0; 01031 int steps = 0; 01032 const int max_steps = 100000; 01033 while(state->StateID != pSearchStateSpace->searchstartstate->StateID && steps < max_steps) 01034 { 01035 steps++; 01036 01037 SBPL_FPRINTF(fOut, "state %d ", state->StateID); 01038 01039 if(state->PlannerSpecificData == NULL) 01040 { 01041 SBPL_FPRINTF(fOut, "path does not exist since search data does not exist\n"); 01042 break; 01043 } 01044 01045 searchstateinfo = (ADState*)state->PlannerSpecificData; 01046 01047 if(bforwardsearch) 01048 nextstate = searchstateinfo->bestpredstate; 01049 else 01050 nextstate = searchstateinfo->bestnextstate; 01051 01052 if(nextstate == NULL) 01053 { 01054 SBPL_FPRINTF(fOut, "path does not exist since nextstate == NULL\n"); 01055 break; 01056 } 01057 if(searchstateinfo->g == INFINITECOST) 01058 { 01059 SBPL_FPRINTF(fOut, "path does not exist since state->g == NULL\n"); 01060 break; 01061 } 01062 01063 int costToGoal = PathCost - costFromStart; 01064 if(!bforwardsearch) 01065 { 01066 //otherwise this cost is not even set 01067 costFromStart += searchstateinfo->costtobestnextstate; 01068 } 01069 01070 01071 #if DEBUG 01072 if(searchstateinfo->g > searchstateinfo->v){ 01073 SBPL_FPRINTF(fOut, "ERROR: underconsistent state %d is encountered\n", state->StateID); 01074 throw new SBPL_Exception(); 01075 } 01076 01077 if(!bforwardsearch) //otherwise this cost is not even set 01078 { 01079 if(nextstate->PlannerSpecificData != NULL && searchstateinfo->g < searchstateinfo->costtobestnextstate + ((ADState*)(nextstate->PlannerSpecificData))->g) 01080 { 01081 SBPL_FPRINTF(fOut, "ERROR: g(source) < c(source,target) + g(target)\n"); 01082 throw new SBPL_Exception(); 01083 } 01084 } 01085 01086 #endif 01087 01088 //PrintSearchState(searchstateinfo, fOut); 01089 SBPL_FPRINTF(fOut, "-->state %d ctg = %d ", 01090 nextstate->StateID, costToGoal); 01091 01092 state = nextstate; 01093 01094 environment_->PrintState(state->StateID, true, fOut); 01095 01096 } 01097 01098 if(state->StateID != pSearchStateSpace->searchstartstate->StateID){ 01099 SBPL_ERROR("ERROR: Failed to printsearchpath, max_steps reached\n"); 01100 return; 01101 } 01102 01103 } 01104 01105 int ADPlanner::getHeurValue(ADSearchStateSpace_t* pSearchStateSpace, int StateID) 01106 { 01107 CMDPSTATE* MDPstate = GetState(StateID, pSearchStateSpace); 01108 ADState* searchstateinfo = (ADState*)MDPstate->PlannerSpecificData; 01109 return searchstateinfo->h; 01110 } 01111 01112 01113 vector<int> ADPlanner::GetSearchPath(ADSearchStateSpace_t* pSearchStateSpace, int& solcost) 01114 { 01115 vector<int> SuccIDV; 01116 vector<int> CostV; 01117 vector<int> wholePathIds; 01118 ADState* searchstateinfo; 01119 CMDPSTATE* state = NULL; 01120 CMDPSTATE* goalstate = NULL; 01121 CMDPSTATE* startstate=NULL; 01122 01123 if(bforwardsearch) 01124 { 01125 startstate = pSearchStateSpace->searchstartstate; 01126 goalstate = pSearchStateSpace->searchgoalstate; 01127 01128 //reconstruct the path by setting bestnextstate pointers appropriately 01129 if(ReconstructPath(pSearchStateSpace) != 1){ 01130 solcost = INFINITECOST; 01131 return wholePathIds; 01132 } 01133 } 01134 else 01135 { 01136 startstate = pSearchStateSpace->searchgoalstate; 01137 goalstate = pSearchStateSpace->searchstartstate; 01138 } 01139 01140 01141 #if DEBUG 01142 //PrintSearchPath(pSearchStateSpace, fDeb); 01143 #endif 01144 01145 01146 state = startstate; 01147 01148 wholePathIds.push_back(state->StateID); 01149 solcost = 0; 01150 01151 FILE* fOut = stdout; 01152 if(fOut == NULL){ 01153 SBPL_ERROR("ERROR: could not open file\n"); 01154 throw new SBPL_Exception(); 01155 } 01156 int steps = 0; 01157 const int max_steps = 100000; 01158 while(state->StateID != goalstate->StateID && steps < max_steps) 01159 { 01160 steps++; 01161 01162 if(state->PlannerSpecificData == NULL) 01163 { 01164 SBPL_FPRINTF(fOut, "path does not exist since search data does not exist\n"); 01165 break; 01166 } 01167 01168 searchstateinfo = (ADState*)state->PlannerSpecificData; 01169 01170 if(searchstateinfo->bestnextstate == NULL) 01171 { 01172 SBPL_FPRINTF(fOut, "path does not exist since bestnextstate == NULL\n"); 01173 break; 01174 } 01175 if(searchstateinfo->g == INFINITECOST) 01176 { 01177 SBPL_FPRINTF(fOut, "path does not exist since bestnextstate == NULL\n"); 01178 break; 01179 } 01180 01181 environment_->GetSuccs(state->StateID, &SuccIDV, &CostV); 01182 int actioncost = INFINITECOST; 01183 for(int i = 0; i < (int)SuccIDV.size(); i++) 01184 { 01185 if(SuccIDV.at(i) == searchstateinfo->bestnextstate->StateID && CostV.at(i)<actioncost) 01186 actioncost = CostV.at(i); 01187 01188 } 01189 solcost += actioncost; 01190 01191 if(searchstateinfo->v < searchstateinfo->g) 01192 { 01193 SBPL_ERROR("ERROR: underconsistent state on the path\n"); 01194 PrintSearchState(searchstateinfo, stdout); 01195 //SBPL_FPRINTF(fDeb, "ERROR: underconsistent state on the path\n"); 01196 //PrintSearchState(searchstateinfo, fDeb); 01197 throw new SBPL_Exception(); 01198 } 01199 01200 //SBPL_FPRINTF(fDeb, "actioncost=%d between states %d and %d\n", 01201 // actioncost, state->StateID, searchstateinfo->bestnextstate->StateID); 01202 //environment_->PrintState(state->StateID, false, fDeb); 01203 //environment_->PrintState(searchstateinfo->bestnextstate->StateID, false, fDeb); 01204 01205 01206 state = searchstateinfo->bestnextstate; 01207 01208 wholePathIds.push_back(state->StateID); 01209 } 01210 01211 if(state->StateID != goalstate->StateID){ 01212 SBPL_ERROR("ERROR: Failed to getsearchpath, steps processed=%d\n", steps); 01213 wholePathIds.clear(); 01214 solcost = INFINITECOST; 01215 return wholePathIds; 01216 } 01217 01218 //PrintSearchPath(pSearchStateSpace, stdout); 01219 01220 return wholePathIds; 01221 } 01222 01223 01224 01225 bool ADPlanner::Search(ADSearchStateSpace_t* pSearchStateSpace, vector<int>& pathIds, int & PathCost, bool bFirstSolution, bool bOptimalSolution, double MaxNumofSecs) 01226 { 01227 CKey key; 01228 TimeStarted = clock(); 01229 searchexpands = 0; 01230 01231 #if DEBUG 01232 SBPL_FPRINTF(fDeb, "new search call (call number=%d)\n", pSearchStateSpace->callnumber); 01233 #endif 01234 01235 if(pSearchStateSpace->bReinitializeSearchStateSpace == true){ 01236 //re-initialize state space 01237 ReInitializeSearchStateSpace(pSearchStateSpace); 01238 } 01239 01240 01241 if(bOptimalSolution) 01242 { 01243 pSearchStateSpace->eps = 1; 01244 MaxNumofSecs = INFINITECOST; 01245 } 01246 else if(bFirstSolution) 01247 { 01248 MaxNumofSecs = INFINITECOST; 01249 } 01250 01251 //ensure heuristics are up-to-date 01252 environment_->EnsureHeuristicsUpdated((bforwardsearch==true)); 01253 01254 //the main loop of AD* 01255 int prevexpands = 0; 01256 clock_t loop_time; 01257 while(pSearchStateSpace->eps_satisfied > AD_FINAL_EPS && 01258 (clock()- TimeStarted) < MaxNumofSecs*(double)CLOCKS_PER_SEC) 01259 { 01260 loop_time = clock(); 01261 //it will be a new search iteration 01262 if(pSearchStateSpace->searchiteration == 0) pSearchStateSpace->searchiteration++; 01263 01264 //decrease eps for all subsequent iterations 01265 if(fabs(pSearchStateSpace->eps_satisfied - pSearchStateSpace->eps) < ERR_EPS && !bFirstSolution) 01266 { 01267 pSearchStateSpace->eps = pSearchStateSpace->eps - AD_DECREASE_EPS; 01268 if(pSearchStateSpace->eps < AD_FINAL_EPS) 01269 pSearchStateSpace->eps = AD_FINAL_EPS; 01270 01271 01272 pSearchStateSpace->bReevaluatefvals = true; 01273 pSearchStateSpace->bRebuildOpenList = true; 01274 01275 pSearchStateSpace->searchiteration++; 01276 } 01277 01278 //build a new open list by merging it with incons one 01279 if(pSearchStateSpace->bRebuildOpenList) 01280 BuildNewOPENList(pSearchStateSpace); 01281 01282 //re-compute f-values if necessary and reorder the heap 01283 if(pSearchStateSpace->bReevaluatefvals) 01284 Reevaluatefvals(pSearchStateSpace); 01285 01286 01287 //improve or compute path 01288 if(ComputePath(pSearchStateSpace, MaxNumofSecs) == 1){ 01289 pSearchStateSpace->eps_satisfied = pSearchStateSpace->eps; 01290 } 01291 01292 //print the solution cost and eps bound 01293 SBPL_PRINTF("eps=%f expands=%d g(sstart)=%d\n", pSearchStateSpace->eps_satisfied, searchexpands - prevexpands, 01294 ((ADState*)pSearchStateSpace->searchgoalstate->PlannerSpecificData)->g); 01295 01296 if(pSearchStateSpace->eps_satisfied == finitial_eps && pSearchStateSpace->eps == finitial_eps) 01297 { 01298 finitial_eps_planning_time = double(clock()-loop_time)/CLOCKS_PER_SEC; 01299 num_of_expands_initial_solution = searchexpands - prevexpands; 01300 } 01301 01302 #if DEBUG 01303 SBPL_FPRINTF(fDeb, "eps=%f eps_sat=%f expands=%d g(sstart)=%d\n", pSearchStateSpace->eps, pSearchStateSpace->eps_satisfied, searchexpands - prevexpands, 01304 ((ADState*)pSearchStateSpace->searchgoalstate->PlannerSpecificData)->g); 01305 #endif 01306 prevexpands = searchexpands; 01307 01308 01309 //if just the first solution then we are done 01310 if(bFirstSolution) 01311 break; 01312 01313 //no solution exists 01314 if(((ADState*)pSearchStateSpace->searchgoalstate->PlannerSpecificData)->g == INFINITECOST) 01315 break; 01316 01317 } 01318 01319 01320 #if DEBUG 01321 SBPL_FFLUSH(fDeb); 01322 #endif 01323 01324 PathCost = ((ADState*)pSearchStateSpace->searchgoalstate->PlannerSpecificData)->g; 01325 MaxMemoryCounter += environment_->StateID2IndexMapping.size()*sizeof(int); 01326 01327 SBPL_PRINTF("MaxMemoryCounter = %d\n", MaxMemoryCounter); 01328 01329 int solcost = INFINITECOST; 01330 bool ret = false; 01331 if(PathCost == INFINITECOST || pSearchStateSpace_->eps_satisfied == INFINITECOST) 01332 { 01333 SBPL_PRINTF("could not find a solution\n"); 01334 ret = false; 01335 } 01336 else 01337 { 01338 SBPL_PRINTF("solution is found\n"); 01339 01340 pathIds = GetSearchPath(pSearchStateSpace, solcost); 01341 ret = true; 01342 } 01343 01344 SBPL_PRINTF("total expands this call = %d, planning time = %.3f secs, solution cost=%d\n", 01345 searchexpands, (clock()-TimeStarted)/((double)CLOCKS_PER_SEC), solcost); 01346 final_eps_planning_time = (clock()-TimeStarted)/((double)CLOCKS_PER_SEC); 01347 final_eps = pSearchStateSpace->eps_satisfied; 01348 01349 01350 //SBPL_FPRINTF(fStat, "%d %d\n", searchexpands, solcost); 01351 01352 return ret; 01353 01354 } 01355 01356 void ADPlanner::Update_SearchSuccs_of_ChangedEdges(vector<int> const * statesIDV) 01357 { 01358 SBPL_PRINTF("updating %d affected states\n", (unsigned int)statesIDV->size()); 01359 01360 if(statesIDV->size() > environment_->StateID2IndexMapping.size()/10) 01361 { 01362 SBPL_PRINTF("skipping affected states and instead restarting planner from scratch\n"); 01363 pSearchStateSpace_->bReinitializeSearchStateSpace = true; 01364 } 01365 01366 //it will be a new search iteration 01367 pSearchStateSpace_->searchiteration++; 01368 01369 //will need to rebuild open list 01370 pSearchStateSpace_->bRebuildOpenList = true; 01371 01372 01373 int numofstatesaffected = 0; 01374 for(int pind = 0; pind < (int)statesIDV->size(); pind++) 01375 { 01376 int stateID = statesIDV->at(pind); 01377 01378 //first check that the state exists (to avoid creation of additional states) 01379 if(environment_->StateID2IndexMapping[stateID][ADMDP_STATEID2IND] == -1) 01380 continue; 01381 01382 //now get the state 01383 CMDPSTATE* state = GetState(stateID, pSearchStateSpace_); 01384 ADState* searchstateinfo = (ADState*)state->PlannerSpecificData; 01385 01386 //now check that the state is not start state and was created after last search reset 01387 if(stateID != pSearchStateSpace_->searchstartstate->StateID && searchstateinfo->callnumberaccessed == pSearchStateSpace_->callnumber) 01388 { 01389 01390 #if DEBUG 01391 SBPL_FPRINTF(fDeb, "updating affected state %d:\n", stateID); 01392 PrintSearchState(searchstateinfo, fDeb); 01393 SBPL_FPRINTF(fDeb, "\n"); 01394 #endif 01395 01396 //now we really do need to update it 01397 Recomputegval(searchstateinfo); 01398 UpdateSetMembership(searchstateinfo); 01399 numofstatesaffected++; 01400 01401 #if DEBUG 01402 SBPL_FPRINTF(fDeb, "the state %d after update\n", stateID); 01403 PrintSearchState(searchstateinfo, fDeb); 01404 SBPL_FPRINTF(fDeb, "\n"); 01405 #endif 01406 01407 01408 } 01409 } 01410 01411 //TODO - check. I believe that there are cases when number of states generated is drastically smaller than the number of states really affected, which is a bug! 01412 SBPL_PRINTF("%d states really affected (%d states generated total so far)\n", numofstatesaffected, (int)environment_->StateID2IndexMapping.size()); 01413 01414 //reset eps for which we know a path was computed 01415 if(numofstatesaffected > 0) 01416 { 01417 //make sure eps is reset appropriately 01418 pSearchStateSpace_->eps = this->finitial_eps; 01419 01420 //reset the satisfied eps 01421 pSearchStateSpace_->eps_satisfied = INFINITECOST; 01422 } 01423 01424 } 01425 01426 01427 //-----------------------------Interface function----------------------------------------------------- 01428 //returns 1 if found a solution, and 0 otherwise 01429 int ADPlanner::replan(double allocated_time_secs, vector<int>* solution_stateIDs_V) 01430 { 01431 int solcost; 01432 01433 return replan(allocated_time_secs, solution_stateIDs_V, &solcost); 01434 01435 } 01436 01437 01438 01439 //returns 1 if found a solution, and 0 otherwise 01440 int ADPlanner::replan(double allocated_time_secs, vector<int>* solution_stateIDs_V, int* psolcost) 01441 { 01442 vector<int> pathIds; 01443 int PathCost = 0; 01444 bool bFound = false; 01445 *psolcost = 0; 01446 bool bOptimalSolution = false; 01447 01448 SBPL_PRINTF("planner: replan called (bFirstSol=%d, bOptSol=%d)\n", bsearchuntilfirstsolution, bOptimalSolution); 01449 01450 //plan for the first solution only 01451 if((bFound = Search(pSearchStateSpace_, pathIds, PathCost, bsearchuntilfirstsolution, bOptimalSolution, allocated_time_secs)) == false) 01452 { 01453 SBPL_PRINTF("failed to find a solution\n"); 01454 } 01455 01456 //copy the solution 01457 *solution_stateIDs_V = pathIds; 01458 *psolcost = PathCost; 01459 01460 return (int)bFound; 01461 01462 } 01463 01464 int ADPlanner::set_goal(int goal_stateID) 01465 { 01466 01467 SBPL_PRINTF("planner: setting goal to %d\n", goal_stateID); 01468 environment_->PrintState(goal_stateID, true, stdout); 01469 01470 //it will be a new search iteration 01471 pSearchStateSpace_->searchiteration++; 01472 pSearchStateSpace_->bRebuildOpenList = true; //is not really necessary for search goal changes 01473 01474 if(bforwardsearch) 01475 { 01476 if(SetSearchGoalState(goal_stateID, pSearchStateSpace_) != 1) 01477 { 01478 SBPL_ERROR("ERROR: failed to set search goal state\n"); 01479 return 0; 01480 } 01481 } 01482 else 01483 { 01484 if(SetSearchStartState(goal_stateID, pSearchStateSpace_) != 1) 01485 { 01486 SBPL_ERROR("ERROR: failed to set search start state\n"); 01487 return 0; 01488 } 01489 } 01490 01491 return 1; 01492 } 01493 01494 01495 int ADPlanner::set_start(int start_stateID) 01496 { 01497 01498 SBPL_PRINTF("planner: setting start to %d\n", start_stateID); 01499 environment_->PrintState(start_stateID, true, stdout); 01500 01501 //it will be a new search iteration 01502 pSearchStateSpace_->searchiteration++; 01503 pSearchStateSpace_->bRebuildOpenList = true; 01504 01505 01506 if(bforwardsearch) 01507 { 01508 if(SetSearchStartState(start_stateID, pSearchStateSpace_) != 1) 01509 { 01510 SBPL_ERROR("ERROR: failed to set search start state\n"); 01511 return 0; 01512 } 01513 } 01514 else 01515 { 01516 if(SetSearchGoalState(start_stateID, pSearchStateSpace_) != 1) 01517 { 01518 SBPL_ERROR("ERROR: failed to set search goal state\n"); 01519 return 0; 01520 } 01521 } 01522 01523 return 1; 01524 01525 } 01526 01527 01528 void ADPlanner::update_succs_of_changededges(vector<int>* succstatesIDV) 01529 { 01530 SBPL_PRINTF("UpdateSuccs called on %d succs\n", (unsigned int)succstatesIDV->size()); 01531 01532 Update_SearchSuccs_of_ChangedEdges(succstatesIDV); 01533 } 01534 01535 void ADPlanner::update_preds_of_changededges(vector<int>* predstatesIDV) 01536 { 01537 SBPL_PRINTF("UpdatePreds called on %d preds\n", (unsigned int)predstatesIDV->size()); 01538 01539 Update_SearchSuccs_of_ChangedEdges(predstatesIDV); 01540 } 01541 01542 01543 int ADPlanner::force_planning_from_scratch() 01544 { 01545 SBPL_PRINTF("planner: forceplanfromscratch set\n"); 01546 01547 pSearchStateSpace_->bReinitializeSearchStateSpace = true; 01548 01549 return 1; 01550 } 01551 01552 01553 int ADPlanner::set_search_mode(bool bSearchUntilFirstSolution) 01554 { 01555 SBPL_PRINTF("planner: search mode set to %d\n", bSearchUntilFirstSolution); 01556 01557 bsearchuntilfirstsolution = bSearchUntilFirstSolution; 01558 01559 return 1; 01560 } 01561 01562 01563 void ADPlanner::costs_changed(StateChangeQuery const & stateChange) 01564 { 01565 if(pSearchStateSpace_->bReinitializeSearchStateSpace == true || pSearchStateSpace_->searchiteration == 0) 01566 return; //no processing if no search efforts anyway 01567 01568 if (bforwardsearch) 01569 Update_SearchSuccs_of_ChangedEdges(stateChange.getSuccessors()); 01570 else 01571 Update_SearchSuccs_of_ChangedEdges(stateChange.getPredecessors()); 01572 } 01573 01574 01575 //--------------------------------------------------------------------------------------------------------- 01576