public void ToStringTest()
        {
            // Without categories
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                string expected, actual;

                expected = name + ": []";
                actual   = target.ToString();

                Assert.AreEqual(expected, actual);
            }

            // With categories
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                string expected, actual;

                target.Add(0.0, "Zero");
                target.Add(1.0, "One");
                target.Add(2.0, "Two");

                expected = name + ": [0 - Zero, 1 - One, 2 - Two]";
                actual   = target.ToString();

                Assert.AreEqual(expected, actual);
            }
        }
示例#2
0
        public async Task TimeSeriesInsightsTypeWithCategoricalVariable_ExpectsError()
        {
            // Arrange
            TimeSeriesInsightsClient client = GetClient();
            var    timeSeriesTypes          = new List <TimeSeriesType>();
            var    tsiTypeNamePrefix        = "type";
            var    timeSeriesTypesName      = Recording.GenerateAlphaNumericId(tsiTypeNamePrefix);
            string timeSeriesTypeId         = Recording.GenerateId();

            // Build Numeric variable
            // Below is an invalid expression
            var categoricalValue    = new TimeSeriesExpression("$event");
            var category            = new TimeSeriesDefaultCategory("label");
            var categoricalVariable = new CategoricalVariable(categoricalValue, category);
            var variables           = new Dictionary <string, TimeSeriesVariable>();
            var variableNamePrefix  = "categoricalVariableName";

            variables.Add(Recording.GenerateAlphaNumericId(variableNamePrefix), categoricalVariable);

            var type = new TimeSeriesType(timeSeriesTypesName, variables);

            type.Id = timeSeriesTypeId;
            timeSeriesTypes.Add(type);

            // Act and Assert
            await TestTimeSeriesTypeWhereErrorIsExpected(client, timeSeriesTypes, timeSeriesTypesName).ConfigureAwait(false);
        }
        /// <summary>
        /// Determines whether the specified target has the
        /// expected state.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="expectedFeatureVariables">
        /// The expected feature variables.</param>
        /// <param name="expectedResponseVariable">
        /// The expected response variable.</param>
        /// <param name="expectedCategoricalEntailments">
        /// The expected categorical entailments.</param>
        /// <exception cref="AssertFailedException">
        /// Target categorical entailment ensemble classifier
        /// has an unexpected state.
        /// </exception>
        public static void IsStateAsExpected(
            CategoricalEntailmentEnsembleClassifier target,
            IReadOnlyList <CategoricalVariable> expectedFeatureVariables,
            CategoricalVariable expectedResponseVariable,
            IReadOnlyList <CategoricalEntailment> expectedCategoricalEntailments)
        {
            if (target.FeatureVariables.Count != expectedFeatureVariables.Count)
            {
                throw new AssertFailedException(
                          "The list of target feature variables has an unexpected count.");
            }

            for (int i = 0; i < expectedFeatureVariables.Count; i++)
            {
                CategoricalVariableAssert.AreEqual(
                    expectedFeatureVariables[i],
                    target.FeatureVariables[i]);
            }

            CategoricalVariableAssert.AreEqual(
                expectedResponseVariable,
                target.ResponseVariable);

            ListAssert <CategoricalEntailment> .ContainSameItems(
                expected : new List <CategoricalEntailment>(expectedCategoricalEntailments),
                actual : new List <CategoricalEntailment>(target.Entailments),
                areEqual : CategoricalEntailmentAssert.AreEqual);
        }
