Beispiel #1
0
        public virtual List <SystemSchedule> GenerateSchedules(SystemClass system, Stack <MissionElements.Task> tasks, SystemState initialStateList, Evaluator scheduleEvaluator)
        {
            //system.setThreadNum(1);
            //DWORD startTickCount = GetTickCount();
            //accumSchedTimeMs = 0;

            // get the global dependencies object
            //Dependencies dependencies = new Dependencies().Instance();

            Console.WriteLine("SIMULATING... ");
            // Create empty systemSchedule with initial state set
            SystemSchedule        emptySchedule   = new SystemSchedule(initialStateList);
            List <SystemSchedule> systemSchedules = new List <SystemSchedule>();

            systemSchedules.Add(emptySchedule);

            // if all asset position types are not dynamic types, can pregenerate accesses for the simulation
            bool canPregenAccess = true;

            foreach (var asset in system.Assets)
            {
                if (asset.AssetDynamicState != null)
                {
                    canPregenAccess &= asset.AssetDynamicState.Type != HSFUniverse.DynamicStateType.DYNAMIC_ECI && asset.AssetDynamicState.Type != HSFUniverse.DynamicStateType.DYNAMIC_LLA;
                }
                else
                {
                    canPregenAccess = false;
                }
            }

            // if accesses can be pregenerated, do it now
            Stack <Access>          preGeneratedAccesses = new Stack <Access>();
            Stack <Stack <Access> > scheduleCombos       = new Stack <Stack <Access> >();

            if (canPregenAccess)
            {
                Console.Write("Pregenerating Accesses...");
                //DWORD startPregenTickCount = GetTickCount();

                preGeneratedAccesses = Access.pregenerateAccessesByAsset(system, tasks, _startTime, _endTime, _stepLength);
                //DWORD endPregenTickCount = GetTickCount();
                //pregenTimeMs = endPregenTickCount - startPregenTickCount;
                //writeAccessReport(access_pregen, tasks); - TODO:  Finish this code - EAM
                Console.WriteLine(" DONE!");
            }
            // otherwise generate an exhaustive list of possibilities for assetTaskList
            else
            {
                Console.Write("Generating Exhaustive Task Combinations... ");
                Stack <Stack <Access> > exhaustive  = new Stack <Stack <Access> >();
                Stack <Access>          allAccesses = new Stack <Access>(tasks.Count);

                foreach (var asset in system.Assets)
                {
                    foreach (var task in tasks)
                    {
                        allAccesses.Push(new Access(asset, task));
                    }

                    exhaustive.Push(allAccesses);
                    allAccesses.Clear();
                }

                scheduleCombos = (Stack <Stack <Access> >)exhaustive.CartesianProduct();
                Console.WriteLine(" DONE!");
            }

            /// \todo TODO: Delete (or never create in the first place) schedules with inconsistent asset tasks (because of asset dependencies)

            // Find the next timestep for the simulation
            //DWORD startSchedTickCount = GetTickCount();

            for (double currentTime = _startTime; currentTime < _endTime; currentTime += _stepLength)
            {
                Console.WriteLine(currentTime);
                // if accesses are pregenerated, look up the access information and update assetTaskList
                if (canPregenAccess)
                {
                    scheduleCombos = GenerateExhaustiveSystemSchedules(preGeneratedAccesses, system, currentTime);
                }

                // Check if it's necessary to crop the systemSchedule list to a more managable number
                if (systemSchedules.Count > _maxNumSchedules)
                {
                    CropSchedules(systemSchedules, scheduleEvaluator, emptySchedule);
                }

                // Create a new system schedule list by adding each of the new Task commands for the Assets onto each of the old schedules
                // Start timing
                // Generate an exhaustive list of new tasks possible from the combinations of Assets and Tasks
                //TODO: Parallelize this.

                List <SystemSchedule> potentialSystemSchedules = new List <SystemSchedule>();

                foreach (var oldSystemSchedule in systemSchedules)
                {
                    foreach (var newAccessStack in scheduleCombos)
                    {
                        if (oldSystemSchedule.CanAddTasks(newAccessStack, currentTime))
                        {
                            SystemSchedule newSched = new SystemSchedule(oldSystemSchedule, newAccessStack, currentTime);
                            potentialSystemSchedules.Add(newSched);
                        }
                    }
                    potentialSystemSchedules.Add(new SystemSchedule(oldSystemSchedule));
                    //deep copy
                }

                // TODO EAM: Remove this and only add new SystemScedule if canAddTasks and CanPerform are both true.  That way we don't need to delete SystemSchedules after the fact below.
                List <SystemSchedule> systemCanPerformList = new List <SystemSchedule>();
                //for (list<systemSchedule*>::iterator newSchedIt = newSysScheds.begin(); newSchedIt != newSysScheds.end(); newSchedIt++)
                // The parallel version
                // Should we use a Partitioner?
                // Need to test this...

                /*
                 * Stopwatch stopWatch = new Stopwatch();
                 * stopWatch.Start();
                 * // The Scheduler has to call the CanPerform for a SystemClass, SystemSchedule combo.  The SystemClass
                 * Parallel.ForEach(potentialSystemSchedules, (currentSchedule) =>
                 * {
                 *  // dependencies.updateStates(newSchedule.getEndStates());
                 *  if (Checker.CheckSchedule(system, currentSchedule))
                 *      systemCanPerformList.Add(currentSchedule);
                 *  Console.WriteLine("Processing {0} on thread {1}", currentSchedule.ToString(), Thread.CurrentThread.ManagedThreadId);
                 * });
                 * stopWatch.Stop();
                 *
                 * TimeSpan ts = stopWatch.Elapsed;
                 * // Format and display the TimeSpan value.
                 * string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                 *  ts.Hours, ts.Minutes, ts.Seconds,
                 *  ts.Milliseconds / 10);
                 * Console.WriteLine("Parallel Scheduler RunTime: " + elapsedTime);
                 */
                foreach (var potentialSchedule in potentialSystemSchedules)
                {
                    if (Checker.CheckSchedule(system, potentialSchedule))
                    {
                        systemCanPerformList.Add(potentialSchedule);
                    }
                    //dependencies.updateStates(newSchedule.getEndStates());
                    //systemCanPerformList.Push(system.canPerform(potentialSchedule));
                }

                // End timing

                /*
                 * // delete systemSchedules (and corresponding lower level classes) that are not possible
                 * list<systemSchedule*>::iterator eraseIt = newSysScheds.begin();
                 * for (vector<bool>::iterator successIt = systemCanPerformList.begin(); successIt != systemCanPerformList.end(); successIt++)
                 * {
                 *  if (*successIt) { eraseIt++; }
                 *  else {
                 *      delete* eraseIt;
                 *      eraseIt = newSysScheds.erase(eraseIt);
                 *  }
                 * }
                 */

                // Merge old and new systemSchedules
                systemSchedules.InsertRange(0, systemCanPerformList);//<--This was potentialSystemSchedules
                potentialSystemSchedules.Clear();
                // Print completion percentage in command window
                Console.Write("Scheduler Status: {0} done; {1} schedules generated.", 100 * currentTime / _endTime, systemSchedules.Count);
            }


            if (systemSchedules.Count > _maxNumSchedules)
            {
                CropSchedules(systemSchedules, scheduleEvaluator, emptySchedule);
            }

            // THIS GOES AWAY IF CAN EXTEND HAPPENS IN THE SUBSYSTEM - EAM
            // extend all schedules to the end of the simulation

            /*
             * foreach (var schedule in systemSchedules)
             * {
             *  bool canExtendUntilEnd = true;
             *  // Iterate through Subsystem Nodes and set that they havent run
             *  foreach (var subsystem in system.Subsystems)
             *      subsystem.IsEvaluated = false;
             *
             *  int subAssetNum;
             *  foreach (var subsystem in system.Subsystems)
             *      canExtendUntilEnd &= subsystem.canPerform(schedule.getSubsystemNewState(subsystem.Asset), schedule.getSubsytemNewTask(subsystem.Asset), system.Environment, _endTime, true);
             *
             *  // Iterate through constraints
             *  foreach (var constraint in system.Constraints)
             *  {
             *      canExtendUntilEnd &= constraint.Accepts(schedule);
             *  }
             *  //                for (vector <const Constraint*>::const_iterator constraintIt = system.getConstraints().begin(); constraintIt != system.getConstraints().end(); constraintIt++)
             *  //            canExtendUntilEnd &= (*constraintIt)->accepts(*schedIt);
             *  if (!canExtendUntilEnd) {
             *      //delete *schedIt;
             *      Console.WriteLine("Schedule may not be valid");
             *  }
             * }
             */

            //DWORD endSchedTickCount = GetTickCount();
            //schedTimeMs = endSchedTickCount - startSchedTickCount;

            //DWORD endTickCount = GetTickCount();
            //totalTimeMs = endTickCount - startTickCount;

            return(systemSchedules);
        }