public void RunTest()
        {
            // context is null
            {
                string parameterName = "context";
                string innerMessage  =
                    ArgumentExceptionAssert.NullPartialMessage +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var sample = DoubleMatrix.Dense(1, 1);

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Run",
                        methodArgs: new object[] { null, 1, .01 });
                },
                    expectedInnerType: typeof(ArgumentNullException),
                    expectedInnerMessage: innerMessage);
            }
        }
        public void RunTest()
        {
            // Valid input - Minimization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestablePartitionOptimizationContext00.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                int    sampleSize = 2000;
                double rarity     = 0.01;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                var expectedPartition = IndexPartition.Create(
                    testableContext.OptimalState);

                var actualPartition = IndexPartition.Create(
                    results.OptimalState);

                IndexPartitionAssert.HaveEqualIdentifiers(
                    expected: expectedPartition,
                    actual: actualPartition);

                IndexPartitionAssert.HaveEqualParts(
                    expected: expectedPartition,
                    actual: actualPartition);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }
        }
        public void Main()
        {
            // Create the context.
            var context = new RosenbrockFunctionMinimizationContext();

            // Create the optimizer.
            var optimizer = new SystemPerformanceOptimizer()
            {
                PerformanceEvaluationParallelOptions = { MaxDegreeOfParallelism = -1 },
                SampleGenerationParallelOptions      = { MaxDegreeOfParallelism = -1 }
            };

            // Set optimization parameters.
            double rarity     = 0.1;
            int    sampleSize = 1000;

            // Solve the problem.
            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            // Show the results.
            Console.WriteLine(
                "The Cross-Entropy optimizer has converged: {0}.",
                results.HasConverged);

            Console.WriteLine();
            Console.WriteLine("Initial guess parameter:");
            Console.WriteLine(context.InitialParameter);

            Console.WriteLine();
            Console.WriteLine("The minimizer of the performance is:");
            Console.WriteLine(results.OptimalState);

            Console.WriteLine();

            Console.WriteLine("The minimum performance is:");
            Console.WriteLine(results.OptimalPerformance);
        }
Пример #4
0
        /// <summary>
        /// Initializes a new instance of the
        /// <see cref="CategoricalEntailmentEnsembleClassifier" /> class
        /// by exploiting the specified <paramref name="trainer"/>
        /// to select the given
        /// <paramref name="numberOfTrainedCategoricalEntailments"/>.
        /// </summary>
        /// <param name="trainer">
        /// An object whose state contains the information needed to
        /// train the classifier.
        /// </param>
        /// <param name="numberOfTrainedCategoricalEntailments">
        /// The number of categorical entailments to be trained.
        /// </param>
        /// <returns>
        /// A classifier whose ensemble contains the trained
        /// categorical entailments.
        /// </returns>
        /// <remarks>
        /// <para>
        /// The <paramref name="trainer"/> can be equipped with a
        /// nonempty initial ensemble of categorical entailments.
        /// This method always trains a classifier by adding
        /// to such ensemble further entailments, whose number
        /// is specified by parameter
        /// <paramref name="numberOfTrainedCategoricalEntailments"/>.
        /// However, the method returns the partial classifier whose
        /// ensemble contains the additional trained entailments only
        /// (no initial entailments).
        /// </para>
        /// </remarks>
        private static CategoricalEntailmentEnsembleClassifier Train(
            CategoricalEntailmentEnsembleTrainer trainer,
            int numberOfTrainedCategoricalEntailments)
        {
            var optimizer = new SystemPerformanceOptimizer();

            int numberOfResponseCategories =
                trainer.ResponseVariable.NumberOfCategories;

            var context =
                new CategoricalEntailmentEnsembleOptimizationContext(
                    objectiveFunction: trainer.Performance,
                    trainer.featureCategoryCounts,
                    numberOfResponseCategories,
                    numberOfTrainedCategoricalEntailments,
                    trainer.allowEntailmentPartialTruthValues,
                    probabilitySmoothingCoefficient: .9,
                    optimizationGoal: OptimizationGoal.Maximization,
                    minimumNumberOfIterations: 10,
                    maximumNumberOfIterations: 1000);

            int numberOfParameters = numberOfTrainedCategoricalEntailments * (
                trainer.featureCategoryCounts.Sum() + numberOfResponseCategories);

            int sampleSize = 100 * numberOfParameters;

            double rarity = .01;

            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            var partialClassifier = context.GetCategoricalEntailmentEnsembleClassifier(
                results.OptimalState,
                new List <CategoricalVariable>(trainer.FeatureVariables),
                trainer.ResponseVariable);

            return(partialClassifier);
        }
        public void SampleGenerationParallelOptionsTest()
        {
            // value is null
            {
                string parameterName = "value";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.SampleGenerationParallelOptions
                        = null;
                },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage:
                    ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: parameterName);
            }

            // value is valid
            {
                int maxDegreeOfParallelism = 2;

                var optimizer = new SystemPerformanceOptimizer
                {
                    SampleGenerationParallelOptions
                        = new System.Threading.Tasks.ParallelOptions()
                        {
                        MaxDegreeOfParallelism = maxDegreeOfParallelism
                        }
                };

                Assert.AreEqual(
                    expected: 2,
                    actual: optimizer
                    .SampleGenerationParallelOptions.MaxDegreeOfParallelism);
            }
        }