示例#4
0
        /// <summary>
        /// Initializes a new instance of
        /// the <see cref="CategoricalEntailmentEnsembleTrainer"/> class
        /// aimed to train the specified number of categorical
        /// entailments by exploiting the specified data sets.
        /// </summary>
        /// <param name="initialCategoricalEntailments">
        /// The collection of initial categorical entailments.
        /// It can be empty: see <see cref="entailments"/>.
        /// </param>
        /// <param name="numberOfTrainedCategoricalEntailments">
        /// The number of categorical entailments
        /// to be trained.
        /// </param>
        /// <param name="features">
        /// The data set containing the training features.
        /// </param>
        /// <param name="response">
        /// The data set containing the training response.
        /// </param>
        /// <param name="allowEntailmentPartialTruthValues">
        /// If set to <c>true</c> signals that the truth value of a
        /// categorical entailment must be equal to the homogeneity
        /// of the probability distribution from which its conclusion has been
        /// drawn. Otherwise, the truth value is unity.
        /// </param>
        /// <param name="trainSequentially">
        /// If set to <c>true</c> signals that the ensemble is trained
        /// sequentially, i.e. it starts as an empty collection, and new
        /// categorical entailments are added through a step-by-step
        /// procedure to the trained ensemble,
        /// by selecting, at each step, the entailment that better
        /// improves the system's performance of the current ensemble.
        /// Otherwise, the categorical entailments are trained simultaneously.
        /// </param>
        public CategoricalEntailmentEnsembleTrainer(
            IReadOnlyList <CategoricalEntailment> initialCategoricalEntailments,
            int numberOfTrainedCategoricalEntailments,
            CategoricalDataSet features,
            CategoricalDataSet response,
            bool allowEntailmentPartialTruthValues,
            bool trainSequentially)
        {
            this.trainSequentially = trainSequentially;

            this.entailments =
                new List <CategoricalEntailment>(initialCategoricalEntailments);

            this.numberOfTrainedCategoricalEntailments = numberOfTrainedCategoricalEntailments;

            var responseVariable = response.Variables[0];
            var featureVariables = features.Variables;

            List <int> featureCategoryCounts            = new(featureVariables.Count);
            int        overallNumberOfFeatureCategories = 0;

            for (int j = 0; j < featureVariables.Count; j++)
            {
                int currentFeatureNumberOfCategories =
                    featureVariables[j].NumberOfCategories;
                featureCategoryCounts.Add(currentFeatureNumberOfCategories);
                overallNumberOfFeatureCategories += currentFeatureNumberOfCategories;
            }
            this.featureCategoryCounts      = featureCategoryCounts;
            this.numberOfResponseCategories = responseVariable.NumberOfCategories;

            this.overallNumberOfCategories = overallNumberOfFeatureCategories +
                                             this.numberOfResponseCategories;
            this.entailmentRepresentationLength = this.overallNumberOfCategories + 1;

            this.responseCodeIndexPairs = new SortedList <double, int>();
            int c = 0;

            foreach (var code in responseVariable.CategoryCodes)
            {
                this.responseCodeIndexPairs[code] = c;
                c++;
            }

            this.randomNumberGeneratorPool =
                new ConcurrentDictionary <int, RandomNumberGenerator>();

            this.featuresData = new DoubleMatrix[features.NumberOfRows];
            for (int i = 0; i < this.featuresData.Length; i++)
            {
                this.featuresData[i] = features.Data[i, ":"];
            }

            this.allowEntailmentPartialTruthValues = allowEntailmentPartialTruthValues;
            this.responseData     = response.Data;
            this.FeatureVariables = features.Variables;
            this.ResponseVariable = response.Variables[0];
        }
        public void AddByCodeOnlyTest()
        {
            // code already exists
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    2.0
                };

                ExceptionAssert.Throw(
                    () => { target.Add(2.0); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_ALREADY_EXISTS_IN_VARIABLE_LIST"));
            }

            // target is read only
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                target.SetAsReadOnly();

                ExceptionAssert.Throw(
                    () => { target.Add(3.0); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));
            }

            // Valid input
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                double   code;
                Category category0, category1;

                code = 1.0;
                target.Add(code);
                category0 = new Category(code);

                code = 2.0;
                target.Add(code);
                category1 = new Category(code);

                CategoricalVariableAssert.IsStateAsExpected(
                    target,
                    name,
                    expectedCategories: new List <Category>(2)
                {
                    category0,
                    category1
                },
                    expectedReadOnlyFlag: false);
            }
        }
        public void TryGetByLabelTest()
        {
            // Getting existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                Category expectedCategory;
                bool     actualFlag, expectedFlag;
                string   categoryLabel;

                categoryLabel = "One";

                actualFlag = target.TryGet(
                    categoryLabel, out Category actualCategory);

                expectedFlag     = true;
                expectedCategory = new Category(1.0, categoryLabel);

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoryAssert.AreEqual(expectedCategory, actualCategory);
            }

            // Getting not existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                Category expectedCategory;
                bool     actualFlag, expectedFlag;
                string   categoryLabel;

                categoryLabel = "Three";

                actualFlag = target.TryGet(
                    categoryLabel, out Category actualCategory);

                expectedFlag     = false;
                expectedCategory = null;

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoryAssert.AreEqual(expectedCategory, actualCategory);
            }
        }
        public void TryGetByCodeTest()
        {
            // Getting existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                bool   actualFlag, expectedFlag;
                double categoryCode;

                categoryCode = 1.0;

                actualFlag = target.TryGet(
                    categoryCode, out Category actualCategory);

                expectedFlag = true;
                Category expectedCategory = new(categoryCode, "One");

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoryAssert.AreEqual(expectedCategory, actualCategory);
            }

            // Getting not existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                Category expectedCategory;
                bool     actualFlag, expectedFlag;
                double   categoryCode;

                categoryCode = 3.0;

                actualFlag = target.TryGet(
                    categoryCode, out Category actualCategory);

                expectedFlag     = false;
                expectedCategory = null;

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoryAssert.AreEqual(expectedCategory, actualCategory);
            }
        }
        public void SetAsReadOnlyTest()
        {
            string expectedName = "The name";

            var target = new CategoricalVariable(expectedName);

            target.SetAsReadOnly();

            CategoricalVariableAssert.IsStateAsExpected(
                target,
                expectedName,
                expectedCategories: new List <Category>(),
                expectedReadOnlyFlag: true);
        }
