Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

FCSAStarSolvingAlgorithm.h

Go to the documentation of this file.
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     // Set the default A* weigths
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     //Initialize the priotity queue of the A* scan
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         // Normalize the A* Weights, so the sum of all of them would be 1.
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     //initializes part of the StateWithLocations
00164     InitSolve(StateWithLocations);
00165 
00166     InitAStar(StateWithLocations);
00167 
00168     // Initialize the first element to indicate it is the first
00169     StateWithLocations->m_Parent = NULL;
00170     StateWithLocations->m_MovesToParent = NULL;
00171     StateWithLocations->m_Depth = 0;
00172 
00173     // Continue as long as there are states in the queue or priority queue.
00174     while (StateWithLocations != NULL)
00175     {
00176         if (StateWithLocations->m_Visited & FCS_VISITED_VISITED)
00177             goto NextState;
00178 
00179         // Count the freecells
00180         NumberOfFreecells = 0;
00181         for(a=0;a<m_NumberOfFreecells;a++)
00182         {
00183             if (StateWithLocations->GetFreecellCardNumber(a) == 0)
00184                 NumberOfFreecells++;
00185         }
00186 
00187         // Count the number of unoccupied stacks
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             // Free the memory that was allocated by derived.
00203             DeleteDerived(&Derived);
00204             return FCS_STATE_WAS_SOLVED;
00205         }
00206 
00207         // Increase the number of iterations by one . This
00208         // is meant to make sure we do not entered this state before which
00209         // will lead to a false iterations count.
00210         m_NumberOfCheckedStates++;
00211 
00212         // Do all the tests at one go, because that the way it should be
00213         // done for BFS and A*
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                 // Save the current position in the scan
00227                 m_FirstStateToCheck = StateWithLocations;
00228 
00229                 DeleteDerived(&Derived);
00230                 return FCS_STATE_SUSPEND_PROCESS;
00231             }
00232         }
00233 
00234         // Insert all the derived states into the PQ or Queue
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         //  Extract the next item in the queue/priority queue.
00245         StateWithLocations = m_AStarQueue->Pop();
00246     }
00247 
00248     // Free the memory that was allocated by derived.
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     // Continue as long as there are states in the queue or priority queue.
00268     while (StateWithLocations != NULL)
00269     {
00270         //this is what the code would be without the optimize stuff
00271         if (StateWithLocations->m_Visited & FCS_VISITED_VISITED)
00272             goto NextState;
00273 
00274         // Count the free-cells
00275         for(a=0;a<m_NumberOfFreecells;a++)
00276         {
00277             if (StateWithLocations->GetFreecellCardNumber(a) == 0)
00278                 NumberOfFreecells++;
00279         }
00280 
00281         // Count the number of unoccupied stacks
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             // Free the memory that was allocated by derived.
00293             DeleteDerived(&Derived);
00294             return FCS_STATE_WAS_SOLVED;
00295         }
00296 
00297         // Do all the tests at one go, because that the way it should be
00298         //  done for BFS and A*
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                 // Save the current position in the scan
00312                 m_FirstStateToCheck = StateWithLocations;
00313 
00314                 DeleteDerived(&Derived);
00315                 return FCS_STATE_SUSPEND_PROCESS;
00316             }
00317         }
00318 
00319         // Insert all the derived states into the PQ or Queue
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         //  Extract the next item in the queue/priority queue.
00328         // It is an A* scan
00329         StateWithLocations = m_AStarQueue->Pop();
00330     }
00331 
00332     // Free the memory that was allocated by derived.
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

Generated on Sat Nov 5 11:20:15 2005 for Cpp Freecell Solver by  doxygen 1.4.4