public static StringDistribution SubAverageConditional(StringDistribution str, int start, int minLength, int maxLength) { Argument.CheckIfNotNull(str, "str"); Argument.CheckIfInRange(start >= 0, "start", "Start index must be non-negative."); Argument.CheckIfInRange(minLength >= 0, "minLength", "Min length must be non-negative."); Argument.CheckIfInRange(maxLength >= 0, "maxLength", "Max length must be non-negative."); if (str.IsPointMass) { var strPoint = str.Point; var alts = new HashSet <string>(); for (int length = minLength; length <= maxLength; length++) { var s = strPoint.Substring(start, Math.Min(length, strPoint.Length)); alts.Add(s); } return(StringDistribution.OneOf(alts)); } var anyChar = StringAutomaton.ConstantOnElement(1.0, ImmutableDiscreteChar.Any()); var transducer = StringTransducer.Consume(StringAutomaton.Repeat(anyChar, minTimes: start, maxTimes: start)); transducer.AppendInPlace(StringTransducer.Copy(StringAutomaton.Repeat(anyChar, minTimes: minLength, maxTimes: maxLength))); transducer.AppendInPlace(StringTransducer.Consume(StringAutomaton.Constant(1.0))); return(StringDistribution.FromWeightFunction(transducer.ProjectSource(str.ToAutomaton()))); }
public void SampleGeometric() { Rand.Restart(96); const double StoppingProbability = 0.7; // The length of sequences sampled from this distribution must follow a geometric distribution StringAutomaton automaton = StringAutomaton.Zero(); automaton.Start = automaton.AddState(); automaton.Start.SetEndWeight(Weight.FromValue(StoppingProbability)); automaton.Start.AddTransition('a', Weight.FromValue(1 - StoppingProbability), automaton.Start); StringDistribution dist = StringDistribution.FromWeightFunction(automaton); var acc = new MeanVarianceAccumulator(); const int SampleCount = 30000; for (int i = 0; i < SampleCount; ++i) { string sample = dist.Sample(); acc.Add(sample.Length); } const double ExpectedMean = (1.0 - StoppingProbability) / StoppingProbability; const double ExpectedVariance = (1.0 - StoppingProbability) / (StoppingProbability * StoppingProbability); Assert.Equal(ExpectedMean, acc.Mean, 1e-2); Assert.Equal(ExpectedVariance, acc.Variance, 1e-2); }
public void LoopyArithmetic() { StringAutomaton automaton1 = StringAutomaton.Zero(); automaton1.Start.AddTransition('a', Weight.FromValue(4.0)).AddTransition('b', Weight.One, automaton1.Start).EndWeight = Weight.One; StringAutomaton automaton2 = StringAutomaton.Zero(); automaton2.Start.AddSelfTransition('a', Weight.FromValue(2)).AddSelfTransition('b', Weight.FromValue(3)).EndWeight = Weight.One; StringAutomaton sum = automaton1.Sum(automaton2); StringInferenceTestUtilities.TestValue(sum, 2.0, string.Empty); StringInferenceTestUtilities.TestValue(sum, 4.0 + 6.0, "ab"); StringInferenceTestUtilities.TestValue(sum, 16.0 + 36.0, "abab"); StringInferenceTestUtilities.TestValue(sum, 12.0, "aab", "aba", "baa"); StringInferenceTestUtilities.TestValue(sum, 18.0, "abb", "bab", "bba"); StringInferenceTestUtilities.TestValue(sum, 8.0, "aaa"); StringInferenceTestUtilities.TestValue(sum, 27.0, "bbb"); StringAutomaton product = automaton1.Product(automaton2); StringInferenceTestUtilities.TestValue(product, 1.0, string.Empty); StringInferenceTestUtilities.TestValue(product, 4 * 6, "ab"); StringInferenceTestUtilities.TestValue(product, 16 * 36, "abab"); StringInferenceTestUtilities.TestValue(product, 0.0, "aba", "bbb", "a", "b"); product.SetToProduct(product, product); StringInferenceTestUtilities.TestValue(product, 1.0, string.Empty); StringInferenceTestUtilities.TestValue(product, 4 * 4 * 6 * 6, "ab"); StringInferenceTestUtilities.TestValue(product, 16 * 16 * 36 * 36, "abab"); StringInferenceTestUtilities.TestValue(product, 0.0, "aba", "bbb", "a", "b"); }
public void NoPoint1() { StringAutomaton f = StringAutomaton.Zero(); f.Start.AddTransition('a', Weight.FromValue(0.5)).AddTransition('b', Weight.FromValue(0.5), f.Start).EndWeight = Weight.One; Assert.Null(f.TryComputePoint()); }
public void Transpose() { StringTransducer transducer = StringTransducer.Consume(StringAutomaton.Constant(3.0)); StringTransducer transpose1 = StringTransducer.Transpose(transducer); StringTransducer transpose2 = transducer.Clone(); transpose2.TransposeInPlace(); var pairs = new[] { new[] { "a", string.Empty }, new[] { string.Empty, string.Empty }, new[] { "a", "bc" }, new[] { "a", "a" } }; foreach (string[] valuePair in pairs) { double referenceValue1 = transducer.GetValue(valuePair[0], valuePair[1]); Assert.Equal(referenceValue1, transpose1.GetValue(valuePair[1], valuePair[0])); Assert.Equal(referenceValue1, transpose2.GetValue(valuePair[1], valuePair[0])); double referenceValue2 = transducer.GetValue(valuePair[1], valuePair[0]); Assert.Equal(referenceValue2, transpose1.GetValue(valuePair[0], valuePair[1])); Assert.Equal(referenceValue2, transpose2.GetValue(valuePair[0], valuePair[1])); } }
public void Copy() { StringTransducer copy = StringTransducer.Copy(); StringInferenceTestUtilities.TestTransducerValue(copy, "important", "important", 1.0); StringInferenceTestUtilities.TestTransducerValue(copy, "important", "i", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "important", "imp", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "important", "t", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "important", "mpo", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, string.Empty, string.Empty, 1.0); StringInferenceTestUtilities.TestTransducerValue(copy, "important", string.Empty, 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, string.Empty, "important", 0.0); //// Test that projection on Copy() doesn't change the automaton StringAutomaton automaton = StringAutomaton.ConstantOn(2.0, "a", "ab", "ac"); automaton = automaton.Sum(StringAutomaton.ConstantOn(1.0, "a")); automaton = automaton.Sum(StringAutomaton.Constant(2.0)); automaton = automaton.Product(StringAutomaton.Constant(3.0)); StringAutomaton automatonClone = copy.ProjectSource(automaton); Assert.Equal(automaton, automatonClone); }
public void CopyElement() { StringTransducer copy = StringTransducer.CopyElement(DiscreteChar.OneOf('a', 'b')); StringInferenceTestUtilities.TestTransducerValue(copy, "a", "a", 1.0); StringInferenceTestUtilities.TestTransducerValue(copy, "b", "b", 1.0); StringInferenceTestUtilities.TestTransducerValue(copy, "a", "b", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "b", "a", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, string.Empty, string.Empty, 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "bb", "bb", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "bab", "bab", 0.0); StringInferenceTestUtilities.TestTransducerValue(copy, "bab", "ba", 0.0); //// Tests that projection on CopyElement(elements) shrinks the support StringAutomaton automaton = StringAutomaton.ConstantOn(2.0, "a", "ab", "ac"); automaton = automaton.Sum(StringAutomaton.ConstantOn(1.0, "a")); automaton = automaton.Sum(StringAutomaton.Constant(2.0)); automaton = automaton.Product(StringAutomaton.Constant(3.0)); for (int i = 0; i < 2; ++i) { StringInferenceTestUtilities.TestValue(automaton, 15, "a"); StringInferenceTestUtilities.TestValue(automaton, 6.0, "b"); StringInferenceTestUtilities.TestValue(automaton, i == 0 ? 6.0 : 0.0, string.Empty); StringInferenceTestUtilities.TestValue(automaton, i == 0 ? 12.0 : 0.0, "ac", "ab"); automaton = copy.ProjectSource(automaton); } }
/// <summary>EP message to <c>str</c>.</summary> /// <param name="format">Incoming message from <c>format</c>.</param> /// <param name="args">Incoming message from <c>args</c>.</param> /// <returns>The outgoing EP message to the <c>str</c> argument.</returns> /// <remarks> /// <para>The outgoing message is a distribution matching the moments of <c>str</c> as the random arguments are varied. The formula is <c>proj[p(str) sum_(format,args) p(format,args) factor(str,format,args)]/p(str)</c>.</para> /// </remarks> public static StringDistribution StrAverageConditional(StringDistribution format, IList <StringDistribution> args) { Argument.CheckIfNotNull(format, "format"); Argument.CheckIfNotNull(args, "args"); Argument.CheckIfValid(args.Count > 0, "args", "There must be at least one argument provided."); // TODO: relax? if (args.Count >= 10) { throw new NotImplementedException("Up to 10 arguments currently supported."); } // Disallow special characters in args or format StringAutomaton result = DisallowBraceReplacersTransducer.ProjectSource(format); List <StringAutomaton> escapedArgs = args.Select(DisallowBraceReplacersTransducer.ProjectSource).ToList(); // Check braces for correctness and replace them with special characters. // Also, make sure that each argument placeholder is present exactly once. // Superposition of transducers is used instead of a single transducer to allow for any order of arguments. // TODO: in case of a single argument, argument escaping stage can be skipped for (int i = 0; i < args.Count; ++i) { result = GetArgumentEscapingTransducer(i, args.Count, false).ProjectSource(result); } // Now replace placeholders with arguments result = GetPlaceholderReplacingTransducer(escapedArgs, false).ProjectSource(result); return(StringDistribution.FromWorkspace(result)); }
/// <summary>EP message to <c>format</c>.</summary> /// <param name="str">Incoming message from <c>str</c>.</param> /// <param name="args">Incoming message from <c>args</c>.</param> /// <returns>The outgoing EP message to the <c>format</c> argument.</returns> /// <remarks> /// <para>The outgoing message is a distribution matching the moments of <c>format</c> as the random arguments are varied. The formula is <c>proj[p(format) sum_(str,args) p(str,args) factor(str,format,args)]/p(format)</c>.</para> /// </remarks> public static StringDistribution FormatAverageConditional(StringDistribution str, IList <StringDistribution> args) { Argument.CheckIfNotNull(str, "str"); Argument.CheckIfNotNull(args, "args"); Argument.CheckIfValid(args.Count > 0, "args", "There must be at least one argument provided."); // TODO: relax? if (args.Count >= 10) { throw new NotImplementedException("Up to 10 arguments currently supported."); } // Disallow special characters in args List <StringAutomaton> escapedArgs = args.Select(DisallowBraceReplacersTransducer.ProjectSource).ToList(); // Reverse the process defined by StrAverageConditional StringAutomaton result = GetPlaceholderReplacingTransducer(escapedArgs, true).ProjectSource(str); for (int i = 0; i < args.Count; ++i) { result = GetArgumentEscapingTransducer(i, args.Count, true).ProjectSource(result); } result = DisallowBraceReplacersTransducer.ProjectSource(result); return(StringDistribution.FromWorkspace(result)); }
public void ComputeNormalizerWithManyNonTrivialLoops2() { StringAutomaton automaton = StringAutomaton.Zero(); automaton.AddStates(6); automaton.States[0].AddEpsilonTransition(Weight.FromValue(0.2), automaton.States[1]); automaton.States[0].AddEpsilonTransition(Weight.FromValue(0.5), automaton.States[3]); automaton.States[0].EndWeight = Weight.FromValue(0.3); automaton.States[1].AddEpsilonTransition(Weight.FromValue(0.8), automaton.States[0]); automaton.States[1].AddEpsilonTransition(Weight.FromValue(0.1), automaton.States[2]); automaton.States[1].EndWeight = Weight.FromValue(0.1); automaton.States[2].EndWeight = Weight.FromValue(1.0); automaton.States[3].AddEpsilonTransition(Weight.FromValue(0.2), automaton.States[4]); automaton.States[3].AddEpsilonTransition(Weight.FromValue(0.1), automaton.States[5]); automaton.States[3].EndWeight = Weight.FromValue(0.7); automaton.States[4].AddEpsilonTransition(Weight.FromValue(0.5), automaton.States[2]); automaton.States[4].AddEpsilonTransition(Weight.FromValue(0.5), automaton.States[6]); automaton.States[4].EndWeight = Weight.FromValue(0.0); automaton.States[5].AddEpsilonTransition(Weight.FromValue(0.1), automaton.States[3]); automaton.States[5].AddEpsilonTransition(Weight.FromValue(0.9), automaton.States[6]); automaton.States[5].EndWeight = Weight.Zero; automaton.States[6].EndWeight = Weight.One; AssertStochastic(automaton); Assert.Equal(0.0, automaton.GetLogNormalizer(), 1e-6); Assert.Equal(0.0, GetLogNormalizerByGetValue(automaton), 1e-6); Assert.Equal(0.0, GetLogNormalizerByGetValueWithTransducers(automaton), 1e-6); }
/// <summary> /// Computes the normalizer of an automaton by replacing every transition with an epsilon transition /// and computing the value of the automaton on an empty sequence. /// </summary> /// <param name="automaton">The automaton.</param> /// <returns>The logarithm of the normalizer.</returns> private static double GetLogNormalizerByGetValue(StringAutomaton automaton) { var epsilonAutomaton = new StringAutomaton(); epsilonAutomaton.SetToFunction(automaton, (dist, weight, group) => ValueTuple.Create <Option <DiscreteChar>, Weight>(Option.None, weight)); // Convert all the edges to epsilon edges return(epsilonAutomaton.GetLogValue(string.Empty)); // Now this will be exactly the normalizer }
public void PointMassDetectionWithEpsilonLoop() { StringAutomaton f = StringAutomaton.Zero(); AddEpsilonLoop(f.Start, 5, 0.5); f.Start.AddTransitionsForSequence("abc").EndWeight = Weight.One; Assert.Equal("abc", f.TryComputePoint()); }
/// <summary> /// Computes the normalizer via transducers. /// </summary> /// <param name="automaton">The automaton.</param> /// <returns>The logarithm of the normalizer.</returns> private static double GetLogNormalizerByGetValueWithTransducers(StringAutomaton automaton) { var one = StringAutomaton.Constant(1.0); StringTransducer transducer = StringTransducer.Consume(automaton); transducer.AppendInPlace(StringTransducer.Produce(one)); return(transducer.ProjectSource(one).GetLogValue("an arbitrary string")); // Now this will be exactly the normalizer }
/// <summary> /// Tests if a projection of a given automaton onto a given transducer has the desired value on a given sequence. /// </summary> /// <param name="transducer">The transducer.</param> /// <param name="input">The automaton to project.</param> /// <param name="str">The sequence to test the projection on.</param> /// <param name="trueValue">The desired value of the projection on the sequence.</param> public static void TestTransducerProjection( StringTransducer transducer, StringAutomaton input, string str, double trueValue) { // Test ProjectSource(func) var result = transducer.ProjectSource(input); TestValue(result, trueValue, str); }
/// <summary> /// Computes the normalizer of an automaton by replacing every transition with an epsilon transition /// and computing the value of the automaton on an empty sequence. /// </summary> /// <param name="automaton">The automaton.</param> /// <returns>The logarithm of the normalizer.</returns> private static double GetLogNormalizerByGetValue(StringAutomaton automaton) { var epsilonAutomaton = new StringAutomaton(); epsilonAutomaton = automaton.ApplyFunction <string, char, ImmutableDiscreteChar, StringManipulator, StringAutomaton>( (dist, weight, group) => ValueTuple.Create <Option <ImmutableDiscreteChar>, Weight>(Option.None, weight)); // Convert all the edges to epsilon edges return(epsilonAutomaton.GetLogValue(string.Empty)); // Now this will be exactly the normalizer }
public void PointMassDetectionLoopInDeadEnd() { StringAutomaton f = StringAutomaton.Zero(); f.Start.AddTransition('a', Weight.FromValue(0.5)).AddSelfTransition('a', Weight.FromValue(0.5)).AddTransition('b', Weight.One); f.Start.AddTransition('b', Weight.FromValue(0.5)).EndWeight = Weight.One; Assert.Equal("b", f.TryComputePoint()); }
public void PointMassDetectionWithDeadLoop() { StringAutomaton f = StringAutomaton.Zero(); f.Start.AddTransition('a', Weight.FromValue(0.5)).AddTransition('b', Weight.Zero, f.Start); f.Start.AddTransitionsForSequence("abc").EndWeight = Weight.One; Assert.Equal("abc", f.TryComputePoint()); }
public void ZeroDetectionWithDeadSelfLoop() { StringAutomaton f = StringAutomaton.Zero(); f.Start.AddSelfTransition('x', Weight.Zero); f.Start.AddTransition('y', Weight.Zero).EndWeight = Weight.One; Assert.True(f.IsZero()); }
public void ZeroDetectionWithEpsilonLoop1() { StringAutomaton f = StringAutomaton.Zero(); AddEpsilonLoop(f.Start, 5, 0); Assert.False(f.IsCanonicZero()); Assert.True(f.IsZero()); }
public void NoPoint2() { StringAutomaton f = StringAutomaton.Zero(); var state = f.Start.AddTransition('a', Weight.FromValue(0.5)); state.SetEndWeight(Weight.One); state.AddTransition('b', Weight.FromValue(0.5), f.Start); Assert.Null(f.TryComputePoint()); }
/// <summary> /// Tests whether the logarithm of the value of a given automaton on given strings equals to a specified value. /// </summary> /// <param name="automaton">The automaton.</param> /// <param name="trueLogValue">The expected logarithm of the function value.</param> /// <param name="strings">The strings to test.</param> public static void TestLogValue(StringAutomaton automaton, double trueLogValue, params string[] strings) { foreach (string str in strings) { double logValue = automaton.GetLogValue(str); Assert.Equal(trueLogValue, logValue, LogValueEps); Assert.Equal(logValue, Clone(automaton).GetLogValue(str)); } }
public void ZeroDetectionWithEpsilonLoop2() { StringAutomaton f = StringAutomaton.Zero(); AddEpsilonLoop(f.Start, 5, 2.0); f.Start.AddTransition('a', Weight.One); Assert.False(f.IsCanonicZero()); Assert.True(f.IsZero()); }
public void ConvertToStringWithLoops4() { StringAutomaton automaton = StringAutomaton.Zero(); automaton.Start.AddTransitionsForSequence("xyz", automaton.Start); automaton.Start.AddTransition('!', Weight.One).EndWeight = Weight.One; Assert.Equal("(xyz)*!", automaton.ToString(AutomatonFormats.Friendly)); Assert.Equal("(xyz)*!", automaton.ToString(AutomatonFormats.Regexp)); }
public void PointMassDetection() { StringDistribution s1 = StringDistribution.OneOf("hello", "world", "people"); StringDistribution s2 = StringDistribution.OneOf("greetings", "people", "animals"); StringDistribution point1 = s1.Product(s2); Assert.True(point1.IsPointMass); Assert.Equal("people", point1.Point); StringDistribution point2 = StringDistribution.OneOf(new Dictionary <string, double> { { "a", 3.0 }, { "b", 0.0 } }); Assert.True(point2.IsPointMass); Assert.Equal("a", point2.Point); StringDistribution point3 = StringDistribution.CaseInvariant("123"); Assert.True(point3.IsPointMass); Assert.Equal("123", point3.Point); StringDistribution point4 = StringDistribution.Char('Z'); Assert.True(point4.IsPointMass); Assert.Equal("Z", point4.Point); StringDistribution point5 = StringDistribution.OneOf(1.0, StringDistribution.String("!"), 0.0, StringDistribution.Any()); Assert.True(point5.IsPointMass); Assert.Equal("!", point5.Point); StringDistribution point6 = StringDistribution.Repeat('@', minTimes: 3, maxTimes: 3); Assert.True(point6.IsPointMass); Assert.Equal("@@@", point6.Point); StringDistribution point7 = StringDistribution.String("hello").Append(StringDistribution.String(" world")); Assert.True(point7.IsPointMass); Assert.Equal("hello world", point7.Point); string point = string.Empty; StringAutomaton point8Automaton = StringAutomaton.Empty(); for (int i = 0; i < 22; ++i) { const string PointElement = "a"; point8Automaton.AppendInPlace(StringAutomaton.ConstantOn(1.0, PointElement, PointElement)); point += PointElement; } StringDistribution point8 = StringDistribution.FromWeightFunction(point8Automaton); Assert.True(point8.IsPointMass); Assert.Equal(point, point8.Point); }
/// <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 ParseInvalid_StringAutomaton() { bool expected = false; string s = "Not a valid string"; bool actual = StringAutomaton.Parse(s); Assert.AreEqual(expected, actual); }
/// <summary> /// Tests if a transducer projects each of given strings to a zero function. /// </summary> /// <param name="transducer">The transducer.</param> /// <param name="strings">The strings to test.</param> public static void TestIfTransducerRejects(StringTransducer transducer, params string[] strings) { foreach (string str in strings) { var res = transducer.ProjectSource(StringAutomaton.ConstantOn(1.0, str)); Assert.True(res.IsZero()); var res2 = transducer.ProjectSource(str); Assert.True(res2.IsZero()); } }
public void ConvertToStringWithDeadTransitions2() { StringAutomaton automaton = StringAutomaton.Zero(); automaton.Start.AddSelfTransition('x', Weight.Zero); automaton.Start.AddTransition('y', Weight.Zero).EndWeight = Weight.One; Assert.Equal("Ø", automaton.ToString(AutomatonFormats.Friendly)); Assert.Equal("Ø", automaton.ToString(AutomatonFormats.Regexp)); }
public void Repeat4() { StringAutomaton automaton = StringAutomaton.ConstantOn(2.0, "aa"); automaton = StringAutomaton.Repeat(automaton, minTimes: 0); StringInferenceTestUtilities.TestValue(automaton, 0.0, "a", "aaa"); StringInferenceTestUtilities.TestValue(automaton, 1.0, string.Empty); StringInferenceTestUtilities.TestValue(automaton, 2.0, "aa"); StringInferenceTestUtilities.TestValue(automaton, 4.0, "aaaa"); }
public void ConvertToStringWithLoops2() { StringAutomaton automaton = StringAutomaton.Zero(); automaton.Start.AddSelfTransition('a', Weight.One); automaton.Start.AddSelfTransition('b', Weight.One); automaton.Start.EndWeight = Weight.One; Assert.Equal("(a|b)*", automaton.ToString(AutomatonFormats.Friendly)); Assert.Equal("(a|b)*", automaton.ToString(AutomatonFormats.Regexp)); }