Esempio n. 1
0
 public SearchResults(long numLeafsCreated, long numSolutionsFound,
                      InvasionSolution defaultSolution,
                      InvasionSolution optimizedSolution)
 {
     SearchTimeSeconds = -1;
     NumLeafsCreated   = numLeafsCreated;
     NumSolutionsFound = numSolutionsFound;
     DefaultSolution   = defaultSolution;
     OptimizedSolution = optimizedSolution;
 }
Esempio n. 2
0
        /*
         * Driver for search logic.
         * i) Check if the chosen state is solved, and if so update solution records accordiningly
         * ii) If not solved, check for preliminary qualities that would disqualify this sub problem from being searched
         * iii) If not disqualified, run a recursive division on the invading army into all possible invasion groupings
         *      Each combination found will be added as a new leaf on the tree
         */
        public void Search(SearchState chosenState, bool keepArmyTogether)
        {
            if (chosenState.IsSolved)
            {
                mNumLeafsCreated++;

                #region SolutionFound
                // Check if the solution is relevant depending on which optimizations are being used and solution quality
                bool updateSolution = false;
                bool recordSolution = false;

                int numStepsInInvasion = chosenState.Depth;

                if (mBestSolution == null) // havent found a solution yet
                {
                    recordSolution = updateSolution = true;
                    if (mIsOptimized)
                    {
                        // only accept solutions that occur in as many turns as the new solution
                        mMaxDepthOfTree = numStepsInInvasion;
                    }
                }
                else if (numStepsInInvasion < mBestSolutionDepth)  // found a quicker invasion strategy
                {
                    recordSolution = updateSolution = true;
                    mBestSolution  = null;
                    // reset solution tracking
                    if (mIsOptimized)
                    {
                        mNumSolutionsFound = 0;
                        mMaxDepthOfTree    = numStepsInInvasion;
                    }
                }
                else if (mBestSolutionDepth == numStepsInInvasion) // occurs in the same number of turns as previous solutions
                {
                    recordSolution = true;
                    if (chosenState.Prob.InvadingArmy.CalculateArmyValue() > mBestSolutionArmyValue)
                    {
                        updateSolution = true;
                    }
                }
                else // worse quality of solution
                {
                    recordSolution = !mIsOptimized;
                }

                if (recordSolution)
                {
                    mNumSolutionsFound++;
                }

                // Create and store new solution
                if (updateSolution)
                {
                    mBestSolution          = ToSolution(chosenState, mInitialArmy, mInitialNation);
                    mBestSolutionDepth     = numStepsInInvasion;
                    mBestSolutionArmyValue = chosenState.Prob.InvadingArmy.CalculateArmyValue();
                }
                #endregion
            }
            else // sub problem is not solved. Check if sub problem can be divided
            {
                if (mBestSolution == null) // record partial solutions until an actual solution is found
                {
                    if (mBestPartialSolution == null)
                    {
                        mBestPartialSolution      = chosenState;
                        mBestPartialSolutionValue = chosenState.Prob.ProblemValue;
                    }
                    else
                    {
                        // only update partial solution if it was able to take more cities than the previous, regardless of better army value
                        if (chosenState.Prob.NationBlueprint.NumCitiesRemaining < mBestPartialSolution.Prob.NationBlueprint.NumCitiesRemaining)
                        {
                            float probValue = chosenState.Prob.ProblemValue;
                            if (probValue < mBestPartialSolutionValue)
                            {
                                mBestPartialSolution      = chosenState;
                                mBestPartialSolutionValue = probValue;
                            }
                        }
                    }
                }

                // check for disqualifying features of invasion state
                bool validState = true;
                if (chosenState.ParentProblem != null)
                {
                    if (chosenState.ParentProblem.StateValue == chosenState.StateValue) // army did not heal nor was a city taken
                    {
                        // do nothing, this state didn't progress the invasion
                        validState = false;
                    }
                }
                // took more turns to complete than our max turn limit
                if (mMaxDepthOfTree != -1 && mIsOptimized && chosenState.Depth >= mMaxDepthOfTree)
                {
                    validState = false;
                }

                // valid subproblem. Add all new leafs possible from this state
                if (validState)
                {
                    List <SearchState> subProblems = Fdiv(chosenState, keepArmyTogether);
                    mNumLeafsCreated += subProblems.Count;
                    foreach (SearchState subProblem in subProblems)
                    {
                        mOpenLeafs.AddLast(subProblem);
                    }
                }
                else
                {
                    mNumLeafsCreated++;
                }
            }
        }
Esempio n. 3
0
        public SearchResults SearchForSolutions(ArmyBlueprint attackers, NationBlueprint defenders, bool optimize)
        {
            mInitialArmy   = attackers;
            mInitialNation = defenders;
            mIsOptimized   = true; /* = optimize; Replace after data collection*/

            // Initialize start variables and start invasion search
            SearchState initialState = new SearchState(attackers, defenders, 0, null, null);

            mOpenLeafs.Clear();
            // orrient the nations layout relative to the army. TODO: allow for dynamic invasion direction
            initialState.Prob.NationBlueprint.BeginInvasion(Vector2.right);

            // Do the default search keeping the units together
            mOpenLeafs.AddLast(initialState);
            mPruneSolutions = true;                    // only care about the best solution with army grouped up. Only record
            mMaxDepthOfTree = mBestSolutionDepth = -1; // max depth = -1 until a solution is found creating a limit to depth

            // Search for solutions with linear invasion strategy
            while (mOpenLeafs.Count > 0)
            {
                SearchState pop = mOpenLeafs.Last.Value;
                mOpenLeafs.RemoveLast();
                Search(pop, true);
            }
            // record default invasion stats
            InvasionSolution linearSolution = null;

            if (mBestSolution == null) // no solution was found
            {
                // record the best result possible
                linearSolution = ToSolution(mBestPartialSolution, mInitialArmy, mInitialNation);
            }
            else
            {
                linearSolution = mBestSolution;
            }

            int bestLinearDepth = linearSolution != null ? mBestSolutionDepth : -1;

            // update the max depth of the optimized search to be the depth of the default time
            mMaxDepthOfTree = bestLinearDepth;
            //Debug.Log("Best Case Group Scenario took " + mMaxDepthOfTree + " turns to complete, needing " + (mMaxDepthOfTree - initialState.Prob.NationBlueprint.NumCitiesRemaining) + " turns to heal");
            // reset search variables for the optimized search
            mPruneSolutions = optimize;
            mOpenLeafs.Clear();
            mBestSolution        = null;
            mBestPartialSolution = null;

            mOpenLeafs.AddLast(initialState);
            // search for parallel attack strategy solutions
            while (mOpenLeafs.Count > 0)
            {
                SearchState pop = mOpenLeafs.Last.Value;
                mOpenLeafs.RemoveLast();
                Search(pop, false);
            }


            // Record optimized Solution
            InvasionSolution parallelSolution = null;

            if (mBestSolution == null)
            {
                parallelSolution = ToSolution(mBestPartialSolution, mInitialArmy, mInitialNation);
            }
            else
            {
                parallelSolution = mBestSolution;
            }

            int bestOptimizedDepth = parallelSolution != null ? mBestSolutionDepth : -1;

            return(new SearchResults(mNumLeafsCreated, mNumSolutionsFound,
                                     linearSolution, parallelSolution));
        }