Пример #6
0
        public void RunTest()
        {
            var optimizer = new SystemPerformanceOptimizer();

            // Create the context.
            var testableContext =
                TestableCategoricalEntailmentEnsembleOptimizationContext01.Get();

            var context = testableContext.Context;

            context.TraceExecution = true;

            // Set optimization parameters.
            int    sampleSize = 3600;
            double rarity     = 0.01;

            // Solve the problem.
            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            Assert.AreEqual(
                expected: true,
                actual: results.HasConverged);

            var expectedClassifier =
                new CategoricalEntailmentEnsembleClassifier(
                    featureVariables: testableContext.FeatureVariables,
                    responseVariable: testableContext.ResponseVariable);

            expectedClassifier.Add(
                featurePremises: new List <SortedSet <double> >(1)
            {
                new SortedSet <double>()
                {
                    0.0, 1.0, 2.0
                }
            },
                responseConclusion: 0.0,
                truthValue: 1.0);

            expectedClassifier.Add(
                featurePremises: new List <SortedSet <double> >(1)
            {
                new SortedSet <double>()
                {
                    3.0, 4.0, 5.0
                }
            },
                responseConclusion: 1.0,
                truthValue: 1.0);

            var actualClassifier =
                new CategoricalEntailmentEnsembleClassifier(
                    featureVariables: testableContext.FeatureVariables,
                    responseVariable: testableContext.ResponseVariable);

            actualClassifier.Add(
                featurePremises: new List <SortedSet <double> >(1)
            {
                new SortedSet <double>()
                {
                    0.0, 1.0, 2.0
                }
            },
                responseConclusion: 0.0,
                truthValue: 1.0);

            actualClassifier.Add(
                context.GetCategoricalEntailmentEnsembleClassifier(
                    state: results.OptimalState,
                    featureVariables: testableContext.FeatureVariables,
                    responseVariable: testableContext.ResponseVariable)
                .Entailments[0]);

            var expectedTrainedEntailment = expectedClassifier.Entailments[1];
            var actualTrainedEntailment   = actualClassifier.Entailments[1];

            Assert.IsTrue(
                expectedTrainedEntailment.FeaturePremises[0]
                .IsSubsetOf(
                    actualTrainedEntailment.FeaturePremises[0]));

            Assert.AreEqual(
                expected: expectedTrainedEntailment.ResponseConclusion,
                actual: actualTrainedEntailment.ResponseConclusion,
                DoubleMatrixTest.Accuracy);

            Assert.AreEqual(
                expected: testableContext.OptimalPerformance,
                actual: results.OptimalPerformance,
                DoubleMatrixTest.Accuracy);
        }
        public void Main()
        {
            // Set the number of items and features under study.
            const int numberOfItems    = 12;
            int       numberOfFeatures = 7;

            // Create a matrix that will represent
            // an artificial data set,
            // having 12 items (rows) and 7 features (columns).
            // This will store the observations which
            // partition discovery will be based on.
            var data = DoubleMatrix.Dense(
                numberOfRows: numberOfItems,
                numberOfColumns: numberOfFeatures);

            // Fill the data rows by sampling from a different
            // distribution while, respectively, drawing observations
            // for items 0 to 3, 4 to 7, and 8 to 11: these will be the
            // three different parts expected to be included in the
            // optimal partition.
            double mu = 1.0;
            var    g  = new GaussianDistribution(mu: mu, sigma: .01);

            IndexCollection range = IndexCollection.Range(0, 3);

            for (int j = 0; j < numberOfFeatures; j++)
            {
                data[range, j] = g.Sample(sampleSize: range.Count);
            }

            mu   += 5.0;
            g.Mu  = mu;
            range = IndexCollection.Range(4, 7);
            for (int j = 0; j < numberOfFeatures; j++)
            {
                data[range, j] = g.Sample(sampleSize: range.Count);
            }

            mu   += 5.0;
            g.Mu  = mu;
            range = IndexCollection.Range(8, 11);
            for (int j = 0; j < numberOfFeatures; j++)
            {
                data[range, j] = g.Sample(sampleSize: range.Count);
            }

            Console.WriteLine("The data set:");
            Console.WriteLine(data);

            // Define the optimization problem as
            // the minimization of the Davies-Bouldin Index
            // of a candidate partition.
            double objectiveFunction(DoubleMatrix x)
            {
                // An argument x has 12 entries, each belonging
                // to the set {0,...,k-1}, where k is the
                // maximum number of allowed parts, so
                // x[j]==i signals that, at x, item j
                // has been assigned to part i.
                IndexPartition <double> selected =
                    IndexPartition.Create(x);

                var performance = IndexPartition.DaviesBouldinIndex(
                    data: data,
                    partition: selected);

                return(performance);
            }

            var optimizationGoal = OptimizationGoal.Minimization;

            // Define the maximum number of parts allowed in the
            // partition to be discovered.
            int maximumNumberOfParts = 3;

            // Create the required context.
            var context = new PartitionOptimizationContext(
                objectiveFunction: objectiveFunction,
                stateDimension: numberOfItems,
                partitionDimension: maximumNumberOfParts,
                probabilitySmoothingCoefficient: .8,
                optimizationGoal: optimizationGoal,
                minimumNumberOfIterations: 3,
                maximumNumberOfIterations: 1000);

            // Create the optimizer.
            var optimizer = new SystemPerformanceOptimizer()
            {
                PerformanceEvaluationParallelOptions = { MaxDegreeOfParallelism = -1 },
                SampleGenerationParallelOptions      = { MaxDegreeOfParallelism = -1 }
            };

            // Set optimization parameters.
            double rarity     = 0.01;
            int    sampleSize = 2000;

            // Solve the problem.
            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            IndexPartition <double> optimalPartition =
                IndexPartition.Create(results.OptimalState);

            // Show the results.
            Console.WriteLine(
                "The Cross-Entropy optimizer has converged: {0}.",
                results.HasConverged);

            Console.WriteLine();
            Console.WriteLine("Initial guess parameter:");
            Console.WriteLine(context.InitialParameter);

            Console.WriteLine();
            Console.WriteLine("The minimizer of the performance is:");
            Console.WriteLine(results.OptimalState);

            Console.WriteLine();
            Console.WriteLine(
                "The optimal partition is:");
            Console.WriteLine(optimalPartition);

            Console.WriteLine();
            Console.WriteLine("The minimum performance is:");
            Console.WriteLine(results.OptimalPerformance);

            Console.WriteLine();
            Console.WriteLine("The Dunn Index for the optimal partition is:");
            var di = IndexPartition.DunnIndex(
                data,
                optimalPartition);

            Console.WriteLine(di);
        }
        public void Main()
        {
            // Set the number of items and features under study.
            const int numberOfItems    = 12;
            int       numberOfFeatures = 7;

            // Define a partition that must be explained.
            // Three parts (clusters) are included,
            // containing, respectively, items 0 to 3,
            // 4 to 7, and 8 to 11.
            var partition = IndexPartition.Create(
                new double[numberOfItems]
            {
                0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2
            });

            // Create a matrix that will represent
            // an artificial data set,
            // having 12 items (rows) and 7 features (columns).
            // This will store the observations which
            // explanation will be based on.
            var data = DoubleMatrix.Dense(
                numberOfRows: numberOfItems,
                numberOfColumns: numberOfFeatures);

            // The first 5 features are built to be almost
            // surely non informative, since they result
            // as samples drawn from a same distribution.
            var g = new GaussianDistribution(mu: 0, sigma: .01);

            for (int j = 0; j < 5; j++)
            {
                data[":", j] = g.Sample(sampleSize: numberOfItems);
            }

            // Features 5 to 6 are instead built to be informative,
            // since they are sampled from different distributions
            // while filling rows whose indexes are in different parts
            // of the partition to be explained.
            var    partIdentifiers = partition.Identifiers;
            double mu = 1.0;

            for (int i = 0; i < partIdentifiers.Count; i++)
            {
                var part     = partition[partIdentifiers[i]];
                int partSize = part.Count;
                g.Mu          = mu;
                data[part, 5] = g.Sample(sampleSize: partSize);
                mu           += 2.0;
                g.Mu          = mu;
                data[part, 6] = g.Sample(sampleSize: partSize);
                mu           += 2.0;
            }

            Console.WriteLine("The data set:");
            Console.WriteLine(data);

            // Define the selection problem as
            // the maximization of the Dunn Index.
            double objectiveFunction(DoubleMatrix x)
            {
                // An argument x has entries equal to one,
                // signaling that the corresponding features
                // are selected at x. Otherwise, the entries
                // are zero.
                IndexCollection selected = x.FindNonzero();

                double performance =
                    IndexPartition.DunnIndex(
                        data: data[":", selected],
                        partition: partition);

                return(performance);
            }

            var optimizationGoal = OptimizationGoal.Maximization;

            // Define how many features must be selected
            // for explanation.
            int numberOfExplanatoryFeatures = 2;

            // Create the required context.
            var context = new CombinationOptimizationContext(
                objectiveFunction: objectiveFunction,
                stateDimension: numberOfFeatures,
                combinationDimension: numberOfExplanatoryFeatures,
                probabilitySmoothingCoefficient: .8,
                optimizationGoal: optimizationGoal,
                minimumNumberOfIterations: 3,
                maximumNumberOfIterations: 1000);

            // Create the optimizer.
            var optimizer = new SystemPerformanceOptimizer()
            {
                PerformanceEvaluationParallelOptions = { MaxDegreeOfParallelism = -1 },
                SampleGenerationParallelOptions      = { MaxDegreeOfParallelism = -1 }
            };

            // Set optimization parameters.
            double rarity     = 0.01;
            int    sampleSize = 1000;

            // Solve the problem.
            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            IndexCollection optimalExplanatoryFeatureIndexes =
                results.OptimalState.FindNonzero();

            // Show the results.
            Console.WriteLine(
                "The Cross-Entropy optimizer has converged: {0}.",
                results.HasConverged);

            Console.WriteLine();
            Console.WriteLine("Initial guess parameter:");
            Console.WriteLine(context.InitialParameter);

            Console.WriteLine();
            Console.WriteLine("The maximizer of the performance is:");
            Console.WriteLine(results.OptimalState);

            Console.WriteLine();
            Console.WriteLine(
                "The {0} features best explaining the given partition have column indexes:",
                numberOfExplanatoryFeatures);
            Console.WriteLine(optimalExplanatoryFeatureIndexes);

            Console.WriteLine();
            Console.WriteLine("The maximum performance is:");
            Console.WriteLine(results.OptimalPerformance);

            Console.WriteLine();
            Console.WriteLine("This is the Dunn Index for the selected features:");
            var di = IndexPartition.DunnIndex(
                data[":", optimalExplanatoryFeatureIndexes],
                partition);

            Console.WriteLine(di);
        }
