示例#1
0
        public void StandGrowthPerformance()
        {
            int thinningPeriod = 4;
            int runs           = 4; // 1 warmup run + measured runs
            int trees          = 300;

            #if DEBUG
            runs  = 1; // do only functional validation of test on DEBUG builds to reduce test execution time
            trees = 10;
            #endif

            PlotsWithHeight      nelder        = PublicApi.GetNelder();
            OrganonConfiguration configuration = PublicApi.CreateOrganonConfiguration(new OrganonVariantNwo());
            configuration.Treatments.Harvests.Add(new ThinByIndividualTreeSelection(thinningPeriod));
            OrganonStand stand = nelder.ToOrganonStand(configuration, 20, 130.0F, trees);
            stand.PlantingDensityInTreesPerHectare = TestConstant.NelderReplantingDensityInTreesPerHectare;

            Objective landExpectationValue = new Objective()
            {
                IsLandExpectationValue = true,
                PlanningPeriods        = 9
            };
            HeuristicParameters defaultParameters = new HeuristicParameters();

            TimeSpan runtime = TimeSpan.Zero;
            for (int run = 0; run < runs; ++run)
            {
                // after warmup: 3 runs * 300 trees = 900 measured growth simulations on i7-3770 (4th gen, Sandy Bridge)
                // dispersion of 5 runs                   min   mean  median  max
                // .NET 5.0 with removed tree compaction  1.67  1.72  1.72    1.82
                Hero hero = new Hero(stand, configuration, landExpectationValue, defaultParameters)
                {
                    IsStochastic      = false,
                    MaximumIterations = 2
                };
                hero.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
                if (run > 0)
                {
                    // skip first run as a warmup run
                    runtime += hero.Run();
                }
            }
            this.TestContext !.WriteLine(runtime.TotalSeconds.ToString());
        }
示例#2
0
        public void NelderHero()
        {
            int   thinningPeriod = 4;
            int   treeCount      = 100;
            int   expectedTreesSelectedWithFiaVolume   = 0;
            float minObjectiveFunctionWithFiaVolume    = 4.154F; // USk$/ha
            float minObjectiveFunctionWithScaledVolume = 3.454F; // USk$/ha
            float minThinnedMbfWithFiaVolume           = 0.0F;

            #if DEBUG
            treeCount = 48;
            expectedTreesSelectedWithFiaVolume   = 0;
            minObjectiveFunctionWithFiaVolume    = 1.790F; // USk$/ha
            minObjectiveFunctionWithScaledVolume = 1.357F; // USk$/ha
            minThinnedMbfWithFiaVolume           = 0.0F;
            #endif

            PlotsWithHeight      nelder        = PublicApi.GetNelder();
            OrganonConfiguration configuration = new OrganonConfiguration(new OrganonVariantNwo());
            configuration.Treatments.Harvests.Add(new ThinByIndividualTreeSelection(thinningPeriod));
            OrganonStand stand = nelder.ToOrganonStand(configuration, 20, 130.0F, treeCount);
            stand.PlantingDensityInTreesPerHectare = TestConstant.NelderReplantingDensityInTreesPerHectare;

            Objective landExpectationValue = new Objective()
            {
                IsLandExpectationValue = true,
                PlanningPeriods        = 9
            };
            Hero hero = new Hero(stand, configuration, landExpectationValue, new HeuristicParameters()
            {
                UseScaledVolume = false
            })
            {
                //IsStochastic = true,
                MaximumIterations = 10
            };
            //hero.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            hero.CurrentTrajectory.SetTreeSelection(0, thinningPeriod);
            hero.Run();

            this.Verify(hero);

            int[] treeSelection = hero.BestTrajectory.IndividualTreeSelectionBySpecies[FiaCode.PseudotsugaMenziesii];
            int   treesSelected = treeSelection.Sum() / thinningPeriod;

            if (hero.BestTrajectory.UseScaledVolume)
            {
                this.TestContext !.WriteLine("best objective: {0} observed, near {1} expected", hero.BestObjectiveFunction, minObjectiveFunctionWithScaledVolume);
                Assert.IsTrue(hero.BestObjectiveFunction > minObjectiveFunctionWithScaledVolume);
                Assert.IsTrue(hero.BestObjectiveFunction < 1.02F * minObjectiveFunctionWithScaledVolume);
            }
            else
            {
                // expected standing volume, MBF, for no trees harvested
                // 0.122, 0.971, 3.18, 6.749, 11.56, 17.54, 24.56, 32.44, 40.97, 49.98
                // expected NPV, US$/ha, for no trees harvested
                // -90.96, 61.62, 373.49, 781.90, 1228.99, 1674.68, 2085.93, 2438.25, 2717.76, 2918.96
                this.TestContext !.WriteLine("best objective: {0} observed, near {1} expected", hero.BestObjectiveFunction, minObjectiveFunctionWithFiaVolume);
                Assert.IsTrue(hero.BestObjectiveFunction > minObjectiveFunctionWithFiaVolume);
                Assert.IsTrue(hero.BestObjectiveFunction < 1.01F * minObjectiveFunctionWithFiaVolume);
                Assert.IsTrue(hero.BestTrajectory.ThinningVolume.ScribnerTotal[thinningPeriod] >= minThinnedMbfWithFiaVolume);
                Assert.IsTrue(hero.BestTrajectory.ThinningVolume.ScribnerTotal[thinningPeriod] <= 1.01 * minThinnedMbfWithFiaVolume);
                Assert.IsTrue(treesSelected == expectedTreesSelectedWithFiaVolume);
            }
        }
