/// <summary> /// Learn <paramref name="k" /> top-ranked Transformation.Text programs for a given set of input-output examples. /// </summary> /// <param name="trainingExamples"> /// The set of input-output examples as a Tuple of the input and the output. /// </param> /// <param name="additionalInputs"> /// The set of additional inputs that do not have output examples, which helps rank learnt programs. /// </param> /// <param name="k">the number of top programs</param> /// <returns>The top-k ranked programs as <see cref="TextTransformationProgram" />s</returns> public static IEnumerable <TextTransformationProgram> LearnTopK(IDictionary <string, string> trainingExamples, IEnumerable <string> additionalInputs = null, int k = 1) { if (trainingExamples == null) { throw new ArgumentNullException(nameof(trainingExamples)); } // Load Transformation.Text grammar Grammar grammar = Language.Grammar; DomainLearningLogic learningLogic = new Witnesses(grammar, // This is currently required as a workaround for a bug. ((RankingScore)Learner.Instance.ScoreFeature).Clone()); // Setup configuration of synthesis process. var engine = new SynthesisEngine(grammar, new SynthesisEngine.Config { // Strategies perform the actual logic of the synthesis process. Strategies = new[] { new DeductiveSynthesis(learningLogic) }, UseThreads = false, CacheSize = int.MaxValue }); // Convert the examples in the format expected by Microsoft.ProgramSynthesis. // Internally, Transformation.Text represents strings as ValueSubstrings to save on // allocating new strings for each substring. // Could also use InputRow.AsState() to construct the input state. Dictionary <State, object> trainExamples = trainingExamples.ToDictionary( t => State.Create(grammar.InputSymbol, new[] { ValueSubstring.Create(t.Key) }), t => (object)ValueSubstring.Create(t.Value)); var spec = new ExampleSpec(trainExamples); // Learn an entire Transformation.Text program (i.e. start at the grammar's start symbol) // for the specification consisting of the examples. // Learn the top-k programs according to the score feature used by Transformation.Text by default. // You could define your own feature on the Transformation.Text grammar to rank programs differently. var task = new LearningTask(grammar.StartSymbol, spec, k, Learner.Instance.ScoreFeature); if (additionalInputs != null) { task.AdditionalInputs = additionalInputs.Select( input => State.Create(grammar.InputSymbol, new[] { ValueSubstring.Create(input) })) .ToList(); } IEnumerable <ProgramNode> topk = engine.Learn(task).RealizedPrograms; // Return the generated programs wraped in a TextTransformationProgram object. return(topk.Select(prog => new TextTransformationProgram(prog))); }
private ProgramSet LearnImpl <TFeatureValue>(IEnumerable <Constraint <MergeConflict, IReadOnlyList <Node> > > constraints, Feature <TFeatureValue> feature, int?k, int?numRandomProgramsToInclude, ProgramSamplingStrategy samplingStrategy, CancellationToken cancel = default) { Grammar grammar = LanguageGrammar.Instance.Grammar; Dictionary <State, object> examples = constraints.OfType <Example <MergeConflict, IReadOnlyList <Node> > >() .ToDictionary( e => State.CreateForLearning(grammar.InputSymbol, e.Input), e => (object)e.Output); var spec = new ExampleSpec(examples); var witnesses = new WitnessFunctions(grammar); var engine = new SynthesisEngine( grammar, new SynthesisEngine.Config { Strategies = new ISynthesisStrategy[] { new DeductiveSynthesis(witnesses) }, UseThreads = false }); LearningTask task = k.HasValue ? LearningTask.Create(grammar.StartSymbol, spec, numRandomProgramsToInclude, samplingStrategy, k.Value, feature) : new LearningTask(grammar.StartSymbol, spec); ProgramSet set = engine.Learn(task, cancel); engine.Configuration.LogListener?.SaveLogToXML("log.xml"); if (k.HasValue) { return(set.Prune(k.Value, numRandomProgramsToInclude, feature, null, task.FeatureCalculationContext, samplingStrategy, engine.RandomNumberGenerator, engine.Configuration.LogListener)); } return(set); }
internal Optional <ProgramSet> LearnDupLet(SynthesisEngine engine, LetRule rule, LearningTask <DisjunctiveExamplesSpec> task, CancellationToken cancel) { var examples = task.Spec; List <string[]> pathsArr = new List <string[]>(); foreach (KeyValuePair <State, IEnumerable <object> > example in examples.DisjunctiveExamples) { State inputState = example.Key; var input = example.Key[Grammar.InputSymbol] as MergeConflict; List <string> idx = new List <string>(); foreach (IReadOnlyList <Node> output in example.Value) { foreach (Node n in Semantics.Concat(input.Upstream, input.Downstream)) { bool flag = false; n.Attributes.TryGetValue(Path, out string inPath); foreach (Node node in output) { node.Attributes.TryGetValue(Path, out string outputPath); if (inPath == outputPath) { flag = true; } } if (!flag) { idx.Add(inPath); } } } pathsArr.Add(idx.ToArray()); } pathsArr.Add(new string[1] { string.Empty }); List <ProgramSet> programSetList = new List <ProgramSet>(); foreach (string[] path in pathsArr) { NonterminalRule findMatchRule = Grammar.Rule(nameof(Semantics.FindMatch)) as NonterminalRule; ProgramSet letValueSet = ProgramSet.List( Grammar.Symbol("find"), new NonterminalNode( findMatchRule, new VariableNode(Grammar.InputSymbol), new LiteralNode(Grammar.Symbol("paths"), path))); var bodySpec = new Dictionary <State, IEnumerable <object> >(); foreach (KeyValuePair <State, IEnumerable <object> > kvp in task.Spec.DisjunctiveExamples) { State input = kvp.Key; MergeConflict x = (MergeConflict)input[Grammar.InputSymbol]; List <IReadOnlyList <Node> > dupValue = Semantics.FindMatch(x, path); State newState = input.Bind(rule.Variable, dupValue); bodySpec[newState] = kvp.Value; } LearningTask bodyTask = task.Clone(rule.LetBody, new DisjunctiveExamplesSpec(bodySpec)); ProgramSet bodyProgramSet = engine.Learn(bodyTask, cancel); var dupLetProgramSet = ProgramSet.Join(rule, letValueSet, bodyProgramSet); programSetList.Add(dupLetProgramSet); } ProgramSet ps = new UnionProgramSet(rule.Head, programSetList.ToArray()); return(ps.Some()); }