Пример #9
0
        public void RunTest()
        {
            // Valid input - Minimization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableSystemPerformanceOptimizationContext00.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                double rarity     = 0.05;
                int    sampleSize = 1000;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    delta: .03);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }

            // Valid input - Maximization - with overrides
            {
                var optimizer = new SystemPerformanceOptimizer()
                {
                    PerformanceEvaluationParallelOptions = { MaxDegreeOfParallelism = 1 },
                    SampleGenerationParallelOptions      = { MaxDegreeOfParallelism = 1 }
                };

                // Create the context.
                var testableContext =
                    TestableSystemPerformanceOptimizationContext01.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                double rarity     = 0.1;
                int    sampleSize = 1000;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    DoubleMatrixTest.Accuracy);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }

            // Valid input - Maximization - without overrides
            {
                var optimizer = new SystemPerformanceOptimizer()
                {
                    PerformanceEvaluationParallelOptions = { MaxDegreeOfParallelism = 1 },
                    SampleGenerationParallelOptions      = { MaxDegreeOfParallelism = 1 }
                };

                // Create the context.
                var testableContext =
                    TestableSystemPerformanceOptimizationContext02.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                double rarity     = 0.1;
                int    sampleSize = 1000;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    DoubleMatrixTest.Accuracy);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }
        }
        public void RunTest()
        {
            // Valid input - Minimization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableContinuousOptimizationContext00.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                int    sampleSize = 100;
                double rarity     = 0.09;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    delta: .03);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }

            // Valid input - Maximization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableContinuousOptimizationContext01.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                int    sampleSize = 100;
                double rarity     = 0.1;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    DoubleMatrixTest.Accuracy);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }

            // Valid input - Maximization - not converging
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableContinuousOptimizationContext01.Get();

                var context = new ContinuousOptimizationContext(
                    objectiveFunction: testableContext.ObjectiveFunction,
                    initialArgument: testableContext.InitialArgument,
                    meanSmoothingCoefficient: testableContext.MeanSmoothingCoefficient,
                    standardDeviationSmoothingCoefficient: testableContext.StandardDeviationSmoothingCoefficient,
                    standardDeviationSmoothingExponent: testableContext.StandardDeviationSmoothingExponent,
                    initialStandardDeviation: testableContext.InitialStandardDeviation,
                    terminationTolerance: testableContext.TerminationTolerance,
                    optimizationGoal: testableContext.OptimizationGoal,
                    minimumNumberOfIterations: testableContext.MinimumNumberOfIterations,
                    maximumNumberOfIterations: testableContext.MinimumNumberOfIterations + 1);

                // Set optimization parameters.
                int    sampleSize = 100;
                double rarity     = 0.1;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: false,
                    actual: results.HasConverged);
            }
        }