示例#9
0
        /// <summary>Initializes a new instance of the
        /// <see cref="TestablePartitionOptimizationContext"/>
        /// class.</summary>
        /// <param name="context">The context to test.</param>
        /// <param name="stateDimension">The expected state dimension.</param>
        /// <param name="eliteSampleDefinition">The expected elite sample definition.</param>
        /// <param name="traceExecution">The expected value about tracing context execution.</param>
        /// <param name="optimizationGoal">The expected optimization goal.</param>
        /// <param name="initialParameter">The expected initial parameter.</param>
        /// <param name="minimumNumberOfIterations">
        /// The expected minimum number of iterations.</param>
        /// <param name="maximumNumberOfIterations">
        /// The expected maximum number of iterations.</param>
        /// <param name="optimalState">The expected optimal state.</param>
        /// <param name="optimalPerformance">The expected optimal performance.</param>
        /// <param name="objectiveFunction">The expected objective function.</param>
        /// <param name="featureVariables">
        /// The expected feature variables.</param>
        /// <param name="responseVariable">
        /// The expected response variable.</param>
        /// <param name="numberOfResponseCategories">
        /// The expected number of response categories</param>
        /// <param name="numberOfCategoricalEntailments">
        /// The expected number of categorical entailments.
        /// </param>
        /// <param name="allowEntailmentPartialTruthValues">
        /// The expected allowance for entailment partial truth values.
        /// </param>
        /// <param name="probabilitySmoothingCoefficient">
        /// The expected probability smoothing coefficient.</param>
        public TestableCategoricalEntailmentEnsembleOptimizationContext(
            CategoricalEntailmentEnsembleOptimizationContext context,
            int stateDimension,
            EliteSampleDefinition eliteSampleDefinition,
            bool traceExecution,
            OptimizationGoal optimizationGoal,
            DoubleMatrix initialParameter,
            int minimumNumberOfIterations,
            int maximumNumberOfIterations,
            DoubleMatrix optimalState,
            double optimalPerformance,
            Func <DoubleMatrix, double> objectiveFunction,
            List <CategoricalVariable> featureVariables,
            CategoricalVariable responseVariable,
            int numberOfResponseCategories,
            int numberOfCategoricalEntailments,
            bool allowEntailmentPartialTruthValues,
            double probabilitySmoothingCoefficient
            ) : base(
                context,
                stateDimension,
                eliteSampleDefinition,
                traceExecution,
                optimizationGoal,
                initialParameter,
                minimumNumberOfIterations,
                maximumNumberOfIterations,
                optimalState,
                optimalPerformance)
        {
            this.ObjectiveFunction = objectiveFunction;
            this.FeatureVariables  = featureVariables;
            this.ResponseVariable  = responseVariable;

            var featureCategoryCounts = new List <int>(featureVariables.Count);

            for (int i = 0; i < featureVariables.Count; i++)
            {
                featureCategoryCounts.Add(featureVariables[i].NumberOfCategories);
            }
            this.FeatureCategoryCounts = featureCategoryCounts;

            this.NumberOfResponseCategories        = numberOfResponseCategories;
            this.NumberOfCategoricalEntailments    = numberOfCategoricalEntailments;
            this.AllowEntailmentPartialTruthValues = allowEntailmentPartialTruthValues;
            this.ProbabilitySmoothingCoefficient   = probabilitySmoothingCoefficient;
        }
        public void ConstructorTest()
        {
            // name is null
            {
                ArgumentExceptionAssert.Throw(
                    () => { new CategoricalVariable(null); },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "name");
            }

            // name is white space
            {
                ArgumentExceptionAssert.Throw(
                    () => { new CategoricalVariable(" "); },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "name");
            }

            // name is empty
            {
                ArgumentExceptionAssert.Throw(
                    () => { new CategoricalVariable(string.Empty); },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage:
                    ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "name");
            }

            // Valid name
            {
                string expectedName = "The name";

                var target = new CategoricalVariable(expectedName);

                CategoricalVariableAssert.IsStateAsExpected(
                    target,
                    expectedName,
                    expectedCategories: new List <Category>(),
                    expectedReadOnlyFlag: false);
            }
        }
        /// <summary>
        /// Verifies that specified categorical variables are equal.
        /// </summary>
        /// <param name="expected">The expected categorical variable.</param>
        /// <param name="actual">The actual categorical variable.</param>
        /// <exception cref="AssertFailedException">
        /// One categorical variable is <b>null</b>, the other is not.<br/>
        /// -or- <br/>
        /// Categorical variables have different names.<br/>
        /// -or- <br/>
        /// Categorical variables have different descriptions.<br/>
        /// -or- <br/>
        /// One categorical variable is read only, the other is not.<br/>
        /// -or- <br/>
        /// Categorical variables have different numbers of categories.
        /// </exception>
        public static void AreEqual(
            CategoricalVariable expected,
            CategoricalVariable actual)
        {
            if (null == expected && null == actual)
            {
                return;
            }

            if (((null == expected) && (null != actual))
                ||
                ((null != expected) && (null == actual)))
            {
                throw new AssertFailedException(
                          "One categorical variable is null, the other is not.");
            }

            if (expected.Name != actual.Name)
            {
                throw new AssertFailedException(
                          "Categorical variables have different names.");
            }

            if (expected.IsReadOnly != actual.IsReadOnly)
            {
                throw new AssertFailedException(
                          "One categorical variable is read only, the other is not.");
            }

            if (expected.Categories.Count != actual.Categories.Count)
            {
                throw new AssertFailedException(
                          "Categorical variables have different numbers of categories.");
            }

            for (int i = 0; i < expected.Categories.Count; i++)
            {
                CategoryAssert.AreEqual(expected.Categories[i], actual.Categories[i]);
            }
        }
        /// <summary>
        /// Determines whether the specified target has the
        /// expected state.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="expectedName">The expected name.</param>
        /// <param name="expectedCategories">The expected categories.</param>
        /// <param name="expectedReadOnlyFlag">
        /// If set to <c>true</c>, the target is expected to be
        /// read-only; otherwise, <c>false</c>.</param>
        /// <exception cref="AssertFailedException">
        /// Target categorical variable has an unexpected state.
        /// </exception>
        public static void IsStateAsExpected(
            CategoricalVariable target,
            string expectedName,
            List <Category> expectedCategories,
            bool expectedReadOnlyFlag)
        {
            var actualName = (string)Reflector.GetField(target, "name");

            Assert.AreEqual(expectedName, actualName);
            Assert.AreEqual(expectedName, target.Name);

            if (target.Categories.Count != expectedCategories.Count)
            {
                throw new AssertFailedException(
                          "Target categorical variable has an unexpected number " +
                          "of categories.");
            }

            Assert.AreEqual(expectedCategories.Count, target.NumberOfCategories);

            for (int i = 0; i < expectedCategories.Count; i++)
            {
                CategoryAssert.AreEqual(expectedCategories[i], target.Categories[i]);
            }

            int j = 0;

            foreach (var code in target.CategoryCodes)
            {
                Assert.AreEqual(target.Categories[j++].Code, code);
            }

            j = 0;
            foreach (var label in target.CategoryLabels)
            {
                Assert.AreEqual(target.Categories[j++].Label, label);
            }

            Assert.AreEqual(expectedReadOnlyFlag, target.IsReadOnly);
        }
        public void ToDoubleMatrixByMethodTest()
        {
            // value is null
            {
                CategoricalVariable target = null;

                ArgumentExceptionAssert.Throw(
                    () => { var result = CategoricalVariable.ToDoubleMatrix(target); },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "value");
            }

            // Valid input
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                var expected = DoubleMatrix.Dense(3, 1,
                                                  new double[3] {
                    0.0, 1.0, 2.0
                });
                expected.Name = target.Name;
                expected.SetRowName(0, "Zero");
                expected.SetRowName(1, "One");
                expected.SetRowName(2, "Two");

                DoubleMatrix actual = CategoricalVariable.ToDoubleMatrix(target);

                DoubleMatrixAssert.AreEqual(expected, actual, 1e-2);
            }
        }
        public void RemoveByCodeTest()
        {
            // Removing existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                CategoricalVariable actualVariable, expectedVariable;
                bool   actualFlag, expectedFlag;
                double categoryCode;

                categoryCode = 1.0;

                actualFlag     = target.Remove(categoryCode);
                actualVariable = target;

                expectedFlag = true;

                expectedVariable = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 2.0, "Two" }
                };

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoricalVariableAssert.AreEqual(expectedVariable, actualVariable);
            }

            // Removing not existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                CategoricalVariable actualVariable, expectedVariable;
                bool   actualFlag, expectedFlag;
                double categoryCode;

                categoryCode = 3.0;

                actualFlag     = target.Remove(categoryCode);
                actualVariable = target;

                expectedFlag = false;

                expectedVariable = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoricalVariableAssert.AreEqual(expectedVariable, actualVariable);
            }

            // Removing categories in read-only variables
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                target.SetAsReadOnly();

                ExceptionAssert.Throw(
                    () => { target.Remove(3.0); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));

                ExceptionAssert.Throw(
                    () => { target.Remove(1.0); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));
            }
        }
        public void NameSetTest()
        {
            // value is null
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Name = null; },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "value");
            }

            // name is white space
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Name = " "; },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "value");
            }

            // name is empty
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Name = string.Empty; },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "value");
            }

            // target is read only
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);
                target.SetAsReadOnly();

                ExceptionAssert.Throw(
                    () => { target.Name = "New name"; },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));
            }

            // Valid input
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                string expected, actual;

                expected = "New name";

                target.Name = expected;

                actual = target.Name;

                Assert.AreEqual(expected, actual);
            }
        }
        public void AddTest()
        {
            // code already exists
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    2.0
                };

                ExceptionAssert.Throw(
                    () => { target.Add(2.0, "second two"); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_ALREADY_EXISTS_IN_VARIABLE_LIST"));
            }

            // label already exists
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 2.0, "two" }
                };

                ExceptionAssert.Throw(
                    () => { target.Add(2.000001, "two"); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_ALREADY_EXISTS_IN_VARIABLE_LIST"));
            }

            // label is null
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Add(3.0, null); },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "label");
            }

            // label is white space
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Add(3.0, " "); },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "label");
            }

            // label is empty
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                ArgumentExceptionAssert.Throw(
                    () => { target.Add(3.0, string.Empty); },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_STRING_IS_EMPTY_OR_WHITESPACE"),
                    expectedParameterName: "label");
            }

            // target is read only
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                target.SetAsReadOnly();

                ExceptionAssert.Throw(
                    () => { target.Add(3.0, "three"); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));
            }

            // Valid input
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name);

                double   code;
                string   label;
                Category category0, category1;

                code  = 1.0;
                label = "one";
                target.Add(code, label);
                category0 = new Category(code, label);

                code  = 2.0;
                label = "two";
                target.Add(code, label);
                category1 = new Category(code, label);

                CategoricalVariableAssert.IsStateAsExpected(
                    target,
                    name,
                    expectedCategories: new List <Category>(2)
                {
                    category0,
                    category1
                },
                    expectedReadOnlyFlag: false);
            }
        }
        /// <summary>
        /// Determines whether the specified target has the
        /// expected state.
        /// </summary>
        /// <param name="target">The target.</param>
        /// <param name="expectedFeatureVariables">
        /// The expected feature variables.</param>
        /// <param name="expectedResponseVariable">
        /// The expected response variable.</param>
        /// <param name="expectedFeaturePremises">
        /// The expected feature premises.</param>
        /// <param name="expectedResponseConclusion">
        /// The expected response conclusion.</param>
        /// <param name="expectedTruthValue">
        /// The expected truth value.</param>
        /// <exception cref="AssertFailedException">
        /// Target categorical entailment has an unexpected state.
        /// </exception>
        public static void IsStateAsExpected(
            CategoricalEntailment target,
            IReadOnlyList <CategoricalVariable> expectedFeatureVariables,
            CategoricalVariable expectedResponseVariable,
            IReadOnlyList <SortedSet <double> > expectedFeaturePremises,
            double expectedResponseConclusion,
            double expectedTruthValue)
        {
            if (target.FeatureVariables.Count != expectedFeatureVariables.Count)
            {
                throw new AssertFailedException(
                          "The list of target feature variables has an unexpected count.");
            }

            for (int i = 0; i < expectedFeatureVariables.Count; i++)
            {
                CategoricalVariableAssert.AreEqual(
                    expectedFeatureVariables[i],
                    target.FeatureVariables[i]);
            }

            CategoricalVariableAssert.AreEqual(
                expectedResponseVariable,
                target.ResponseVariable);

            var targetFeaturePremises =
                (List <SortedSet <double> >)Reflector.GetField(target, "featurePremises");

            for (int i = 0; i < expectedFeaturePremises.Count; i++)
            {
                if (!expectedFeaturePremises[i].SetEquals(
                        target.FeaturePremises[i]))
                {
                    throw new AssertFailedException(
                              "The target feature premises are not as expected.");
                }

                if (!expectedFeaturePremises[i].SetEquals(
                        targetFeaturePremises[i]))
                {
                    throw new AssertFailedException(
                              "The target feature premises are not as expected.");
                }
            }

            bool[] expectedIsProperPremise = new bool[expectedFeaturePremises.Count];
            for (int i = 0; i < expectedFeaturePremises.Count; i++)
            {
                expectedIsProperPremise[i] = !(
                    expectedFeaturePremises[i].Count == 0
                    ||
                    expectedFeaturePremises[i].Count == expectedFeatureVariables[i].NumberOfCategories);
            }

            bool[] actualIsProperPremise =
                (bool[])Reflector.GetField(target, "isNonemptyProperPremise");

            ArrayAssert <bool> .AreEqual(
                expected : expectedIsProperPremise,
                actual : actualIsProperPremise);

            Assert.AreEqual(
                expected: expectedResponseConclusion,
                actual: target.ResponseConclusion,
                delta: DoubleMatrixTest.Accuracy);

            Assert.AreEqual(
                expected: expectedTruthValue,
                actual: target.TruthValue,
                delta: DoubleMatrixTest.Accuracy);
        }
        public async Task TimeSeriesInsightsQuery_AggregateSeriesWithCategoricalVariable()
        {
            // Arrange
            TimeSeriesInsightsClient tsiClient    = GetClient();
            DeviceClient             deviceClient = await GetDeviceClient().ConfigureAwait(false);

            // Figure out what the Time Series Id is composed of
            TimeSeriesModelSettings modelSettings = await tsiClient.ModelSettings.GetAsync().ConfigureAwait(false);

            // Create a Time Series Id where the number of keys that make up the Time Series Id is fetched from Model Settings
            TimeSeriesId tsiId = await GetUniqueTimeSeriesInstanceIdAsync(tsiClient, modelSettings.TimeSeriesIdProperties.Count)
                                 .ConfigureAwait(false);

            try
            {
                // Send some events to the IoT hub with with a second between each event
                await QueryTestsHelper.SendEventsToHubAsync(
                    deviceClient,
                    tsiId,
                    modelSettings.TimeSeriesIdProperties.ToArray(),
                    30)
                .ConfigureAwait(false);

                DateTimeOffset now       = Recording.UtcNow;
                DateTimeOffset endTime   = now.AddMinutes(10);
                DateTimeOffset startTime = now.AddMinutes(-10);

                var queryAggregateSeriesRequestOptions = new QueryAggregateSeriesRequestOptions();

                var categoricalVariable = new CategoricalVariable(
                    new TimeSeriesExpression($"tolong($event.{QueryTestsHelper.Temperature}.Double)"),
                    new TimeSeriesDefaultCategory("N/A"));
                categoricalVariable.Categories.Add(new TimeSeriesAggregateCategory("good", new List <object> {
                    1
                }));

                queryAggregateSeriesRequestOptions.InlineVariables["categorical"] = categoricalVariable;

                await TestRetryHelper.RetryAsync <AsyncPageable <QueryResultPage> >(async() =>
                {
                    QueryAnalyzer queryAggregateSeriesPages = tsiClient.Queries.CreateAggregateSeriesQueryAnalyzer(
                        tsiId,
                        startTime,
                        endTime,
                        TimeSpan.FromSeconds(5),
                        queryAggregateSeriesRequestOptions);

                    await foreach (TimeSeriesPoint point in queryAggregateSeriesPages.GetResultsAsync())
                    {
                        point.GetUniquePropertyNames().Should().HaveCount(3)
                        .And
                        .Contain((property) => property == "categorical[good]")
                        .And
                        .Contain((property) => property == "categorical[N/A]");
                    }

                    return(null);
                }, MaxNumberOfRetries, s_retryDelay);
            }
            finally
            {
                deviceClient?.Dispose();
            }
        }
        public void FromDoubleMatrixByMethodTest()
        {
            // With named rows
            {
                string name = "The name";

                var target = DoubleMatrix.Dense(3, 1,
                                                new double[3] {
                    0.0, 1.0, 2.0
                });
                target.Name = name;
                target.SetRowName(0, "Zero");
                target.SetRowName(1, "One");
                target.SetRowName(2, "Two");

                var actual = CategoricalVariable.FromDoubleMatrix(target);

                var expected = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                CategoricalVariableAssert.AreEqual(expected, actual);
            }

            // With unnamed rows
            {
                string name = "The name";

                var target = DoubleMatrix.Dense(3, 1,
                                                new double[3] {
                    0.0, 1.0, 2.0
                });
                target.Name = name;

                var actual = CategoricalVariable.FromDoubleMatrix(target);

                var expected = new CategoricalVariable(name)
                {
                    0.0,
                    1.0,
                    2.0
                };

                CategoricalVariableAssert.AreEqual(expected, actual);
            }

            // value is null
            {
                DoubleMatrix target = null;

                ArgumentExceptionAssert.Throw(
                    () => { var result = CategoricalVariable.FromDoubleMatrix(target); },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "value");
            }

            // value is not a column vector
            {
                var target = DoubleMatrix.Dense(2, 3);

                ArgumentExceptionAssert.Throw(
                    () => { var result = CategoricalVariable.FromDoubleMatrix(target); },
                    expectedType: typeof(ArgumentOutOfRangeException),
                    expectedPartialMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_PAR_MUST_BE_COLUMN_VECTOR"),
                    expectedParameterName: "value");
            }
        }
        public void RemoveByLabelTest()
        {
            // Removing existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                CategoricalVariable actualVariable, expectedVariable;
                bool   actualFlag, expectedFlag;
                string categoryLabel;

                categoryLabel = "One";

                actualFlag     = target.Remove(categoryLabel);
                actualVariable = target;

                expectedFlag = true;

                expectedVariable = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 2.0, "Two" }
                };

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoricalVariableAssert.AreEqual(expectedVariable, actualVariable);
            }

            // Removing not existing category
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                CategoricalVariable actualVariable, expectedVariable;
                bool   actualFlag, expectedFlag;
                string categoryLabel;

                categoryLabel = "Three";

                actualFlag     = target.Remove(categoryLabel);
                actualVariable = target;

                expectedFlag = false;

                expectedVariable = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                Assert.AreEqual(expectedFlag, actualFlag);
                CategoricalVariableAssert.AreEqual(expectedVariable, actualVariable);
            }

            // label is null
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                ArgumentExceptionAssert.Throw(
                    () => { target.Remove(null); },
                    expectedType: typeof(ArgumentNullException),
                    expectedPartialMessage: ArgumentExceptionAssert.NullPartialMessage,
                    expectedParameterName: "label");
            }

            // Removing categories in read-only variables
            {
                string name   = "The name";
                var    target = new CategoricalVariable(name)
                {
                    { 0.0, "Zero" },
                    { 1.0, "One" },
                    { 2.0, "Two" }
                };

                target.SetAsReadOnly();

                ExceptionAssert.Throw(
                    () => { target.Remove("One"); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));

                ExceptionAssert.Throw(
                    () => { target.Remove("Three"); },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: ImplementationServices.GetResourceString(
                        "STR_EXCEPT_CAT_VARIABLE_IS_READONLY"));
            }
        }
        public void GetEnumeratorTest()
        {
            // IEnumerable.GetEnumerator
            {
                var target = new CategoricalVariable("V")
                {
                    0, 1, 2
                };
                IEnumerable enumerable = (IEnumerable)target;

                IEnumerator enumerator = enumerable.GetEnumerator();
                object      current;
                int         index = 0;

                while (enumerator.MoveNext())
                {
                    current = enumerator.Current;
                    Assert.AreEqual(target.Categories[index], (Category)current);
                    index++;
                }

                // reset
                enumerator.Reset();

                // dispose
                enumerator = null;
                GC.Collect(10, GCCollectionMode.Forced);
            }

            // IEnumerable<Category>.GetEnumerator
            {
                var target = new CategoricalVariable("V")
                {
                    0, 1, 2
                };
                IEnumerable <Category> enumerable = (IEnumerable <Category>)target;

                IEnumerator <Category> enumerator = enumerable.GetEnumerator();

                int      index = 0;
                Category current;

                while (enumerator.MoveNext())
                {
                    current = enumerator.Current;
                    Assert.AreEqual(target.Categories[index], current);
                    index++;
                }

                // reset
                enumerator.Reset();

                // dispose
                enumerator.Dispose();
            }

            // IEnumerable<Category>.Current returns null
            {
                var target = new CategoricalVariable("V")
                {
                    0, 1, 2
                };
                var enumerable = (IEnumerable <Category>)target;

                var enumerator = enumerable.GetEnumerator();

                Assert.IsNull(enumerator.Current);
            }

            // IEnumerable.Current fails
            {
                string STR_EXCEPT_ENU_OUT_OF_BOUNDS =
                    "Enumeration has either not started or has already finished.";
                var target = new CategoricalVariable("V")
                {
                    0, 1, 2
                };
                var enumerable = (IEnumerable)target;

                var enumerator = enumerable.GetEnumerator();

                ExceptionAssert.Throw(
                    () =>
                {
                    object current = enumerator.Current;
                },
                    expectedType: typeof(InvalidOperationException),
                    expectedMessage: STR_EXCEPT_ENU_OUT_OF_BOUNDS);
            }

            // valid input
            {
                var target = new CategoricalVariable("V")
                {
                    { 0, "A" },
                    { 1, "B" },
                    { 2, "C" }
                };

                Category[] expected = new Category[3] {
                    new Category(0, "A"),
                    new Category(1, "B"),
                    new Category(2, "C")
                };

                int index = 0;
                foreach (var category in target)
                {
                    CategoryAssert.AreEqual(
                        expected: expected[index],
                        actual: category);
                    index++;
                }
            }
        }