00001 #ifndef MMANN_FCS_ASTAR_SOLVING_ALGORITHM_H
00002 #define MMANN_FCS_ASTAR_SOLVING_ALGORITHM_H
00003
00011
00012 #include <limits.h>
00013 #include <stdlib.h>
00014 #include <math.h>
00015 #include "FCSFreecellData.h"
00016 #include "FCSFreecellAlgorithm.h"
00017 #include "PriorityQueue.h"
00018
00020 #define FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT 1.3
00021
00022 #define FCS_A_STAR_SEQS_OVER_RENEGADE_CARDS_EXPONENT 1.3
00023
00025 static const double FCSAStarDefaultWeights[5] = {0.5,0,0.3,0,0.2};
00026
00028 enum AStarWeightEnum {FCS_A_STAR_WEIGHT_CARDS_OUT = 0,
00029 FCS_A_STAR_WEIGHT_MAX_SEQUENCE_MOVE = 1,
00030 FCS_A_STAR_WEIGHT_CARDS_UNDER_SEQUENCES = 2,
00031 FCS_A_STAR_WEIGHT_SEQS_OVER_RENEGADE_CARDS = 3,
00032 FCS_A_STAR_WEIGHT_DEPTH = 4};
00033
00035 template <class SolvingAlgorithmType>
00036 class FCSAStarSolvingAlgorithm : public SolvingAlgorithmType
00037 {
00038 public:
00040 FCSAStarSolvingAlgorithm(FCCommandLineArguments* CommandLine);
00041
00043 virtual ~FCSAStarSolvingAlgorithm();
00044
00050 virtual FCSStateSolvingReturnCodes Solve(FCSStateWithLocations* StateWithLocations, int Depth);
00051
00056 virtual FCSStateSolvingReturnCodes Resume(int Depth);
00057
00058 protected:
00060 FCSAStarSolvingAlgorithm();
00061
00063 void InitFCSAStarSolvingAlgorithm();
00064
00068 void InitAStar(FCSStateWithLocations* StateWithLocations);
00069
00074 int AStarRateState(FCSStateWithLocations* StateWithLocations);
00075
00076 private:
00078 PriorityQueue<FCSStateWithLocations>* m_AStarQueue;
00079
00081 double m_AStarInitialCardsUnderSequence;
00082
00084 double m_AStarWeights[5];
00085
00087 FCSStateWithLocations* m_FirstStateToCheck;
00088
00089 };
00090
00091 template <class SolvingAlgorithmType>
00092 FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::FCSAStarSolvingAlgorithm() : SolvingAlgorithmType()
00093 {
00094 InitFCSAStarSolvingAlgorithm();
00095 }
00096
00097 template <class SolvingAlgorithmType>
00098 void FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::InitFCSAStarSolvingAlgorithm()
00099 {
00100 m_AStarQueue = NULL;
00101
00102
00103 for(int a=0;a<(sizeof(m_AStarWeights)/sizeof(m_AStarWeights[0]));a++)
00104 {
00105 m_AStarWeights[a] = FCSAStarDefaultWeights[a];
00106 }
00107
00108 m_AStarInitialCardsUnderSequence = 0;
00109 m_FirstStateToCheck = NULL;
00110 }
00111
00112 template <class SolvingAlgorithmType>
00113 FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::FCSAStarSolvingAlgorithm(FCCommandLineArguments* CommandLine) : SolvingAlgorithmType(CommandLine)
00114 {
00115 unsigned int a;
00116 double sum = 0;
00117
00118 InitFCSAStarSolvingAlgorithm();
00119
00120 m_AStarQueue = new PriorityQueue<FCSStateWithLocations>(1024, INT_MAX, 256, true);
00121
00122
00123 if (CommandLine->GetAStarWeights() != NULL)
00124 {
00125 for (a=0; a < sizeof(m_AStarWeights)/sizeof(m_AStarWeights[0]);a++)
00126 {
00127 if (CommandLine->GetAStarWeightValues(a) < 0)
00128 m_AStarWeights[a] = FCSAStarDefaultWeights[a];
00129 else
00130 m_AStarWeights[a] = CommandLine->GetAStarWeightValues(a);
00131 }
00132
00133
00134 for(a=0; a < (sizeof(m_AStarWeights)/sizeof(m_AStarWeights[0]));a++)
00135 sum += m_AStarWeights[a];
00136
00137 if (sum == 0)
00138 sum = 1;
00139
00140 for(a=0;a<(sizeof(m_AStarWeights)/sizeof(m_AStarWeights[0]));a++)
00141 m_AStarWeights[a] /= sum;
00142 }
00143 }
00144
00145 template <class SolvingAlgorithmType>
00146 FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::~FCSAStarSolvingAlgorithm()
00147 {
00148 if (m_AStarQueue != NULL)
00149 delete m_AStarQueue;
00150 }
00151
00152 template <class SolvingAlgorithmType>
00153 FCSStateSolvingReturnCodes FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::Solve(FCSStateWithLocations* StateWithLocations, int Depth)
00154 {
00155 int NumberOfFreeStacks = 0,
00156 NumberOfFreecells = 0,
00157 DerivedIndex, a;
00158
00159 FCSStateSolvingReturnCodes Check;
00160
00161 FCSDerivedStatesList Derived;
00162
00163
00164 InitSolve(StateWithLocations);
00165
00166 InitAStar(StateWithLocations);
00167
00168
00169 StateWithLocations->m_Parent = NULL;
00170 StateWithLocations->m_MovesToParent = NULL;
00171 StateWithLocations->m_Depth = 0;
00172
00173
00174 while (StateWithLocations != NULL)
00175 {
00176 if (StateWithLocations->m_Visited & FCS_VISITED_VISITED)
00177 goto NextState;
00178
00179
00180 NumberOfFreecells = 0;
00181 for(a=0;a<m_NumberOfFreecells;a++)
00182 {
00183 if (StateWithLocations->GetFreecellCardNumber(a) == 0)
00184 NumberOfFreecells++;
00185 }
00186
00187
00188 NumberOfFreeStacks = 0;
00189 for(a=0;a<m_NumberOfStacks;a++)
00190 {
00191 if (StateWithLocations->GetStackLength(a) == 0)
00192 NumberOfFreeStacks++;
00193 }
00194
00195 m_DebugDisplayInfo->Display(m_StateType, m_NumberOfCheckedStates, StateWithLocations->m_Depth, StateWithLocations,
00196 ((StateWithLocations->m_Parent == NULL) ? 0 : StateWithLocations->m_Parent->m_VisitIterations), m_NumberOfStatesInCollection);
00197
00198 if ((NumberOfFreeStacks == m_NumberOfStacks) && (NumberOfFreecells == m_NumberOfFreecells))
00199 {
00200 m_FinalState = StateWithLocations;
00201
00202
00203 DeleteDerived(&Derived);
00204 return FCS_STATE_WAS_SOLVED;
00205 }
00206
00207
00208
00209
00210 m_NumberOfCheckedStates++;
00211
00212
00213
00214
00215 Derived.m_NumberOfStates = 0;
00216 for(a=0 ; a < m_TestsOrderNumber; a++)
00217 {
00218 Check = RunTest(m_TestsOrder[a] & FCS_TEST_ORDER_NO_FLAGS_MASK, StateWithLocations,
00219 StateWithLocations->m_Depth, NumberOfFreeStacks,
00220 NumberOfFreecells, &Derived);
00221
00222 if ((Check == FCS_STATE_BEGIN_SUSPEND_PROCESS) ||
00223 (Check == FCS_STATE_EXCEEDS_MAX_NUM_TIMES) ||
00224 (Check == FCS_STATE_SUSPEND_PROCESS))
00225 {
00226
00227 m_FirstStateToCheck = StateWithLocations;
00228
00229 DeleteDerived(&Derived);
00230 return FCS_STATE_SUSPEND_PROCESS;
00231 }
00232 }
00233
00234
00235 for(DerivedIndex = 0; DerivedIndex < Derived.m_NumberOfStates; DerivedIndex++)
00236 m_AStarQueue->Push(Derived.m_States[DerivedIndex], AStarRateState(Derived.m_States[DerivedIndex]));
00237
00238 StateWithLocations->m_Visited |= FCS_VISITED_VISITED;
00239
00240 StateWithLocations->m_VisitIterations = m_NumberOfCheckedStates-1;
00241
00242 NextState:
00243
00244
00245 StateWithLocations = m_AStarQueue->Pop();
00246 }
00247
00248
00249 DeleteDerived(&Derived);
00250
00251 return FCS_STATE_IS_NOT_SOLVEABLE;
00252 }
00253
00254 template <class SolvingAlgorithmType>
00255 FCSStateSolvingReturnCodes FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::Resume(int Depth)
00256 {
00257 FCSStateWithLocations* StateWithLocations = m_FirstStateToCheck;
00258
00259 int NumberOfFreeStacks = 0,
00260 NumberOfFreecells = 0,
00261 DerivedIndex, a;
00262
00263 FCSStateSolvingReturnCodes Check;
00264
00265 FCSDerivedStatesList Derived;
00266
00267
00268 while (StateWithLocations != NULL)
00269 {
00270
00271 if (StateWithLocations->m_Visited & FCS_VISITED_VISITED)
00272 goto NextState;
00273
00274
00275 for(a=0;a<m_NumberOfFreecells;a++)
00276 {
00277 if (StateWithLocations->GetFreecellCardNumber(a) == 0)
00278 NumberOfFreecells++;
00279 }
00280
00281
00282 for(a=0;a<m_NumberOfStacks;a++)
00283 {
00284 if (StateWithLocations->GetStackLength(a) == 0)
00285 NumberOfFreeStacks++;
00286 }
00287
00288 if ((NumberOfFreeStacks == m_NumberOfStacks) && (NumberOfFreecells == m_NumberOfFreecells))
00289 {
00290 m_FinalState = StateWithLocations;
00291
00292
00293 DeleteDerived(&Derived);
00294 return FCS_STATE_WAS_SOLVED;
00295 }
00296
00297
00298
00299
00300 Derived.m_NumberOfStates = 0;
00301 for(a=0 ; a < m_TestsOrderNumber; a++)
00302 {
00303 Check = RunTest(m_TestsOrder[a] & FCS_TEST_ORDER_NO_FLAGS_MASK, StateWithLocations,
00304 StateWithLocations->m_Depth, NumberOfFreeStacks,
00305 NumberOfFreecells, &Derived);
00306
00307 if ((Check == FCS_STATE_BEGIN_SUSPEND_PROCESS) ||
00308 (Check == FCS_STATE_EXCEEDS_MAX_NUM_TIMES) ||
00309 (Check == FCS_STATE_SUSPEND_PROCESS))
00310 {
00311
00312 m_FirstStateToCheck = StateWithLocations;
00313
00314 DeleteDerived(&Derived);
00315 return FCS_STATE_SUSPEND_PROCESS;
00316 }
00317 }
00318
00319
00320 for(DerivedIndex = 0; DerivedIndex < Derived.m_NumberOfStates; DerivedIndex++)
00321 m_AStarQueue->Push(Derived.m_States[DerivedIndex], AStarRateState(Derived.m_States[DerivedIndex]));
00322
00323 StateWithLocations->m_Visited |= FCS_VISITED_VISITED;
00324 StateWithLocations->m_VisitIterations = m_NumberOfCheckedStates-1;
00325
00326 NextState:
00327
00328
00329 StateWithLocations = m_AStarQueue->Pop();
00330 }
00331
00332
00333 DeleteDerived(&Derived);
00334
00335 return FCS_STATE_IS_NOT_SOLVEABLE;
00336 }
00337
00338 template <class SolvingAlgorithmType>
00339 void FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::InitAStar(FCSStateWithLocations* StateWithLocations)
00340 {
00341 int NumberOfCards, c;
00342 FCSCard *ThisCard = FCSCard::Create(),
00343 *PreviousCard = FCSCard::Create();
00344 double CardsUnderSequences = 0;
00345
00346 for(int a=0;a<m_NumberOfStacks;a++)
00347 {
00348 NumberOfCards = StateWithLocations->GetStackLength(a);
00349
00350 if (NumberOfCards <= 1)
00351 continue;
00352
00353 c = NumberOfCards-2;
00354 ThisCard->Copy(StateWithLocations->GetStackCard(a, c+1));
00355 PreviousCard->Copy(StateWithLocations->GetStackCard(a, c));
00356
00357 while (IsParentCard(ThisCard, PreviousCard) && (c >= 0))
00358 {
00359 c--;
00360 ThisCard->Copy(PreviousCard);
00361 if (c>=0)
00362 PreviousCard->Copy(StateWithLocations->GetStackCard(a, c));
00363 }
00364 CardsUnderSequences += pow(c+1, FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT);
00365 }
00366
00367 m_AStarInitialCardsUnderSequence = CardsUnderSequences;
00368
00369 delete ThisCard;
00370 delete PreviousCard;
00371 }
00372
00373 template <class SolvingAlgorithmType>
00374 int FCSAStarSolvingAlgorithm<SolvingAlgorithmType>::AStarRateState(FCSStateWithLocations* StateWithLocations)
00375 {
00376 FCSCard *ThisCard = FCSCard::Create(),
00377 *PreviousCard = FCSCard::Create();
00378
00379 int NumberOfCards,
00380 NumberOfCardsInFounds = 0,
00381 NumberOfFreeStacks = 0,
00382 NumberOfFreecells = 0,
00383 a, c;
00384
00385 double CardsUnderSequences = 0,
00386 SequencesOverRenegadeCards = 0,
00387 ReturnValue = 0,
00388 Temp;
00389
00390 for(a=0;a<m_NumberOfStacks;a++)
00391 {
00392 NumberOfCards = StateWithLocations->GetStackLength(a);
00393 if (NumberOfCards == 0)
00394 NumberOfFreeStacks++;
00395
00396 if (NumberOfCards <= 1)
00397 continue;
00398
00399 c = NumberOfCards-2;
00400 ThisCard->Copy(StateWithLocations->GetStackCard(a, c+1));
00401 PreviousCard->Copy(StateWithLocations->GetStackCard(a, c));
00402 while ((c >= 0) && IsParentCard(ThisCard, PreviousCard))
00403 {
00404 c--;
00405 ThisCard->Copy(PreviousCard);
00406 if (c>=0)
00407 PreviousCard->Copy(StateWithLocations->GetStackCard(a, c));
00408 }
00409
00410 CardsUnderSequences += pow(c+1, FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT);
00411
00412 if (c >= 0)
00413 {
00414 SequencesOverRenegadeCards += ((m_IsUnlimitedSequenceMove) ?
00415 1 : pow(NumberOfCards-c-1, FCS_A_STAR_SEQS_OVER_RENEGADE_CARDS_EXPONENT));
00416 }
00417 }
00418
00419 ReturnValue += ((m_AStarInitialCardsUnderSequence - CardsUnderSequences) /
00420 m_AStarInitialCardsUnderSequence) * m_AStarWeights[FCS_A_STAR_WEIGHT_CARDS_UNDER_SEQUENCES];
00421
00422 ReturnValue += (SequencesOverRenegadeCards /
00423 pow(m_NumberOfDecks*52, FCS_A_STAR_SEQS_OVER_RENEGADE_CARDS_EXPONENT) )
00424 * m_AStarWeights[FCS_A_STAR_WEIGHT_SEQS_OVER_RENEGADE_CARDS];
00425
00426 for(a=0;a<m_NumberOfDecks*4;a++)
00427 {
00428 NumberOfCardsInFounds += StateWithLocations->GetFoundation(a);
00429 }
00430
00431 ReturnValue += ((double)NumberOfCardsInFounds/(m_NumberOfDecks*52)) * m_AStarWeights[FCS_A_STAR_WEIGHT_CARDS_OUT];
00432
00433 for(a=0;a<m_NumberOfFreecells;a++)
00434 {
00435 if (StateWithLocations->GetFreecellCardNumber(a) == 0)
00436 NumberOfFreecells++;
00437 }
00438
00439 if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
00440 {
00441 if (m_IsUnlimitedSequenceMove)
00442 {
00443 Temp = (((double)NumberOfFreecells+NumberOfFreeStacks)/(m_NumberOfFreecells+m_NumberOfStacks));
00444 }
00445 else
00446 {
00447 Temp = (((double)((NumberOfFreecells+1)<<NumberOfFreeStacks)) / ((m_NumberOfFreecells+1)<<(m_NumberOfStacks)));
00448 }
00449 }
00450 else
00451 {
00452 if (m_IsUnlimitedSequenceMove)
00453 {
00454 Temp = (((double)NumberOfFreecells)/m_NumberOfFreecells);
00455 }
00456 else
00457 {
00458 Temp = 0;
00459 }
00460 }
00461
00462 ReturnValue += (Temp * m_AStarWeights[FCS_A_STAR_WEIGHT_MAX_SEQUENCE_MOVE]);
00463
00464 if (StateWithLocations->m_Depth <= 20000)
00465 ReturnValue += ((20000 - StateWithLocations->m_Depth)/20000.0) * m_AStarWeights[FCS_A_STAR_WEIGHT_DEPTH];
00466
00467 delete ThisCard;
00468 delete PreviousCard;
00469
00470 return (int)(ReturnValue*INT_MAX);
00471 }
00472
00473 #endif