예제 #1
0
        protected override void ProcessRecord()
        {
            PlotsWithHeight plot;

            if (this.ExpansionFactor.HasValue)
            {
                plot = new PlotsWithHeight(this.Plots !, this.ExpansionFactor.Value);
            }
            else
            {
                plot = new PlotsWithHeight(this.Plots !);
            }
            plot.Read(this.Xlsx !, this.XlsxSheet);

            OrganonConfiguration configuration = new OrganonConfiguration(OrganonVariant.Create(this.Model));
            OrganonStand         stand;

            if (this.Trees.HasValue)
            {
                stand = plot.ToOrganonStand(configuration, this.Age, this.SiteIndex, this.Trees.Value);
            }
            else
            {
                stand = plot.ToOrganonStand(configuration, this.Age, this.SiteIndex);
            }
            if (this.PlantingDensity.HasValue)
            {
                stand.PlantingDensityInTreesPerHectare = this.PlantingDensity.Value;
            }
            this.WriteObject(stand);
        }
예제 #2
0
        protected override void ProcessRecord()
        {
            if (this.HarvestPeriods.Count < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(this.HarvestPeriods));
            }
            if ((this.PerturbBy < 0.0F) || (this.PerturbBy > 1.0F))
            {
                throw new ArgumentOutOfRangeException(nameof(this.PerturbBy));
            }
            if (this.PlanningPeriods.Count < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(this.PlanningPeriods));
            }
            if (this.ProportionalPercentage.Count < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(this.ProportionalPercentage));
            }

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            IList <TParameters> parameterCombinations = this.GetParameterCombinations();
            int treeCount = this.Stand !.GetTreeRecordCount();
            List <HeuristicSolutionDistribution> distributions = new List <HeuristicSolutionDistribution>(parameterCombinations.Count * this.HarvestPeriods.Count * this.PlanningPeriods.Count);

            for (int planningPeriodIndex = 0; planningPeriodIndex < this.PlanningPeriods.Count; ++planningPeriodIndex)
            {
                for (int harvestPeriodIndex = 0; harvestPeriodIndex < this.HarvestPeriods.Count; ++harvestPeriodIndex)
                {
                    int planningPeriods = this.PlanningPeriods[planningPeriodIndex];
                    int harvestPeriods  = this.HarvestPeriods[harvestPeriodIndex];
                    if (harvestPeriods >= planningPeriods) // minimum 10 years between thinning and final harvest (if five year time step)
                    {
                        continue;
                    }

                    for (int parameterIndex = 0; parameterIndex < parameterCombinations.Count; ++parameterIndex)
                    {
                        distributions.Add(new HeuristicSolutionDistribution(1, harvestPeriods, treeCount)
                        {
                            HarvestPeriodIndex  = harvestPeriodIndex,
                            ParameterIndex      = parameterIndex,
                            PlanningPeriodIndex = planningPeriodIndex
                        });
                    }
                }
            }

            ParallelOptions parallelOptions = new ParallelOptions()
            {
                MaxDegreeOfParallelism = this.Threads
            };
            int  totalRuns     = distributions.Count * this.BestOf;
            int  runsCompleted = 0;
            Task runs          = Task.Run(() =>
            {
                Parallel.For(0, totalRuns, parallelOptions, (int iteration, ParallelLoopState loopState) =>
                {
                    if (loopState.ShouldExitCurrentIteration)
                    {
                        return;
                    }

                    int distributionIndex = iteration / this.BestOf;
                    HeuristicSolutionDistribution distribution = distributions[distributionIndex];
                    OrganonConfiguration organonConfiguration  = new OrganonConfiguration(OrganonVariant.Create(this.TreeModel));
                    organonConfiguration.Treatments.Harvests.Add(this.CreateHarvest(distribution.HarvestPeriodIndex));

                    Objective objective = new Objective()
                    {
                        IsLandExpectationValue = this.LandExpectationValue,
                        PlanningPeriods        = this.PlanningPeriods[distribution.PlanningPeriodIndex]
                    };
                    TParameters runParameters  = parameterCombinations[distribution.ParameterIndex];
                    Heuristic currentHeuristic = this.CreateHeuristic(organonConfiguration, objective, runParameters);
                    if (runParameters.PerturbBy > 0.0F)
                    {
                        if ((runParameters.PerturbBy == 1.0F) || (distribution.EliteSolutions.NewIndividuals == 0))
                        {
                            // minor optimization point: save a few time steps by by re-using pre-thin results
                            // minor optimization point: save one loop over stand by skipping this for genetic algorithms
                            currentHeuristic.RandomizeTreeSelection(runParameters.ProportionalPercentage);
                        }
                        else
                        {
                            // TODO: support initialization from unperturbed elite solutions
                            // TODO: intialize genetic algorithm population from elite solutions?
                            // TODO: how to define generation statistics?
                            // TODO: more granular locking?
                            lock (distributions)
                            {
                                currentHeuristic.RandomizeTreeSelectionFrom(runParameters.PerturbBy, distribution.EliteSolutions);
                            }
                        }
                    }
                    TimeSpan runTime = currentHeuristic.Run();

                    lock (distributions)
                    {
                        distribution.AddRun(currentHeuristic, runTime, runParameters);
                        ++runsCompleted;
                    }

                    if (this.Stopping)
                    {
                        loopState.Stop();
                    }
                });
            });

            string name = this.GetName();
            int    sleepsSinceLastStatusUpdate = 0;

            while (runs.IsCompleted == false)
            {
                Thread.Sleep(TimeSpan.FromSeconds(1.0));
                ++sleepsSinceLastStatusUpdate;

                if (runs.IsFaulted)
                {
                    Debug.Assert(runs.Exception != null && runs.Exception.InnerException != null);
                    // per https://stackoverflow.com/questions/20170527/how-to-correctly-rethrow-an-exception-of-task-already-in-faulted-state
                    ExceptionDispatchInfo.Capture(runs.Exception.InnerException).Throw();
                }
                if (sleepsSinceLastStatusUpdate > 30)
                {
                    double fractionComplete = (double)runsCompleted / (double)totalRuns;
                    double secondsElapsed   = stopwatch.Elapsed.TotalSeconds;
                    double secondsRemaining = secondsElapsed * (1.0 / fractionComplete - 1.0);
                    this.WriteProgress(new ProgressRecord(0, name, String.Format(runsCompleted + " of " + totalRuns + " runs completed by " + this.Threads + " threads."))
                    {
                        PercentComplete  = (int)(100.0 * fractionComplete),
                        SecondsRemaining = (int)Math.Round(secondsRemaining)
                    });
                    sleepsSinceLastStatusUpdate = 0;
                }
            }
            runs.GetAwaiter().GetResult(); // propagate any exceptions since last IsFaulted check

            foreach (HeuristicSolutionDistribution distribution in distributions)
            {
                distribution.OnRunsComplete();
            }
            stopwatch.Stop();

            this.WriteObject(distributions);
            if (distributions.Count == 1)
            {
                this.WriteSingleDistributionSummary(distributions[0], stopwatch.Elapsed);
            }
            else
            {
                this.WriteMultipleDistributionSummary(distributions, stopwatch.Elapsed);
            }
        }