Пример #11
0
        /// <summary>
        /// Finds the maximum of the specified
        /// parametric objective function.
        /// </summary>
        /// <param name="objectiveFunction">
        /// The objective function to be maximized.
        /// </param>
        /// <param name="initialArgument">
        /// The argument at which the method starts the search
        /// for optimality.
        /// </param>
        /// <param name="functionParameter">
        /// The function parameter.
        /// </param>
        /// <typeparam name="TFunctionParameter">
        /// The type of the function parameter.
        /// </typeparam>
        /// <returns>
        /// The argument at which the function is maximized.
        /// </returns>
        /// <remarks>
        /// <para>
        /// It is assumed that the <paramref name="objectiveFunction"/>
        /// will accept row
        /// vectors as valid representations of an argument.
        /// As a consequence, <paramref name="initialArgument"/> is
        /// expected to be a row vector.
        /// </para>
        /// </remarks>
        /// <example>
        /// <para>
        /// In the following example, function
        /// <latex mode='display'>
        /// f\round{x,\alpha}=\exp\round{-\round{x-2}^2}
        /// + \round{\alpha} \exp\round{-\round{x+2}^2}
        /// </latex>
        /// is maximized.
        /// </para>
        /// <para>
        /// The search for the maximizer starts from
        /// the initial argument <latex>-6</latex>.
        /// </para>
        /// <para>
        /// <code title="Maximizing a parametric function."
        /// source="..\Novacta.Analytics.CodeExamples\ContinuousOptimizationExample1.cs.txt"
        /// language="cs" />
        /// </para>
        /// </example>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="objectiveFunction"/> is
        /// <b>null</b>.<br/>
        /// -or-<br/>
        /// <paramref name="initialArgument"/> is <b>null</b>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="initialArgument"/> is not a row
        /// vector.
        /// </exception>
        public static DoubleMatrix Maximize <TFunctionParameter>(
            Func <DoubleMatrix, TFunctionParameter, double> objectiveFunction,
            DoubleMatrix initialArgument,
            TFunctionParameter functionParameter)
        {
            #region Input validation

            if (objectiveFunction is null)
            {
                throw new ArgumentNullException(nameof(objectiveFunction));
            }

            if (initialArgument is null)
            {
                throw new ArgumentNullException(nameof(initialArgument));
            }

            if (!initialArgument.IsRowVector)
            {
                throw new ArgumentException(
                          ImplementationServices.GetResourceString(
                              "STR_EXCEPT_PAR_MUST_BE_ROW_VECTOR"),
                          nameof(initialArgument));
            }

            #endregion

            double func(DoubleMatrix x) => objectiveFunction(x, functionParameter);

            int numberOfArguments = initialArgument.Count;

            var initialParameter = DoubleMatrix.Dense(
                2,
                numberOfArguments);

            initialParameter[0, ":"]  = initialArgument;
            initialParameter[1, ":"] += 1.0e2;

            var optimizer =
                new SystemPerformanceOptimizer();

            var context = new ContinuousOptimizationContext(
                objectiveFunction: func,
                initialArgument: initialArgument,
                meanSmoothingCoefficient: .8,
                standardDeviationSmoothingCoefficient: .7,
                standardDeviationSmoothingExponent: 6,
                initialStandardDeviation: 100.0,
                optimizationGoal: OptimizationGoal.Maximization,
                terminationTolerance: 1.0e-3,
                minimumNumberOfIterations: 3,
                maximumNumberOfIterations: 1000);

            int sampleSize = 100 * numberOfArguments;

            double rarity = .01;

            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            return(results.OptimalState);
        }
        public void EvauatePerformancesTest()
        {
            // context is null
            {
                string parameterName = "context";
                string innerMessage  =
                    ArgumentExceptionAssert.NullPartialMessage +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var sample = DoubleMatrix.Dense(1, 1);

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "EvaluatePerformances",
                        methodArgs: new object[] { null, sample });
                },
                    expectedInnerType: typeof(ArgumentNullException),
                    expectedInnerMessage: innerMessage);
            }

            // sample is null
            {
                string parameterName = "sample";
                string innerMessage  =
                    ArgumentExceptionAssert.NullPartialMessage +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "EvaluatePerformances",
                        methodArgs: new object[] { context, null });
                },
                    expectedInnerType: typeof(ArgumentNullException),
                    expectedInnerMessage: innerMessage);
            }

            // sample is not context compatible
            {
                string parameterName = "sample";

                string innerMessage =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CEP_SAMPLE_IS_CONTEXT_INCOMPATIBLE") +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "EvaluatePerformances",
                        methodArgs: new object[] {
                        context,
                        DoubleMatrix.Dense(1, context.StateDimension + 1)
                    });
                },
                    expectedInnerType: typeof(ArgumentException),
                    expectedInnerMessage: innerMessage);
            }
        }
        public void SampleTest()
        {
            // context is null
            {
                string parameterName = "context";
                string innerMessage  =
                    ArgumentExceptionAssert.NullPartialMessage +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var parameter = DoubleMatrix.Dense(1, 1);

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] { null, 1, parameter });
                },
                    expectedInnerType: typeof(ArgumentNullException),
                    expectedInnerMessage: innerMessage);
            }

            // parameter is null
            {
                string parameterName = "parameter";
                string innerMessage  =
                    ArgumentExceptionAssert.NullPartialMessage +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] { context, 1, null });
                },
                    expectedInnerType: typeof(ArgumentNullException),
                    expectedInnerMessage: innerMessage);
            }

            // sampleSize is zero
            {
                string parameterName = "sampleSize";
                string innerMessage  =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_MUST_BE_POSITIVE") +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] {
                        context,
                        0,
                        context.InitialParameter
                    });
                },
                    expectedInnerType: typeof(ArgumentOutOfRangeException),
                    expectedInnerMessage: innerMessage);
            }

            // sampleSize is negative
            {
                string parameterName = "sampleSize";
                string innerMessage  =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_MUST_BE_POSITIVE") +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] {
                        context,
                        -1,
                        context.InitialParameter
                    });
                },
                    expectedInnerType: typeof(ArgumentOutOfRangeException),
                    expectedInnerMessage: innerMessage);
            }

            // parameter is not context compatible: wrong number of rows
            {
                string parameterName = "parameter";
                string innerMessage  =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CEP_PARAMETER_IS_CONTEXT_INCOMPATIBLE") +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] {
                        context,
                        1,
                        DoubleMatrix.Dense(
                            context.InitialParameter.NumberOfRows + 1,
                            context.InitialParameter.NumberOfColumns)
                    });
                },
                    expectedInnerType: typeof(ArgumentException),
                    expectedInnerMessage: innerMessage);
            }

            // parameter is not context compatible: wrong number of columns
            {
                string parameterName = "parameter";
                string innerMessage  =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CEP_PARAMETER_IS_CONTEXT_INCOMPATIBLE") +
                    " (Parameter '" + parameterName + "')";

                var optimizer = new SystemPerformanceOptimizer();

                var context = TestableSystemPerformanceOptimizationContext00.Get().Context;

                ExceptionAssert.InnerThrow(
                    () =>
                {
                    Reflector.ExecuteBaseMember(
                        obj: optimizer,
                        methodName: "Sample",
                        methodArgs: new object[] {
                        context,
                        1,
                        DoubleMatrix.Dense(
                            context.InitialParameter.NumberOfRows,
                            context.InitialParameter.NumberOfColumns + 1)
                    });
                },
                    expectedInnerType: typeof(ArgumentException),
                    expectedInnerMessage: innerMessage);
            }
        }
