$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 //extern clock_t time3_addallout; 00037 //extern clock_t time_gethash; 00038 //extern clock_t time_createhash; 00039 00040 00041 //function prototypes 00042 00043 00044 //-------------------problem specific and local functions--------------------- 00045 00046 00047 static unsigned int inthash(unsigned int key) 00048 { 00049 key += (key << 12); 00050 key ^= (key >> 22); 00051 key += (key << 4); 00052 key ^= (key >> 9); 00053 key += (key << 10); 00054 key ^= (key >> 2); 00055 key += (key << 7); 00056 key ^= (key >> 12); 00057 return key; 00058 } 00059 00060 //examples of hash functions: map state coordinates onto a hash value 00061 //#define GETHASHBIN(X, Y) (Y*WIDTH_Y+X) 00062 //here we have state coord: <X1, X2, X3, X4> 00063 unsigned int EnvironmentXXX::GETHASHBIN(unsigned int X1, unsigned int X2, 00064 unsigned int X3, unsigned int X4) 00065 { 00066 00067 return inthash((inthash(X1)+(inthash(X2)<<1)+(inthash(X3)<<2)+(inthash(X4)<<3))) & (EnvXXX.HashTableSize-1); 00068 } 00069 00070 00071 00072 void EnvironmentXXX::PrintHashTableHist() 00073 { 00074 int s0=0, s1=0, s50=0, s100=0, s200=0, s300=0, slarge=0; 00075 00076 for(int j = 0; j < (int)EnvXXX.HashTableSize; j++) 00077 { 00078 if((int)EnvXXX.Coord2StateIDHashTable[j].size() == 0) 00079 s0++; 00080 else if((int)EnvXXX.Coord2StateIDHashTable[j].size() < 50) 00081 s1++; 00082 else if((int)EnvXXX.Coord2StateIDHashTable[j].size() < 100) 00083 s50++; 00084 else if((int)EnvXXX.Coord2StateIDHashTable[j].size() < 200) 00085 s100++; 00086 else if((int)EnvXXX.Coord2StateIDHashTable[j].size() < 300) 00087 s200++; 00088 else if((int)EnvXXX.Coord2StateIDHashTable[j].size() < 400) 00089 s300++; 00090 else 00091 slarge++; 00092 } 00093 SBPL_PRINTF("hash table histogram: 0:%d, <50:%d, <100:%d, <200:%d, <300:%d, <400:%d >400:%d\n", 00094 s0,s1, s50, s100, s200,s300,slarge); 00095 } 00096 00097 void EnvironmentXXX::ReadConfiguration(FILE* fCfg) 00098 { 00099 //read in the configuration of environment and initialize EnvCfg structure 00100 00101 } 00102 00103 00104 void EnvironmentXXX::InitializeEnvConfig() 00105 { 00106 //aditional to configuration file initialization of EnvCfg if necessary 00107 00108 } 00109 00110 00111 EnvXXXHashEntry_t* EnvironmentXXX::GetHashEntry(unsigned int X1, unsigned int X2, 00112 unsigned int X3, unsigned int X4) 00113 { 00114 //clock_t currenttime = clock(); 00115 00116 int binid = GETHASHBIN(X1, X2, X3, X4); 00117 00118 #if DEBUG 00119 if ((int)EnvXXX.Coord2StateIDHashTable[binid].size() > 500) 00120 { 00121 SBPL_PRINTF("WARNING: Hash table has a bin %d (X1=%d X2=%d X3=%d X4=%d) of size %d\n", 00122 binid, X1, X2, X3, X4, EnvXXX.Coord2StateIDHashTable[binid].size()); 00123 00124 PrintHashTableHist(); 00125 } 00126 #endif 00127 00128 //iterate over the states in the bin and select the perfect match 00129 for(int ind = 0; ind < (int)EnvXXX.Coord2StateIDHashTable[binid].size(); ind++) 00130 { 00131 if( EnvXXX.Coord2StateIDHashTable[binid][ind]->X1 == X1 00132 && EnvXXX.Coord2StateIDHashTable[binid][ind]->X2 == X2 00133 && EnvXXX.Coord2StateIDHashTable[binid][ind]->X3 == X3 00134 && EnvXXX.Coord2StateIDHashTable[binid][ind]->X4 == X4) 00135 { 00136 //time_gethash += clock()-currenttime; 00137 return EnvXXX.Coord2StateIDHashTable[binid][ind]; 00138 } 00139 } 00140 00141 //time_gethash += clock()-currenttime; 00142 00143 return NULL; 00144 } 00145 00146 00147 EnvXXXHashEntry_t* EnvironmentXXX::CreateNewHashEntry(unsigned int X1, unsigned int X2, 00148 unsigned int X3, unsigned int X4) 00149 { 00150 int i; 00151 00152 //clock_t currenttime = clock(); 00153 00154 EnvXXXHashEntry_t* HashEntry = new EnvXXXHashEntry_t; 00155 00156 HashEntry->X1 = X1; 00157 HashEntry->X2 = X2; 00158 HashEntry->X3 = X3; 00159 HashEntry->X4 = X4; 00160 00161 HashEntry->stateID = EnvXXX.StateID2CoordTable.size(); 00162 00163 //insert into the tables 00164 EnvXXX.StateID2CoordTable.push_back(HashEntry); 00165 00166 00167 //get the hash table bin 00168 i = GETHASHBIN(HashEntry->X1, HashEntry->X2, 00169 HashEntry->X3, HashEntry->X4); 00170 00171 //insert the entry into the bin 00172 EnvXXX.Coord2StateIDHashTable[i].push_back(HashEntry); 00173 00174 //insert into and initialize the mappings 00175 int* entry = new int [NUMOFINDICES_STATEID2IND]; 00176 StateID2IndexMapping.push_back(entry); 00177 for(i = 0; i < NUMOFINDICES_STATEID2IND; i++) 00178 { 00179 StateID2IndexMapping[HashEntry->stateID][i] = -1; 00180 } 00181 00182 if(HashEntry->stateID != (int)StateID2IndexMapping.size()-1) 00183 { 00184 SBPL_ERROR("ERROR in Env... function: last state has incorrect stateID\n"); 00185 throw new SBPL_Exception(); 00186 } 00187 00188 00189 //time_createhash += clock()-currenttime; 00190 00191 return HashEntry; 00192 } 00193 00194 00195 void EnvironmentXXX::CreateStartandGoalStates() 00196 { 00197 EnvXXXHashEntry_t* HashEntry; 00198 00199 //create start state 00200 unsigned int X1 = 0; 00201 unsigned int X2 = 0; 00202 unsigned int X3 = 0; 00203 unsigned int X4 = 0; 00204 HashEntry = CreateNewHashEntry(X1, X2, X3, X4); 00205 EnvXXX.startstateid = HashEntry->stateID; 00206 00207 //create goal state 00208 X1 = X2 = X3 = X4 = 1; 00209 HashEntry = CreateNewHashEntry(X1, X2, X3, X4); 00210 EnvXXX.goalstateid = HashEntry->stateID; 00211 } 00212 00213 00214 void EnvironmentXXX::InitializeEnvironment() 00215 { 00216 00217 //initialize the map from Coord to StateID 00218 EnvXXX.HashTableSize = 32*1024; //should be power of two 00219 EnvXXX.Coord2StateIDHashTable = new vector<EnvXXXHashEntry_t*>[EnvXXX.HashTableSize]; 00220 00221 //initialize the map from StateID to Coord 00222 EnvXXX.StateID2CoordTable.clear(); 00223 00224 //create start and goal states 00225 CreateStartandGoalStates(); 00226 } 00227 00228 00229 void EnvironmentXXX::AddAllOutcomes(unsigned int SourceX1, unsigned int SourceX2, unsigned int SourceX3, 00230 unsigned int SourceX4, CMDPACTION* action, int cost) 00231 { 00232 EnvXXXHashEntry_t* OutHashEntry; 00233 int i; 00234 float CumProb = 0.0; 00235 00236 //iterate over outcomes 00237 for(i = 0; i < 2; i++) 00238 { 00239 unsigned int newX1 = SourceX1+i; 00240 unsigned int newX2 = SourceX2+i; 00241 unsigned int newX3 = SourceX3+i; 00242 unsigned int newX4 = SourceX4+i; 00243 00244 //add the outcome 00245 if((OutHashEntry = GetHashEntry(newX1, newX2, 00246 newX3, newX4)) == NULL) 00247 { 00248 //have to create a new entry 00249 OutHashEntry = CreateNewHashEntry(newX1, newX2, 00250 newX3, newX4); 00251 } 00252 float Prob = 0.5; //probability of the outcome 00253 action->AddOutcome(OutHashEntry->stateID, cost, Prob); 00254 CumProb += Prob; 00255 00256 } //while 00257 00258 if(CumProb != 1.0) 00259 { 00260 SBPL_ERROR("ERROR in EnvXXX... function: prob. of all action outcomes=%f\n", CumProb); 00261 throw new SBPL_Exception(); 00262 } 00263 00264 } 00265 00266 00267 //------------------------------------------------------------------------------ 00268 00269 //------------------------------Heuristic computation-------------------------- 00270 00271 void EnvironmentXXX::ComputeHeuristicValues() 00272 { 00273 //whatever necessary pre-computation of heuristic values is done here 00274 SBPL_PRINTF("Precomputing heuristics\n"); 00275 00276 00277 00278 SBPL_PRINTF("done\n"); 00279 00280 } 00281 00282 //-----------interface with outside functions----------------------------------- 00283 bool EnvironmentXXX::InitializeEnv(const char* sEnvFile) 00284 { 00285 00286 FILE* fCfg = fopen(sEnvFile, "r"); 00287 if(fCfg == NULL) 00288 { 00289 SBPL_ERROR("ERROR: unable to open %s\n", sEnvFile); 00290 throw new SBPL_Exception(); 00291 } 00292 ReadConfiguration(fCfg); 00293 fclose(fCfg); 00294 00295 //Initialize other parameters of the environment 00296 InitializeEnvConfig(); 00297 00298 //initialize Environment 00299 InitializeEnvironment(); 00300 00301 //pre-compute heuristics 00302 ComputeHeuristicValues(); 00303 00304 return true; 00305 } 00306 00307 00308 bool EnvironmentXXX::InitializeMDPCfg(MDPConfig *MDPCfg) 00309 { 00310 //initialize MDPCfg with the start and goal ids 00311 MDPCfg->goalstateid = EnvXXX.goalstateid; 00312 MDPCfg->startstateid = EnvXXX.startstateid; 00313 00314 return true; 00315 } 00316 00317 00318 00319 int EnvironmentXXX::GetFromToHeuristic(int FromStateID, int ToStateID) 00320 { 00321 #if USE_HEUR==0 00322 return 0; 00323 #endif 00324 00325 00326 #if DEBUG 00327 if(FromStateID >= (int)EnvXXX.StateID2CoordTable.size() 00328 || ToStateID >= (int)EnvXXX.StateID2CoordTable.size()) 00329 { 00330 SBPL_ERROR("ERROR in EnvXXX... function: stateID illegal\n"); 00331 throw new SBPL_Exception(); 00332 } 00333 #endif 00334 00335 //define this function if it is used in the planner 00336 00337 SBPL_ERROR("ERROR in EnvXXX.. function: FromToHeuristic is undefined\n"); 00338 throw new SBPL_Exception(); 00339 00340 return 0; 00341 00342 } 00343 00344 00345 int EnvironmentXXX::GetGoalHeuristic(int stateID) 00346 { 00347 #if USE_HEUR==0 00348 return 0; 00349 #endif 00350 00351 #if DEBUG 00352 if(stateID >= (int)EnvXXX.StateID2CoordTable.size()) 00353 { 00354 SBPL_ERROR("ERROR in EnvXXX... function: stateID illegal\n"); 00355 throw new SBPL_Exception(); 00356 } 00357 #endif 00358 00359 00360 //define this function if it used in the planner (heuristic forward search would use it) 00361 00362 SBPL_ERROR("ERROR in EnvXXX..function: GetGoalHeuristic is undefined\n"); 00363 throw new SBPL_Exception(); 00364 } 00365 00366 00367 int EnvironmentXXX::GetStartHeuristic(int stateID) 00368 { 00369 #if USE_HEUR==0 00370 return 0; 00371 #endif 00372 00373 00374 #if DEBUG 00375 if(stateID >= (int)EnvXXX.StateID2CoordTable.size()) 00376 { 00377 SBPL_ERROR("ERROR in EnvXXX... function: stateID illegal\n"); 00378 throw new SBPL_Exception(); 00379 } 00380 #endif 00381 00382 //define this function if it used in the planner (heuristic backward search would use it) 00383 00384 SBPL_ERROR("ERROR in EnvXXX.. function: GetStartHeuristic is undefined\n"); 00385 throw new SBPL_Exception(); 00386 00387 return 0; 00388 00389 00390 } 00391 00392 00393 00394 void EnvironmentXXX::SetAllActionsandAllOutcomes(CMDPSTATE* state) 00395 { 00396 00397 00398 #if DEBUG 00399 if(state->StateID >= (int)EnvXXX.StateID2CoordTable.size()) 00400 { 00401 SBPL_ERROR("ERROR in EnvXXX... function: stateID illegal\n"); 00402 throw new SBPL_Exception(); 00403 } 00404 00405 if((int)state->Actions.size() != 0) 00406 { 00407 SBPL_ERROR("ERROR in Env_setAllActionsandAllOutcomes: actions already exist for the state\n"); 00408 throw new SBPL_Exception(); 00409 } 00410 #endif 00411 00412 //if it is goal then no successors 00413 if(state->StateID == EnvXXX.goalstateid) 00414 return; 00415 00416 //get values for the state 00417 EnvXXXHashEntry_t* HashEntry = EnvXXX.StateID2CoordTable[state->StateID]; 00418 00419 //iterate through the actions for the state 00420 for (int aind = 0; aind < XXX_MAXACTIONSWIDTH; aind++) 00421 { 00422 int cost = 1; 00423 00424 //Add Action 00425 CMDPACTION* action = state->AddAction(aind); 00426 00427 //clock_t currenttime = clock(); 00428 //add all the outcomes to the action 00429 AddAllOutcomes(HashEntry->X1, HashEntry->X2, HashEntry->X3, HashEntry->X4, action, cost); 00430 00431 //you can break if the number of actual actions is smaller than the maximum possible 00432 00433 //time3_addallout += clock()-currenttime; 00434 } 00435 } 00436 00437 00438 00439 void EnvironmentXXX::SetAllPreds(CMDPSTATE* state) 00440 { 00441 //implement this if the planner needs access to predecessors 00442 00443 SBPL_ERROR("ERROR in EnvXXX... function: SetAllPreds is undefined\n"); 00444 throw new SBPL_Exception(); 00445 } 00446 00447 00448 void EnvironmentXXX::GetSuccs(int SourceStateID, vector<int>* SuccIDV, vector<int>* CostV) 00449 { 00450 00451 SBPL_ERROR("ERROR in EnvXXX... function: GetSuccs is undefined\n"); 00452 throw new SBPL_Exception(); 00453 } 00454 00455 void EnvironmentXXX::GetPreds(int TargetStateID, vector<int>* PredIDV, vector<int>* CostV) 00456 { 00457 00458 SBPL_ERROR("ERROR in EnvXXX... function: GetPreds is undefined\n"); 00459 throw new SBPL_Exception(); 00460 } 00461 00462 00463 int EnvironmentXXX::SizeofCreatedEnv() 00464 { 00465 return (int)EnvXXX.StateID2CoordTable.size(); 00466 00467 } 00468 00469 void EnvironmentXXX::PrintState(int stateID, bool bVerbose, FILE* fOut /*=NULL*/) 00470 { 00471 #if DEBUG 00472 if(stateID >= (int)EnvXXX.StateID2CoordTable.size()) 00473 { 00474 SBPL_ERROR("ERROR in EnvXXX... function: stateID illegal (2)\n"); 00475 throw new SBPL_Exception(); 00476 } 00477 #endif 00478 00479 if(fOut == NULL) 00480 fOut = stdout; 00481 00482 EnvXXXHashEntry_t* HashEntry = EnvXXX.StateID2CoordTable[stateID]; 00483 00484 if(stateID == EnvXXX.goalstateid) 00485 { 00486 SBPL_FPRINTF(fOut, "the state is a goal state\n"); 00487 } 00488 00489 SBPL_FPRINTF(fOut, "X1=%d X2=%d X3=%d X4=%d\n", 00490 HashEntry->X1, HashEntry->X2, 00491 HashEntry->X3, HashEntry->X4); 00492 00493 00494 } 00495 00496 00497 void EnvironmentXXX::PrintEnv_Config(FILE* fOut) 00498 { 00499 00500 //implement this if the planner needs to print out EnvXXX. configuration 00501 00502 SBPL_ERROR("ERROR in EnvXXX... function: PrintEnv_Config is undefined\n"); 00503 throw new SBPL_Exception(); 00504 00505 } 00506 //------------------------------------------------------------------------------