public void ShouldCreateCorrectDataContainer()
        {
            //Arrange
            var firstJob = new Job(1, 100, null, 1, 10);
            var secondJob = new Job(2, 100, new List<int> {1}, 1, 10);
            var thirdJob = new Job(3, 200, new List<int>{1, 2}, 1, 20);
            var jobs = new List<Job> { firstJob, secondJob, thirdJob };
            var resource1 = new Resource(1, 10);
            var resource2 = new Resource(2, 30);
            var resources = new List<Resource> { resource1, resource2 };
            var dependencies = new List<double[]> { new[] {0.7, 1.2} , new[] {1.4, 0.8}, new[] {1.0,2.0} };
            //Act
            var container = new SchedulingDataContainer(resources, jobs, dependencies);
            //Assert
            AreEqual(container.Jobs, jobs);
            AreEqual(container.Resources, resources);

            AreEqual(container.Jobs[0].Number, 1);
            AreEqual(container.Jobs[0].FullWorkVolume, 100);
            AreEqual(container.Jobs[0].MinimumIntensity, 1);
            AreEqual(container.Jobs[0].MaximumIntensity, 10);
            AreEqual(container.Jobs[0].ResourceDependencies.Count, 2);
            AreEqual(container.Jobs[0].PrecedingJobs.Count, 0);
            AreEqual(container.Jobs[0].NumberOfDependants, 2);
            AreEqual(container.Jobs[0].ResourceDependencies[0].Job, firstJob);
            AreEqual(container.Jobs[0].ResourceDependencies[0].Resource, resource1);
            AreEqual(container.Jobs[0].ResourceDependencies[0].Value, 0.7);
            AreEqual(container.Jobs[0].ResourceDependencies[1].Job, firstJob);
            AreEqual(container.Jobs[0].ResourceDependencies[1].Resource, resource2);
            AreEqual(container.Jobs[0].ResourceDependencies[1].Value, 1.2);

            AreEqual(container.Jobs[1].Number, 2);
            AreEqual(container.Jobs[1].PrecedingJobs.Count, 1);
            AreEqual(container.Jobs[1].PrecedingJobs[0], firstJob);
            AreEqual(container.Jobs[1].NumberOfDependants, 1);
            AreEqual(container.Jobs[1].ResourceDependencies.Count, 2);
            AreEqual(container.Jobs[1].ResourceDependencies[0].Job, secondJob);
            AreEqual(container.Jobs[1].ResourceDependencies[0].Resource, resource1);
            AreEqual(container.Jobs[1].ResourceDependencies[0].Value, 1.4);
            AreEqual(container.Jobs[1].ResourceDependencies[1].Job, secondJob);
            AreEqual(container.Jobs[1].ResourceDependencies[1].Resource, resource2);
            AreEqual(container.Jobs[1].ResourceDependencies[1].Value, 0.8);

            AreEqual(container.Jobs[2].Number, 3);
            AreEqual(container.Jobs[2].PrecedingJobs.Count, 2);
            AreEqual(container.Jobs[2].PrecedingJobs[0], firstJob);
            AreEqual(container.Jobs[2].PrecedingJobs[1], secondJob);
            AreEqual(container.Jobs[2].ResourceDependencies.Count, 2);
            AreEqual(container.Jobs[2].ResourceDependencies[0].Job, thirdJob);
            AreEqual(container.Jobs[2].ResourceDependencies[0].Resource, resource1);
            AreEqual(container.Jobs[2].ResourceDependencies[0].Value, 1.0);
            AreEqual(container.Jobs[2].ResourceDependencies[1].Job, thirdJob);
            AreEqual(container.Jobs[2].ResourceDependencies[1].Resource, resource2);
            AreEqual(container.Jobs[2].ResourceDependencies[1].Value, 2.0);
        }
Exemple #2
0
        public List<PlanStep> GetBasePlan(IEnumerable<Resource> resources, IEnumerable<Job> jobs, IEnumerable<double[]> dependencyValues)
        {
            //Initialization
            var dataContainer = new SchedulingDataContainer(resources, jobs, dependencyValues);
            var plan = new List<PlanStep>();
            var unfinishedJobs = new LinkedList<Job>(dataContainer.Jobs);
            var resArr = resources.ToArray();

            var resourcesForStep = new Resource[resArr.Length];
            int stepNumber = 1;
            //Repeat while we have unfinished jobs
            while (unfinishedJobs.Count> 0)
            {
                //Set up resources per step
                for (int r = 0; r < resArr.Length; r++) resourcesForStep[r] = resArr[r].DeepCopy();

                //Select jobs we can plan
                var jobsPossibleToExecute = unfinishedJobs.Where(j => j.CanStart()).ToList();
                //Put to heap with greed comparer
                var jobHeap = new Heap<Job>(jobsPossibleToExecute, jobsPossibleToExecute.Count(), new JobGreedyComparer());
                var jobsForStep = new List<RunningJob>();
                do
                {
                    //Take first
                    var jobToExecute = jobHeap.PopRoot();
                    //Check we can plan it
                    //and compute intensity
                    var maxIntensity = CalcMaxPossibleIntensity(jobToExecute, resourcesForStep);
                    if (maxIntensity > 0)
                    {
                        //Start job
                        jobToExecute.State = JobState.Started;
                        //calc spended resources, remaining resources and time
                        foreach (var resource in resourcesForStep)
                        {
                            var jobResourceDependency = jobToExecute.ResourceDependencies.FirstOrDefault(d => d.Resource.Number == resource.Number);
                            if (jobResourceDependency != null)
                                resource.Value -= jobResourceDependency.Value*maxIntensity;
                        }

                        var time = jobToExecute.RemainingVolume/maxIntensity;
                        jobsForStep.Add(new RunningJob(jobToExecute, maxIntensity, time,
                            plan.LastOrDefault()!=null?plan.LastOrDefault().TimeEnd:0));
                    }

                    //Repeat while we have some jobs
                    //TODO: Optimize, maybe we don't need to check all jobs
                } while (jobHeap.Count>0);

                var stepTime = jobsForStep.Min(j => j.RunTime);
                var startTime = (plan.Count > 0) ? plan.Last().TimeEnd : 0;
                //Create PlanStep at this moment
                var step = new PlanStep(jobsForStep, startTime, stepTime + startTime, stepNumber++);
                //Compute all jobs to finish
                foreach (var runningJob in jobsForStep)
                {
                    if (runningJob.RunTime.FloatEquals(stepTime))
                    {
                        runningJob.JobReference.State = JobState.Finished;
                        runningJob.JobReference.RemainingVolume = 0;
                        unfinishedJobs.Remove(runningJob.JobReference);
                    }
                    else
                    {
                        var completed = runningJob.Intencity*stepTime;
                        runningJob.JobReference.RemainingVolume -= completed;
                        runningJob.RunTime = step.TimeDelta;
                    }
                }

                //Memorize job progress
                plan.Add(step);
            }

            return plan;
        }