예제 #1
0
        /// <summary>
        /// Creates an automaton for validating the correctness of argument placeholders for a given argument.
        /// </summary>
        /// <param name="argToValidateIndex">The index of the argument to validate.</param>
        /// <param name="argNames">The names of all arguments.</param>
        /// <returns>The created automaton.</returns>
        private static StringAutomaton GetArgumentValidatingAutomaton(int argToValidateIndex, IReadOnlyList <string> argNames)
        {
            Debug.Assert(
                argNames != null && argNames.All(name => !string.IsNullOrEmpty(name)),
                "A valid array of argument names must be provided.");
            Debug.Assert(
                argToValidateIndex >= 0 && argToValidateIndex < argNames.Count,
                "The provided argument index must be a valid index in the argument name array.");

            string          argListKey = ArgumentListToDictionaryKey(argToValidateIndex, argNames);
            StringAutomaton result;

            if (ArgsToValidatingAutomaton.TryGetValue(argListKey, out result))
            {
                return(result);
            }

            // Accepts placeholder for the current argument
            StringAutomaton checkBracesForCurrentArg = StringAutomaton.ConstantOn(1.0, "{" + argNames[argToValidateIndex] + "}");

            StringAutomaton checkBracesForOtherArgs = DisallowBracesAutomaton.Clone();

            if (argNames.Count > 1)
            {
                // Skips placeholders for every argument except the current one
                StringAutomaton skipOtherArgs = StringAutomaton.ConstantOnElement(1.0, '{');
                skipOtherArgs.AppendInPlace(StringAutomaton.ConstantOn(1.0, argNames.Where((arg, index) => index != argToValidateIndex)));
                skipOtherArgs.AppendInPlace(StringAutomaton.ConstantOnElement(1.0, '}'));

                // Accepts placeholders for arguments other than current, with arbitrary intermediate text
                checkBracesForOtherArgs.AppendInPlace(skipOtherArgs);
                checkBracesForOtherArgs = StringAutomaton.Repeat(checkBracesForOtherArgs, minTimes: 0);
                checkBracesForOtherArgs.AppendInPlace(DisallowBracesAutomaton);
            }

            // Checks the placeholder for the current argument, then skips placeholders for other arguments
            StringAutomaton validateArgumentThenOtherArguments = checkBracesForCurrentArg.Clone();

            validateArgumentThenOtherArguments.AppendInPlace(checkBracesForOtherArgs);
            if (!RequirePlaceholderForEveryArgument)
            {
                // Make this block optional
                validateArgumentThenOtherArguments = StringAutomaton.Sum(
                    validateArgumentThenOtherArguments,
                    StringAutomaton.ConstantOn(1.0, string.Empty));
            }

            // Accepts placeholders for arguments other then current, then for the current argument, then again other placeholders
            result = checkBracesForOtherArgs.Clone();
            result.AppendInPlace(validateArgumentThenOtherArguments);

            result.TryDeterminize();
            ArgsToValidatingAutomaton[argListKey] = result;

            return(result);
        }
        public void NonNormalizableLoop3()
        {
            StringAutomaton automaton = StringAutomaton.Zero();

            automaton.Start.AddTransition('a', Weight.FromValue(2.0), automaton.Start);
            automaton.Start.EndWeight = Weight.FromValue(5.0);

            StringAutomaton copyOfAutomaton = automaton.Clone();

            Assert.Throws <InvalidOperationException>(() => automaton.NormalizeValues());
            Assert.False(copyOfAutomaton.TryNormalizeValues());
            ////Assert.Equal(f, copyOfF); // TODO: fix equality first
        }
예제 #3
0
        /// <summary>
        /// Tests if the weights of all outgoing transitions sum to one for each state of a given automaton.
        /// </summary>
        /// <param name="automaton">The automaton.</param>
        private static void AssertStochastic(StringAutomaton automaton)
        {
            StringAutomaton automatonClone = automaton.Clone();

            automatonClone.RemoveDeadStates();

            for (int i = 0; i < automatonClone.States.Count; ++i)
            {
                Weight weightSum = automatonClone.States[i].EndWeight;
                for (int j = 0; j < automatonClone.States[i].Transitions.Count; ++j)
                {
                    weightSum += automatonClone.States[i].Transitions[j].Weight;
                }

                Assert.Equal(0.0, weightSum.LogValue, 1e-6);
            }
        }
        public void NonNormalizableLoop2()
        {
            StringAutomaton automaton = StringAutomaton.Zero();

            var endState = automaton.Start.AddTransition('a', Weight.FromValue(2.0));

            endState.EndWeight = Weight.FromValue(5.0);
            endState.AddTransition('b', Weight.FromValue(0.1), automaton.Start);
            endState.AddTransition('c', Weight.FromValue(0.05), automaton.Start);
            endState.AddSelfTransition('!', Weight.FromValue(0.75));

            StringAutomaton copyOfAutomaton = automaton.Clone();

            Assert.Throws <InvalidOperationException>(() => copyOfAutomaton.NormalizeValues());
            Assert.False(copyOfAutomaton.TryNormalizeValues());
            ////Assert.Equal(f, copyOfF); // TODO: fix equality first
        }
예제 #5
0
        public void NonNormalizableLoop4()
        {
            StringAutomaton automaton = StringAutomaton.Zero();

            automaton.Start.AddSelfTransition('a', Weight.FromValue(0.1));
            var branch1 = automaton.Start.AddTransition('a', Weight.FromValue(2.0));

            branch1.AddSelfTransition('a', Weight.FromValue(2.0));
            branch1.SetEndWeight(Weight.One);
            var branch2 = automaton.Start.AddTransition('a', Weight.FromValue(2.0));

            branch2.SetEndWeight(Weight.One);

            StringAutomaton copyOfAutomaton = automaton.Clone();

            Assert.Throws <InvalidOperationException>(() => automaton.NormalizeValues());
            Assert.False(copyOfAutomaton.TryNormalizeValues());
            ////Assert.Equal(f, copyOfF); // TODO: fix equality first
        }
        public void NormalizeValuesWithNonTrivialLoop()
        {
            StringAutomaton automaton = StringAutomaton.Zero();

            var endState = automaton.Start.AddTransition('a', Weight.FromValue(2.0));

            endState.EndWeight = Weight.FromValue(5.0);
            endState.AddTransition('b', Weight.FromValue(0.1), automaton.Start);
            endState.AddTransition('c', Weight.FromValue(0.05), automaton.Start);
            endState.AddSelfTransition('!', Weight.FromValue(0.5));

            var    normalizedAutomaton = automaton.Clone();
            double logNormalizer       = normalizedAutomaton.NormalizeValues();

            Assert.Equal(Math.Log(50.0), logNormalizer, 1e-6);
            Assert.Equal(Math.Log(50.0), GetLogNormalizerByGetValue(automaton), 1e-6);
            Assert.Equal(Math.Log(50.0), GetLogNormalizerByGetValueWithTransducers(automaton), 1e-6);
            AssertStochastic(normalizedAutomaton);
            foreach (var str in new[] { "a!!", "abaca", "a!ba!!ca!!!!" })
            {
                Assert.False(double.IsNegativeInfinity(automaton.GetLogValue(str)));
                Assert.Equal(automaton.GetLogValue(str), normalizedAutomaton.GetLogValue(str) + logNormalizer, 1e-6);
            }
        }