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()))); }
/// <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); }
/// <summary>EP message to <c>str</c>.</summary> /// <param name="sub">Incoming message from <c>sub</c>.</param> /// <param name="start">Constant value for <c>start</c>.</param> /// <param name="length">Constant value for <c>length</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_(sub) p(sub) factor(sub,str,start,length)]/p(str)</c>.</para> /// </remarks> public static StringDistribution StrAverageConditional(StringDistribution sub, int start, int length) { Argument.CheckIfNotNull(sub, "sub"); Argument.CheckIfInRange(start >= 0, "start", "Start index must be non-negative."); Argument.CheckIfInRange(length >= 0, "length", "Length must be non-negative."); var anyChar = StringAutomaton.ConstantOnElement(1.0, DiscreteChar.Any()); var transducer = StringTransducer.Produce(StringAutomaton.Repeat(anyChar, minTimes: start, maxTimes: start)); transducer.AppendInPlace(StringTransducer.Copy(StringAutomaton.Repeat(anyChar, minTimes: length, maxTimes: length))); transducer.AppendInPlace(StringTransducer.Produce(StringAutomaton.Constant(1.0))); return(StringDistribution.FromWorkspace(transducer.ProjectSource(sub))); }
public void ConsumeAutomaton() { StringAutomaton automaton = StringAutomaton.Constant(2.0, DiscreteChar.Lower()); automaton = automaton.Sum(StringAutomaton.ConstantOnElement(3.0, 'a')); StringTransducer consume = StringTransducer.Consume(automaton); StringInferenceTestUtilities.TestTransducerValue(consume, "aaa", string.Empty, 2.0); StringInferenceTestUtilities.TestTransducerValue(consume, "bb", string.Empty, 2.0); StringInferenceTestUtilities.TestTransducerValue(consume, "a", string.Empty, 5.0); StringInferenceTestUtilities.TestTransducerValue(consume, string.Empty, string.Empty, 2.0); StringInferenceTestUtilities.TestTransducerValue(consume, "bb", "aaa", 0.0); StringInferenceTestUtilities.TestTransducerValue(consume, "bb", "bb", 0.0); StringInferenceTestUtilities.TestTransducerValue(consume, string.Empty, "bb", 0.0); StringInferenceTestUtilities.TestTransducerValue(consume, string.Empty, "a", 0.0); }
public void ProduceAutomaton() { StringAutomaton automaton = StringAutomaton.Constant(2.0, ImmutableDiscreteChar.Lower()); automaton = automaton.Sum(StringAutomaton.ConstantOnElement(3.0, 'a')); StringTransducer produce = StringTransducer.Produce(automaton); StringInferenceTestUtilities.TestTransducerValue(produce, string.Empty, "aaa", 2.0); StringInferenceTestUtilities.TestTransducerValue(produce, string.Empty, "bb", 2.0); StringInferenceTestUtilities.TestTransducerValue(produce, string.Empty, "a", 5.0); StringInferenceTestUtilities.TestTransducerValue(produce, string.Empty, string.Empty, 2.0); StringInferenceTestUtilities.TestTransducerValue(produce, "aaa", "bb", 0.0); StringInferenceTestUtilities.TestTransducerValue(produce, "bb", "bb", 0.0); StringInferenceTestUtilities.TestTransducerValue(produce, "bb", string.Empty, 0.0); StringInferenceTestUtilities.TestTransducerValue(produce, "a", string.Empty, 0.0); }
public void ReplaceAutomaton() { StringAutomaton automaton1 = StringAutomaton.Constant(2.0, DiscreteChar.Lower()); automaton1 = automaton1.Sum(StringAutomaton.ConstantOnElement(3.0, 'a')); StringAutomaton automaton2 = StringAutomaton.Constant(0.5, DiscreteChar.Digit()); automaton2 = automaton2.Sum(StringAutomaton.Constant(2.5, DiscreteChar.LetterOrDigit())); StringTransducer replace = StringTransducer.Replace(automaton1, automaton2); StringInferenceTestUtilities.TestTransducerValue(replace, string.Empty, "123", 6.0); StringInferenceTestUtilities.TestTransducerValue(replace, "a", "123", 15.0); StringInferenceTestUtilities.TestTransducerValue(replace, "ax", "AbC", 5.0); StringInferenceTestUtilities.TestTransducerValue(replace, "a", "a", 12.5); StringInferenceTestUtilities.TestTransducerValue(replace, string.Empty, string.Empty, 6.0); StringInferenceTestUtilities.TestTransducerValue(replace, "123", string.Empty, 0.0); StringInferenceTestUtilities.TestTransducerValue(replace, "AbC", "ax", 0.0); StringInferenceTestUtilities.TestTransducerValue(replace, "1", "1", 0.0); }