/* Input: 123 is a number blubb is not a number 5$"%! is not a number 45 is a number task 1: tokenize well (in this case, ignore quotes) task 2: discover patterns "* is a number" and "* is not a number" task 3: call pattern 1 positive, pattern 2 negative task 4: make set of positive/negative example strings for argument task 5a: learn description for positive examples, output new examples task 5b: learn description for negative examples, output new examples Generates new examples for numbers, e.g.: 351 is a number 73 is a number */ cprint { S input = autoUnindent_mls([[ 123 is a number blubb is not a number 5$"%! is not a number 45 is a number ]]); S output; transient L someFunctions = ll( f isDigit, f isLetter, f isLetterOrDigit, f isSpace); visual jvsplit(jhsplit(dm_textAreaAsSection input(), dm_textAreaAsSection output()), super); start { dm_onFieldChangeAndNow input(r calc); } void calc { // task 1: tokenize well (in this case, ignore quotes) ITokenizer tokenizer = lambda1 splitAtSpaceTokenizer; LLS tokenizedInput = map(s -> simpleSpacesAndTrim(tokenizer.tokenize(s)), tlft(input)); pnlStruct(+tokenizedInput); // task 2: discover patterns "* is a number" and "* is not a number" Set patterns = asSet(findOneArgumentPatterns(tokenizedInput)); assertEquals(2, l(patterns)); print(+patterns); // task 3: make set of positive/negative example strings for argument Map examples = mapToValues_linkedHashMap(patterns, pat -> mapNotNulls(tok -> firstMatch(getFlexMatchIC(pat, tok)), tokenizedInput)); print(+examples); // task 4: make theories replace Xmp with L. Map> examplesAsLists = mapValues(l -> lambdaMap characters(l), examples); print(examplesAsLists); //examplesAsLists = reverseKeys(examplesAsLists); // test reversing to see if theory gets reversed L posExamples = firstValue(examplesAsLists), negExamples = secondValue(examplesAsLists); // for functions that are applicable to the elements of the examples: new LinkedHashSet<ITheoryOn<Xmp>> theories; for (O function : concatAsOrderedSet(lambdaMap plusNegation(someFunctions))) { //if (!functionCallableOnAll_nonSynthetic(function, concatLists(values(examplesAsLists)))) continue; print("Testing function " + function); theories.add(new AllElementsSatisfy(function)); theories.add(new AnyElementSatisfies(function)); } theories.addAll(concatLists(lambdaMap theoryPlusInverse(theories))); pnl(theories); // test theories Map<ITheoryOn<Xmp>, PosNeg<Xmp>> theoryResults = mapToValues(theories, theory -> PosNeg(mapToValues(trueFalseMap(posExamples, negExamples), (example, x) -> theory.check(example) == x))); pnl(theoryResults); // make new examples replace Theory with ITheoryOn<Xmp>. new LS newStatements; L<Theory> perfectTheories = sortByMetaTransformerStructureComplexity(keysWhereValue(theoryResults, pn -> pn.perfect())); print(+perfectTheories); newStatements.addAll(makeExamplesFor(perfectTheories, posExamples, firstKey(examplesAsLists))); // perfect theories for negative examples L<Theory> antiPerfectTheories = sortByMetaTransformerStructureComplexity(keysWhereValue(theoryResults, pn -> pn.antiPerfect())); print(+antiPerfectTheories); newStatements.addAll(makeExamplesFor(antiPerfectTheories, negExamples, secondKey(examplesAsLists))); setField(output := lines(newStatements)); } LS makeExamplesFor(L<ITheoryOn<L<Char>>> theories, Cl<L<Char>> examples, S pattern) { new LS out; IntRange sizeRange = sizeRangeOfCollections(examples); print(+sizeRange); for (ITheoryOn<L<Char>> t : theories) if (t cast AllElementsSatisfy) { IF0<Char> generator = predicateToGenerator(t.pred); if (generator == null) continue with print("No generator for " + t.pred); repeat 3 { S example = charactersToString(repF(random(sizeRange), generator)); print("> ", addAndReturn(out, format_noQuote(pattern, example))); } break; } ret out; } IF0<Char> predicateToGenerator(O f) { ret () -> (Char) random(filter(f, printableASCIICharsList())); } }