/// <summary> /// Determine if the system can execute the proposed schedule /// </summary> /// <param name="system"></param> /// <param name="proposedSchedule"></param> /// <returns></returns> public static bool CheckSchedule(SystemClass system, SystemSchedule proposedSchedule) { // Iterate through Subsystem Nodes and set that they havent run foreach (var subsystem in system.Subsystems) subsystem.IsEvaluated = false; // Iterate through constraints foreach (var constraint in system.Constraints) { foreach (Subsystem sub in constraint.Subsystems) { if (!checkSub(sub, proposedSchedule, system.Environment)) return false; if (!CheckConstraints(system, proposedSchedule, constraint)) return false; //if (!constraint.accepts(proposedSchedule)) // return false; } } // Check the remaining Subsystems that aren't included in any Constraints if (!checkSubs(system.Subsystems, proposedSchedule, system.Environment)) return false; return true; }
/// <summary> /// Copy Constructor for the System Class /// </summary> /// <param name="other"></param> public SystemClass(SystemClass other){ SystemClass copy = DeepCopy.Copy<SystemClass>(other); Assets = copy.Assets; Subsystems = copy.Subsystems; Constraints = copy.Constraints; Environment = copy.Environment; ThreadNum = copy.ThreadNum; }
/// <summary> /// PreGenerate all Accesses from all Assets to all Tasks based on a simple Line of Sight model. Access is based on Line of Sight, a spherical Earth and the current ECI /// position of the Asset and the Task.Target.DynamicState /// </summary> /// <param name="system">The system underconsideration</param> /// <param name="tasks"></param> /// <param name="startTime"></param> /// <param name="endTime"></param> /// <param name="stepTime"></param> public static Stack<Access> pregenerateAccessesByAsset(SystemClass system, Stack<Task> tasks, double startTime, double endTime, double stepTime) { Stack<Access> accessesByAsset = new Stack<Access>(); // For all assets... foreach (Asset asset in system.Assets) { // ...for all tasks... foreach (Task task in tasks) { // ...for all time.... for (double accessTime = SimParameters.SimStartSeconds; accessTime <= SimParameters.SimEndSeconds; accessTime += SchedParameters.SimStepSeconds) { // create a new access, or extend the access endTime if this is an update to an existing access bool hasAccess = Utilities.GeometryUtilities.hasLOS(asset.AssetDynamicState.PositionECI(accessTime), task.Target.DynamicState.PositionECI(accessTime)); if (hasAccess) { bool isNewAccess; if (accessesByAsset.Count == 0 || accessTime == SimParameters.SimStartSeconds || accessesByAsset.Peek().Task.Target.Name != task.Target.Name) isNewAccess = true; else isNewAccess = (accessTime - accessesByAsset.Peek().AccessEnd) > SchedParameters.SimStepSeconds; if (isNewAccess) { Access newAccess = new Access(asset, task); newAccess.AccessStart = accessTime; newAccess.AccessEnd = accessTime; accessesByAsset.Push(newAccess); } else // extend the access accessesByAsset.Peek().AccessEnd = accessTime; } } } } return accessesByAsset; }
static int Main(string[] args) { // Begin the Logger ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); log.Info("STARTING HSF RUN"); //Do not delete // Set Defaults var simulationInputFilePath = @"..\..\..\SimulationInput.XML"; var targetDeckFilePath = @"..\..\..\v2.2-300targets.xml"; var modelInputFilePath = @"..\..\..\DSAC_Static.xml"; bool simulationSet = false, targetSet = false, modelSet = false; // Get the input filenames int i = 0; foreach(var input in args) { i++; switch (input) { case "-s": simulationInputFilePath = args[i]; simulationSet = true; break; case "-t": targetDeckFilePath = args[i]; targetSet = true; break; case "-m": modelInputFilePath = args[i]; modelSet = true; break; } } ///add usage statement if (!simulationSet) { log.Info("Using Default Simulation File"); } if (!targetSet) { log.Info("Using Default Target File"); } if (!modelSet) { log.Info("Using Default Model File"); } // Initialize Output File var outputFileName = string.Format("output-{0:yyyy-MM-dd}-*", DateTime.Now); var outputPath = @"C:\HorizonLog\"; var txt = ".txt"; string[] fileNames = System.IO.Directory.GetFiles(outputPath, outputFileName, System.IO.SearchOption.TopDirectoryOnly); double number = 0; foreach (var fileName in fileNames) { char version = fileName[fileName.Length - txt.Length-1]; if(number < Char.GetNumericValue(version)) number = Char.GetNumericValue(version); } number++; outputFileName = outputFileName.Remove(outputFileName.Length - 1) + number; outputPath += outputFileName + txt; // Find the main input node from the XML input files XmlNode evaluatorNode = XmlParser.ParseSimulationInput(simulationInputFilePath); // Load the target deck into the targets list from the XML target deck input file Stack<Task> systemTasks = new Stack<Task>(); bool targetsLoaded = Task.loadTargetsIntoTaskList(XmlParser.GetTargetNode(targetDeckFilePath), systemTasks); if (!targetsLoaded) { return 1; } // Find the main model node from the XML model input file var modelInputXMLNode = XmlParser.GetModelNode(modelInputFilePath); // Load the environment. First check if there is an ENVIRONMENT XMLNode in the input file Universe SystemUniverse = null; //Create singleton dependency dictionary Dependency dependencies = Dependency.Instance; // Initialize List to hold assets and subsystem nodes List<Asset> assetList = new List<Asset>(); List<Subsystem> subList = new List<Subsystem>(); // Maps used to set up preceeding nodes Dictionary<ISubsystem, XmlNode> subsystemXMLNodeMap = new Dictionary<ISubsystem, XmlNode>(); Dictionary<string, Subsystem> subsystemMap = new Dictionary<string, Subsystem>(); List<KeyValuePair<string, string>> dependencyMap = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> dependencyFcnMap = new List<KeyValuePair<string, string>>(); // Dictionary<string, ScriptedSubsystem> scriptedSubNames = new Dictionary<string, ScriptedSubsystem>(); // Create Constraint list List<Constraint> constraintsList = new List<Constraint>(); //Create Lists to hold all the initial condition and dependency nodes to be parsed later List<XmlNode> ICNodes = new List<XmlNode>(); List<XmlNode> DepNodes = new List<XmlNode>(); SystemState initialSysState = new SystemState(); // Set up Subsystem Nodes, first loop through the assets in the XML model input file foreach (XmlNode modelChildNode in modelInputXMLNode.ChildNodes) { if (modelChildNode.Name.Equals("ENVIRONMENT")) { // Create the Environment based on the XMLNode SystemUniverse = new Universe(modelChildNode); } if (modelChildNode.Name.Equals("ASSET")) { Asset asset = new Asset(modelChildNode); assetList.Add(asset); // Loop through all the of the ChildNodess for this Asset foreach (XmlNode childNode in modelChildNode.ChildNodes) { // Get the current Subsystem XML Node, and create it using the SubsystemFactory if (childNode.Name.Equals("SUBSYSTEM")) { //is this how we want to do this? // Check if the type of the Subsystem is scripted, networked, or other string subName = SubsystemFactory.GetSubsystem(childNode, dependencies, asset, subsystemMap); foreach (XmlNode ICorDepNode in childNode.ChildNodes) { if(ICorDepNode.Name.Equals("IC")) ICNodes.Add(ICorDepNode); if (ICorDepNode.Name.Equals("DEPENDENCY")) { string depSubName = "", depFunc = ""; depSubName = Subsystem.parseNameFromXmlNode(ICorDepNode, asset.Name) ; dependencyMap.Add(new KeyValuePair<string, string>(subName, depSubName)); if (ICorDepNode.Attributes["fcnName"] != null) { depFunc = ICorDepNode.Attributes["fcnName"].Value.ToString(); dependencyFcnMap.Add(new KeyValuePair<string, string>(subName, depFunc)); } } } } //Create a new Constraint if (childNode.Name.Equals("CONSTRAINT")) { constraintsList.Add(ConstraintFactory.GetConstraint(childNode, subsystemMap, asset)); } } if (ICNodes.Count > 0) initialSysState.Add(SystemState.setInitialSystemState(ICNodes, asset)); ICNodes.Clear(); } } if (SystemUniverse == null) SystemUniverse = new Universe(); foreach (KeyValuePair<string, Subsystem> sub in subsystemMap) { if(!sub.Value.GetType().Equals(typeof(ScriptedSubsystem)))//let the scripted subsystems add their own dependency collector sub.Value.AddDependencyCollector(); subList.Add(sub.Value); } log.Info("Subsystems and Constraints Loaded"); //Add all the dependent subsystems to the dependent subsystem list of the subsystems foreach (KeyValuePair<string, string> depSubPair in dependencyMap) { Subsystem subToAddDep, depSub; subsystemMap.TryGetValue(depSubPair.Key, out subToAddDep); subsystemMap.TryGetValue(depSubPair.Value, out depSub); subToAddDep.DependentSubsystems.Add(depSub); } //give the dependency functions to all the subsytems that need them foreach (KeyValuePair<string, string> depFunc in dependencyFcnMap) { Subsystem subToAddDep; subsystemMap.TryGetValue(depFunc.Key, out subToAddDep); subToAddDep.SubsystemDependencyFunctions.Add(depFunc.Value, dependencies.GetDependencyFunc(depFunc.Value)); } log.Info("Dependencies Loaded"); SystemClass simSystem = new SystemClass(assetList, subList, constraintsList, SystemUniverse); if (simSystem.CheckForCircularDependencies()) throw new NotFiniteNumberException("System has circular dependencies! Please correct then try again."); Evaluator schedEvaluator = EvaluatorFactory.GetEvaluator(evaluatorNode, dependencies); Scheduler scheduler = new Scheduler(schedEvaluator); List<SystemSchedule> schedules = scheduler.GenerateSchedules(simSystem, systemTasks, initialSysState); // Evaluate the schedules and set their values foreach (SystemSchedule systemSchedule in schedules) { systemSchedule.ScheduleValue = schedEvaluator.Evaluate(systemSchedule); bool canExtendUntilEnd = true; // Extend the subsystem states to the end of the simulation foreach (var subsystem in simSystem.Subsystems) { if(systemSchedule.AllStates.Events.Count >0) if (!subsystem.CanExtend(systemSchedule.AllStates.Events.Peek(), simSystem.Environment, SimParameters.SimEndSeconds)) log.Error("Cannot Extend " + subsystem.Name + " to end of simulation"); } } // Sort the sysScheds by their values schedules.Sort((x, y) => x.ScheduleValue.CompareTo(y.ScheduleValue)); schedules.Reverse(); double maxSched = schedules[0].ScheduleValue; i = 0; //Morgan's Way using (StreamWriter sw = File.CreateText(outputPath)) { foreach (SystemSchedule sched in schedules) { sw.WriteLine("Schedule Number: " + i + "Schedule Value: " + schedules[i].ScheduleValue); foreach (var eit in sched.AllStates.Events) { if (i < 5)//just compare the first 5 schedules for now { sw.WriteLine(eit.ToString()); } } i++; } log.Info("Max Schedule Value: " + maxSched); } // Mehiel's way string stateDataFilePath = @"C:\HorizonLog\" + string.Format("output-{0:yyyy-MM-dd-hh-mm-ss}", DateTime.Now); SystemSchedule.WriteSchedule(schedules[0], stateDataFilePath); var csv = new StringBuilder(); csv.Clear(); foreach (var asset in simSystem.Assets) { File.WriteAllText(@"..\..\..\" + asset.Name + "_dynamicStateData.csv", asset.AssetDynamicState.ToString()); } return 0; // Console.ReadKey(); }
/// <summary> /// Generate schedules by adding a new event to the end of existing ones /// Create a new system schedule list by adding each of the new Task commands for the Assets onto each of the old schedules /// </summary> /// <param name="system"></param> /// <param name="tasks"></param> /// <param name="initialStateList"></param> /// <returns></returns> public virtual List<SystemSchedule> GenerateSchedules(SystemClass system, Stack<Task> tasks, SystemState initialStateList) { log.Info("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) { log.Info("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 log.Info("Done pregenerating accesses"); } // otherwise generate an exhaustive list of possibilities for assetTaskList else { log.Info("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)); allAccesses.Push(new Access(asset, null)); exhaustive.Push(allAccesses); allAccesses.Clear(); } scheduleCombos = (Stack<Stack<Access>>)exhaustive.CartesianProduct(); log.Info("Done generating exhaustive task combinations"); } /// 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(); int i = 1; List<SystemSchedule> potentialSystemSchedules = new List<SystemSchedule>(); List<SystemSchedule> systemCanPerformList = new List<SystemSchedule>(); for (double currentTime = _startTime; currentTime < _endTime; currentTime += _stepLength) { log.Info("Simulation Time " + 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) { log.Info("Cropping Schedules..."); CropSchedules(systemSchedules, ScheduleEvaluator, emptySchedule); systemSchedules.Add(emptySchedule); } // Generate an exhaustive list of new tasks possible from the combinations of Assets and Tasks //TODO: Parallelize this. int k = 0; foreach (var oldSystemSchedule in systemSchedules) { potentialSystemSchedules.Add(new SystemSchedule( new StateHistory(oldSystemSchedule.AllStates))); foreach (var newAccessStack in scheduleCombos) { k++; if (oldSystemSchedule.CanAddTasks(newAccessStack, currentTime)) { var CopySchedule = new StateHistory(oldSystemSchedule.AllStates); potentialSystemSchedules.Add(new SystemSchedule(CopySchedule, newAccessStack, currentTime)); // oldSched = new SystemSchedule(CopySchedule); } } } int numSched = 0; foreach (var potentialSchedule in potentialSystemSchedules) { if (Checker.CheckSchedule(system, potentialSchedule)) systemCanPerformList.Add(potentialSchedule); numSched++; } foreach (SystemSchedule systemSchedule in systemCanPerformList) systemSchedule.ScheduleValue = ScheduleEvaluator.Evaluate(systemSchedule); systemCanPerformList.Sort((x, y) => x.ScheduleValue.CompareTo(y.ScheduleValue)); systemCanPerformList.Reverse(); // Merge old and new systemSchedules var oldSystemCanPerfrom = new List<SystemSchedule>(systemCanPerformList); systemSchedules.InsertRange(0, oldSystemCanPerfrom);//<--This was potentialSystemSchedules potentialSystemSchedules.Clear(); systemCanPerformList.Clear(); // Print completion percentage in command window Console.WriteLine("Scheduler Status: {0}% done; {1} schedules generated.", 100 * currentTime / _endTime, systemSchedules.Count); } return systemSchedules; }
/// <summary> /// Return all possible combinations of performing Tasks by Asset at current simulation time /// </summary> /// <param name="currentAccessForAllAssets"></param> /// <param name="system"></param> /// <param name="currentTime"></param> /// <returns></returns> public static Stack<Stack<Access>> GenerateExhaustiveSystemSchedules(Stack<Access> currentAccessForAllAssets, SystemClass system, double currentTime) { // A stack of accesses stacked by asset Stack<Stack<Access>> currentAccessesByAsset = new Stack<Stack<Access>>(); foreach (Asset asset in system.Assets) currentAccessesByAsset.Push(Access.getCurrentAccessesForAsset(currentAccessForAllAssets, asset, currentTime)); IEnumerable<IEnumerable<Access>> allScheduleCombos = currentAccessesByAsset.CartesianProduct(); Stack<Stack<Access>> allOfThem = new Stack<Stack<Access>>(); foreach (var accessStack in allScheduleCombos) { Stack<Access> someOfThem = new Stack<Access>(accessStack); allOfThem.Push(someOfThem); } return allOfThem; }
/// <summary> /// Check if the constraint has been violated in progressing the state of the system /// </summary> /// <param name="system"></param> /// <param name="proposedSchedule"></param> /// <param name="constraint"></param> /// <returns></returns> private static bool CheckConstraints(SystemClass system, SystemSchedule proposedSchedule, Constraint constraint) { if (!constraint.Accepts(proposedSchedule.AllStates.GetLastState())) { // TODO: Change this to logger // HSFLogger.Log(new HSFLogData(constraint, subsystem, task, value, time)); Console.WriteLine("Constraint Failed"); return false; } return true; }