Пример #14
0
        /// <summary>
        /// Explains existing clusters by selecting
        /// a number of features from the specified corresponding data set.
        /// </summary>
        /// <param name="data">
        /// The matrix whose columns contain the features observed at the
        /// items under study.
        /// </param>
        /// <param name="partition">
        /// A partition of the row indexes valid for <paramref name="data"/>.
        /// </param>
        /// <param name="numberOfExplanatoryFeatures">
        /// The number of features to be selected.
        /// </param>
        /// <remarks>
        /// <para>
        /// Method <see cref="Explain(
        /// DoubleMatrix, IndexPartition{double}, int)"/>
        /// selects the specified <paramref name="numberOfExplanatoryFeatures"/>
        /// from the given
        /// <paramref name="data"/>, by minimizing the Davies-Bouldin
        /// Index corresponding to
        /// the <paramref name="partition"/> of the items under study.
        /// </para>
        /// <para>
        /// This method uses a default Cross-Entropy context of
        /// type <see cref="CombinationOptimizationContext"/> to identify the
        /// optimal features.
        /// If different selection criteria need to be applied,
        /// or extra control on the
        /// parameters of the underlying algorithm is required,
        /// a specialized <see cref="CombinationOptimizationContext"/> can be
        /// can be instantiated and hence exploited executing
        /// method <see cref="SystemPerformanceOptimizer.Optimize(
        /// SystemPerformanceOptimizationContext, double, int)">Optimize</see>
        /// on a <see cref="SystemPerformanceOptimizer"/> object.
        /// See the documentation about <see cref="CombinationOptimizationContext"/>
        /// for additional examples.
        /// </para>
        /// </remarks>
        /// <example>
        /// <para>
        /// In the following example, an existing partition of 12 items is explained
        /// by selecting 2 features out of the seven ones available in
        /// an artificial data set regarding the items under study.
        /// </para>
        /// <para>
        /// <code title="Selecting features from a data set to explain a given partition."
        /// source="..\Novacta.Analytics.CodeExamples\ClustersExplainExample0.cs.txt"
        /// language="cs" />
        /// </para>
        /// </example>
        /// <returns>
        /// The collection of column indexes, valid for <paramref name="data"/>, that
        /// correspond to the features selected to explain the
        /// given <paramref name="partition"/> of row indexes.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="data"/> is <b>null</b>.<br/>
        /// -or-<br/>
        /// <paramref name="partition"/> is <b>null</b>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="numberOfExplanatoryFeatures"/> is not positive.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="numberOfExplanatoryFeatures"/> is not less than
        /// the number of columns in <paramref name="data"/>.<br/>
        /// -or-<br/>
        /// A part in <paramref name="partition"/> contains a position
        /// which is not valid as a row index of <paramref name="data"/>.
        /// </exception>
        /// <seealso cref="IndexPartition.DaviesBouldinIndex(
        /// DoubleMatrix, IndexPartition{double})"/>
        /// <seealso cref="CombinationOptimizationContext"/>
        /// <seealso cref="SystemPerformanceOptimizer"/>
        public static IndexCollection Explain(
            DoubleMatrix data,
            IndexPartition <double> partition,
            int numberOfExplanatoryFeatures)
        {
            #region Input validation

            if (data is null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (numberOfExplanatoryFeatures < 1)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(numberOfExplanatoryFeatures),
                          ImplementationServices.GetResourceString(
                              "STR_EXCEPT_PAR_MUST_BE_POSITIVE"));
            }

            int stateDimension = data.NumberOfColumns;

            if (stateDimension <= numberOfExplanatoryFeatures)
            {
                throw new ArgumentException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_PAR_MUST_BE_LESS_THAN_OTHER_COLUMNS"),
                              nameof(numberOfExplanatoryFeatures),
                              nameof(data)),
                          nameof(numberOfExplanatoryFeatures)
                          );
            }

            if (partition is null)
            {
                throw new ArgumentNullException(nameof(partition));
            }

            #endregion

            double objectiveFunction(DoubleMatrix x)
            {
                IndexCollection selected = x.FindNonzero();

                double performance =
                    IndexPartition.DaviesBouldinIndex(
                        data: data[":", selected],
                        partition: partition);

                return(performance);
            }

            var optimizer =
                new SystemPerformanceOptimizer();

            var context = new CombinationOptimizationContext(
                objectiveFunction: objectiveFunction,
                stateDimension: stateDimension,
                combinationDimension: numberOfExplanatoryFeatures,
                probabilitySmoothingCoefficient: .8,
                optimizationGoal: OptimizationGoal.Minimization,
                minimumNumberOfIterations: 3,
                maximumNumberOfIterations: 1000);

            double rarity = .01;

            int sampleSize = 1000 * stateDimension;

            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            var optimalState = results.OptimalState;

            return(optimalState.FindNonzero());
        }