示例#3
0
        public void NelderTrajectory()
        {
            int  expectedUnthinnedTreeRecordCount = 661;
            int  lastPeriod      = 9;
            bool useScaledVolume = false;

            PlotsWithHeight      nelder        = PublicApi.GetNelder();
            OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(new OrganonVariantNwo());
            OrganonStand         stand         = nelder.ToOrganonStand(configuration, 20, 130.0F);

            stand.PlantingDensityInTreesPerHectare = TestConstant.NelderReplantingDensityInTreesPerHectare;

            OrganonStandTrajectory unthinnedTrajectory = new OrganonStandTrajectory(stand, configuration, TimberValue.Default, lastPeriod, useScaledVolume);

            unthinnedTrajectory.Simulate();
            foreach (Stand?unthinnedStand in unthinnedTrajectory.StandByPeriod)
            {
                AssertNullable.IsNotNull(unthinnedStand);
                Assert.IsTrue(unthinnedStand.GetTreeRecordCount() == expectedUnthinnedTreeRecordCount);
            }

            int thinPeriod = 3;

            configuration.Treatments.Harvests.Add(new ThinByPrescription(thinPeriod)
            {
                FromAbovePercentage    = 20.0F,
                ProportionalPercentage = 15.0F,
                FromBelowPercentage    = 10.0F
            });
            OrganonStandTrajectory thinnedTrajectory = new OrganonStandTrajectory(stand, configuration, TimberValue.Default, lastPeriod, useScaledVolume);

            AssertNullable.IsNotNull(thinnedTrajectory.StandByPeriod[0]);
            Assert.IsTrue(thinnedTrajectory.StandByPeriod[0] !.GetTreeRecordCount() == expectedUnthinnedTreeRecordCount);

            thinnedTrajectory.Simulate();

            for (int periodIndex = 0; periodIndex < thinPeriod; ++periodIndex)
            {
                Stand?unthinnedStand = thinnedTrajectory.StandByPeriod[periodIndex];
                AssertNullable.IsNotNull(unthinnedStand);
                Assert.IsTrue(unthinnedStand.GetTreeRecordCount() == expectedUnthinnedTreeRecordCount);
            }
            int expectedThinnedTreeRecordCount = 328; // must be updated if prescription changes

            for (int periodIndex = thinPeriod; periodIndex < thinnedTrajectory.PlanningPeriods; ++periodIndex)
            {
                Stand?thinnedStand = thinnedTrajectory.StandByPeriod[periodIndex];
                AssertNullable.IsNotNull(thinnedStand);
                Assert.IsTrue(thinnedStand.GetTreeRecordCount() == expectedThinnedTreeRecordCount);
            }

            // verify unthinned trajectory
            //                                          0      1      2      3       4       5       6       7       8       9
            float[] minimumUnthinnedQmd = new float[] { 6.61F, 8.17F, 9.52F, 10.67F, 11.68F, 12.56F, 13.34F, 14.05F, 14.69F, 15.28F };      // in
            //                                                0      1      2      3      4       5       6       7       8       9
            float[] minimumUnthinnedTopHeight = new float[] { 54.1F, 67.9F, 80.3F, 91.6F, 101.9F, 111.3F, 119.9F, 127.8F, 135.0F, 141.7F }; // ft
            float[] minimumUnthinnedVolume;
            if (unthinnedTrajectory.UseScaledVolume)
            {
                minimumUnthinnedVolume = new float[] { 9.758F, 19.01F, 31.07F, 47.24F, 62.21F, 75.09F, 89.64F, 103.7F, 116.5F, 128.9F }; // Poudel 2018 + Scribner long log net MBF/ha
            }
            else
            {
                //                                     0       1       2       3       4       5       6       7       8       9
                minimumUnthinnedVolume = new float[] { 4.428F, 15.02F, 30.49F, 48.39F, 66.72F, 84.45F, 101.1F, 116.4F, 130.6F, 143.6F }; // FIA SV6x32 MBF/ha
            }
            PublicApi.Verify(unthinnedTrajectory, minimumUnthinnedQmd, minimumUnthinnedTopHeight, minimumUnthinnedVolume, 0, lastPeriod, 0, 0, configuration.Variant.TimeStepInYears);

            // verify thinned trajectory
            //                                        0      1      2      3       4       5       6       7       8       9
            float[] minimumThinnedQmd = new float[] { 6.61F, 8.19F, 9.53F, 11.81F, 13.44F, 14.80F, 15.99F, 17.05F, 18.00F, 18.85F };     // in
            //                                              0      1      2      3      4      5       6       7       8       9
            float[] minimumThinnedTopHeight = new float[] { 54.1F, 67.9F, 80.3F, 88.3F, 98.4F, 108.0F, 116.9F, 125.0F, 132.5F, 139.4F }; // ft
            float[] minimumThinnedVolume;
            if (thinnedTrajectory.UseScaledVolume)
            {
                minimumThinnedVolume = new float[] { 9.758F, 19.01F, 31.07F, 28.25F, 41.77F, 54.37F, 68.44F, 85.10F, 100.4F, 114.7F }; // Poudel 2018 + Scribner long log net MBF/ha
            }
            else
            {
                //                                   0       1       2       3       4       5       6       7       8       9
                minimumThinnedVolume = new float[] { 4.428F, 15.02F, 30.50F, 30.64F, 47.26F, 64.81F, 82.54F, 99.87F, 116.3F, 131.7F }; // FIA MBF/ha
            }
            PublicApi.Verify(thinnedTrajectory, minimumThinnedQmd, minimumThinnedTopHeight, minimumThinnedVolume, thinPeriod, lastPeriod, 200, 400, configuration.Variant.TimeStepInYears);
            PublicApi.Verify(thinnedTrajectory, minimumThinnedVolume, thinPeriod);
        }