Пример #15
0
        public void RunTest()
        {
            // Valid input - Minimization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableCombinationOptimizationContext00.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                int    sampleSize = 300;
                double rarity     = 0.01;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    delta: .03);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }

            // Valid input - Maximization
            {
                var optimizer = new SystemPerformanceOptimizer();

                // Create the context.
                var testableContext =
                    TestableCombinationOptimizationContext01.Get();

                var context = testableContext.Context;

                // Set optimization parameters.
                int    sampleSize = 300;
                double rarity     = 0.01;

                // Solve the problem.
                var results = optimizer.Optimize(
                    context,
                    rarity,
                    sampleSize);

                Assert.AreEqual(
                    expected: true,
                    actual: results.HasConverged);

                DoubleMatrixAssert.AreEqual(
                    expected: testableContext.OptimalState,
                    actual: results.OptimalState,
                    DoubleMatrixTest.Accuracy);

                Assert.AreEqual(
                    expected: testableContext.OptimalPerformance,
                    actual: results.OptimalPerformance,
                    DoubleMatrixTest.Accuracy);
            }
        }
Пример #16
0
        /// <summary>
        /// Discovers optimal clusters
        /// in a data set.
        /// </summary>
        /// <param name="maximumNumberOfParts">
        /// The maximum number of parts allowed in the optimal
        /// partition.
        /// </param>
        /// <param name="data">
        /// The matrix whose rows contain the observations for the
        /// items under study.
        /// </param>
        /// <remarks>
        /// <para>
        /// Method <see cref="Discover(DoubleMatrix, int)"/> partitions
        /// a collection of items in no more than the specified
        /// <paramref name="maximumNumberOfParts"/>,
        /// given the specified <paramref name="data"/>, by minimizing the sum of
        /// intra-cluster squared deviations.
        /// </para>
        /// <para>
        /// This method uses a default Cross-Entropy context of
        /// type <see cref="PartitionOptimizationContext"/> to identify the
        /// optimal partition.
        /// If different partitioning criteria need to be applied,
        /// or extra control on the
        /// parameters of the underlying algorithm is required,
        /// a specialized <see cref="PartitionOptimizationContext"/> can be
        /// can be instantiated and hence exploited executing
        /// method <see cref="SystemPerformanceOptimizer.Optimize(
        /// SystemPerformanceOptimizationContext, double, int)">Optimize</see>
        /// on a <see cref="SystemPerformanceOptimizer"/> object.
        /// See the documentation about <see cref="PartitionOptimizationContext"/>
        /// for additional examples.
        /// </para>
        /// </remarks>
        /// <example>
        /// <para>
        /// In the following example, a partition that optimally split 12 items
        /// is discovered
        /// given
        /// an artificial data set regarding the items under study.
        /// </para>
        /// <para>
        /// <code title="Optimal partitioning of a data set."
        /// source="..\Novacta.Analytics.CodeExamples\ClustersDiscoverExample0.cs.txt"
        /// language="cs" />
        /// </para>
        /// </example>
        /// <returns>
        /// A partition of the row indexes valid for <paramref name="data"/>.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="data"/> is <b>null</b>.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="maximumNumberOfParts"/> is not greater than one.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="maximumNumberOfParts"/> is not less than
        /// the number of rows in <paramref name="data"/>.
        /// </exception>
        /// <seealso cref="PartitionOptimizationContext"/>
        /// <seealso cref="SystemPerformanceOptimizer"/>
        public static IndexPartition <double> Discover(
            DoubleMatrix data,
            int maximumNumberOfParts)
        {
            #region Input validation

            if (data is null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            if (maximumNumberOfParts < 2)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(maximumNumberOfParts),
                          string.Format(
                              CultureInfo.InvariantCulture,
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_PAR_MUST_BE_GREATER_THAN_VALUE"),
                              "1"));
            }

            int stateDimension = data.NumberOfRows;

            if (stateDimension <= maximumNumberOfParts)
            {
                throw new ArgumentException(
                          string.Format(
                              CultureInfo.InvariantCulture,
                              ImplementationServices.GetResourceString(
                                  "STR_EXCEPT_PAR_MUST_BE_LESS_THAN_OTHER_ROWS"),
                              nameof(maximumNumberOfParts),
                              nameof(data)),
                          nameof(maximumNumberOfParts)
                          );
            }

            #endregion

            double objectiveFunction(DoubleMatrix x)
            {
                double performance = 0.0;
                var    partition   = IndexPartition.Create(x);

                foreach (double category in partition.Identifiers)
                {
                    performance += Stat.Sum(
                        Stat.SumOfSquaredDeviations(
                            data[partition[category], ":"],
                            DataOperation.OnColumns));
                }

                return(performance);
            }

            var optimizer =
                new SystemPerformanceOptimizer();

            var context = new PartitionOptimizationContext(
                objectiveFunction: objectiveFunction,
                stateDimension: stateDimension,
                partitionDimension: maximumNumberOfParts,
                probabilitySmoothingCoefficient: .8,
                optimizationGoal: OptimizationGoal.Minimization,
                minimumNumberOfIterations: 3,
                maximumNumberOfIterations: 1000);

            double rarity = .01;

            int sampleSize = 500 * maximumNumberOfParts;

            var results = optimizer.Optimize(
                context,
                rarity,
                sampleSize);

            return(IndexPartition.Create(results.OptimalState));
        }
        public void OptimizeTest()
        {
            // context is null
            {
                string parameterName = "context";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context: null,
                        rarity: 0.1,
                        sampleSize: 1000);
                },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage:
                    ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: parameterName);
            }

            // rarity is less than 0
            {
                var STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL"), 0.0, 1.0);

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: -0.1,
                        sampleSize: 1000);
                },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL,
                    expectedParameterName: parameterName);
            }

            // rarity is equal to 0
            {
                var STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL"), 0.0, 1.0);

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: 0.0,
                        sampleSize: 1000);
                },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL,
                    expectedParameterName: parameterName);
            }

            // rarity is greater than 1
            {
                var STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL"), 0.0, 1.0);

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: 1.1,
                        sampleSize: 1000);
                },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL,
                    expectedParameterName: parameterName);
            }

            // rarity is equal to 1
            {
                var STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL"), 0.0, 1.0);

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: 1.0,
                        sampleSize: 1000);
                },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    STR_EXCEPT_PAR_NOT_IN_OPEN_INTERVAL,
                    expectedParameterName: parameterName);
            }

            // rarity is too low given context and sample size
            {
                var STR_EXCEPT_CEM_TOO_LOW_RARITY =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_CEM_TOO_LOW_RARITY"), "sampleSize");

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext02
                        .Get().Context,
                        rarity: .01,
                        sampleSize: 50);
                },
                    expectedType: typeof(ArgumentException),
                    expectedPartialMessage:
                    STR_EXCEPT_CEM_TOO_LOW_RARITY,
                    expectedParameterName: parameterName);
            }

            // rarity is too high given context and sample size
            {
                var STR_EXCEPT_CEM_TOO_HIGH_RARITY =
                    String.Format(
                        ImplementationServices.GetResourceString(
                            "STR_EXCEPT_CEM_TOO_HIGH_RARITY"), "sampleSize");

                string parameterName = "rarity";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: .99,
                        sampleSize: 50);
                },
                    expectedType: typeof(ArgumentException),
                    expectedPartialMessage:
                    STR_EXCEPT_CEM_TOO_HIGH_RARITY,
                    expectedParameterName: parameterName);
            }

            // sampleSize is not positive
            {
                var STR_EXCEPT_PAR_MUST_BE_POSITIVE =
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_MUST_BE_POSITIVE");

                string parameterName = "sampleSize";

                var optimizer = new SystemPerformanceOptimizer();

                ArgumentExceptionAssert.Throw(
                    () =>
                {
                    optimizer.Optimize(
                        context:
                        TestableSystemPerformanceOptimizationContext00
                        .Get().Context,
                        rarity: 0.1,
                        sampleSize: 0);
                },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    STR_EXCEPT_PAR_MUST_BE_POSITIVE,
                    expectedParameterName: parameterName);
            }
        }