示例#4
0
        public void NelderOtherHeuristics()
        {
            int thinningPeriod = 4;
            int treeCount      = 75;

            #if DEBUG
            treeCount = 25;
            #endif

            PlotsWithHeight      nelder        = PublicApi.GetNelder();
            OrganonConfiguration configuration = OrganonTest.CreateOrganonConfiguration(new OrganonVariantNwo());
            configuration.Treatments.Harvests.Add(new ThinByIndividualTreeSelection(thinningPeriod));
            OrganonStand stand = nelder.ToOrganonStand(configuration, 20, 130.0F, treeCount);
            stand.PlantingDensityInTreesPerHectare = TestConstant.NelderReplantingDensityInTreesPerHectare;

            Objective landExpectationValue = new Objective()
            {
                IsLandExpectationValue = true,
                PlanningPeriods        = 9
            };
            Objective volume = new Objective()
            {
                PlanningPeriods = landExpectationValue.PlanningPeriods
            };
            HeuristicParameters defaultParameters = new HeuristicParameters()
            {
                UseScaledVolume = false
            };

            GeneticParameters geneticParameters = new GeneticParameters(treeCount)
            {
                PopulationSize     = 7,
                MaximumGenerations = 5,
                UseScaledVolume    = defaultParameters.UseScaledVolume
            };
            GeneticAlgorithm genetic        = new GeneticAlgorithm(stand, configuration, landExpectationValue, geneticParameters);
            TimeSpan         geneticRuntime = genetic.Run();

            GreatDeluge deluge = new GreatDeluge(stand, configuration, volume, defaultParameters)
            {
                RainRate        = 5,
                LowerWaterAfter = 9,
                StopAfter       = 10
            };
            deluge.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            TimeSpan delugeRuntime = deluge.Run();

            RecordTravel recordTravel = new RecordTravel(stand, configuration, landExpectationValue, defaultParameters)
            {
                StopAfter = 10
            };
            recordTravel.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            TimeSpan recordRuntime = recordTravel.Run();

            SimulatedAnnealing annealer = new SimulatedAnnealing(stand, configuration, volume, defaultParameters)
            {
                Iterations = 100
            };
            annealer.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            TimeSpan annealerRuntime = annealer.Run();

            TabuParameters tabuParameters = new TabuParameters()
            {
                UseScaledVolume = defaultParameters.UseScaledVolume
            };
            TabuSearch tabu = new TabuSearch(stand, configuration, landExpectationValue, tabuParameters)
            {
                Iterations = 7,
                //Jump = 2,
                MaximumTenure = 5
            };
            tabu.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            TimeSpan tabuRuntime = tabu.Run();

            ThresholdAccepting thresholdAcceptor = new ThresholdAccepting(stand, configuration, volume, defaultParameters);
            thresholdAcceptor.IterationsPerThreshold.Clear();
            thresholdAcceptor.Thresholds.Clear();
            thresholdAcceptor.IterationsPerThreshold.Add(10);
            thresholdAcceptor.Thresholds.Add(1.0F);
            thresholdAcceptor.RandomizeTreeSelection(TestConstant.Default.SelectionPercentage);
            TimeSpan acceptorRuntime = thresholdAcceptor.Run();

            RandomGuessing random = new RandomGuessing(stand, configuration, volume, defaultParameters)
            {
                Iterations = 4
            };
            TimeSpan randomRuntime = random.Run();

            configuration.Treatments.Harvests.Clear();
            configuration.Treatments.Harvests.Add(new ThinByPrescription(thinningPeriod));
            PrescriptionParameters prescriptionParameters = new PrescriptionParameters()
            {
                Maximum         = 60.0F,
                Minimum         = 50.0F,
                Step            = 10.0F,
                UseScaledVolume = defaultParameters.UseScaledVolume
            };
            PrescriptionEnumeration enumerator = new PrescriptionEnumeration(stand, configuration, landExpectationValue, prescriptionParameters);
            TimeSpan enumerationRuntime        = enumerator.Run();

            // heuristics assigned to volume optimization
            this.Verify(deluge);
            this.Verify(annealer);
            this.Verify(thresholdAcceptor);
            this.Verify(random);

            // heuristics assigned to net present value optimization
            this.Verify(genetic);
            this.Verify(enumerator);
            this.Verify(recordTravel);
            this.Verify(tabu);

            HeuristicSolutionDistribution distribution = new HeuristicSolutionDistribution(1, thinningPeriod, treeCount);
            distribution.AddRun(annealer, annealerRuntime, defaultParameters);
            distribution.AddRun(deluge, delugeRuntime, defaultParameters);
            distribution.AddRun(thresholdAcceptor, acceptorRuntime, defaultParameters);
            distribution.AddRun(genetic, geneticRuntime, defaultParameters);
            distribution.AddRun(enumerator, enumerationRuntime, defaultParameters);
            distribution.AddRun(recordTravel, recordRuntime, defaultParameters);
            distribution.AddRun(tabu, tabuRuntime, defaultParameters);
            distribution.AddRun(random, randomRuntime, defaultParameters);
            distribution.OnRunsComplete();
        }