!7 cmodule Timeline > DynPrintLog { transient S input = [[ --- Rules Event 1 happens before event 2 := vars {event 1, event 2, X, Y} Event 1 happens at day X. Event 2 happens at day Y. X < Y. --- Facts Enrolling happens before graduation. Enrolling happens at day 200. Graduation happens at day 100. // Contradiction! ]]; transient new L rules; start-thread { SS sections = minusSignSectionsCI(input); for (S s : splitAtEmptyLines(sections.get("rules"))) { LS lines = tlft(s); S head = dropSuffix_trim(":=", popFirst(lines)); Rule_StringToStrings rule = new(head); new Matches m; if (match3_plusBrackets("vars * ", first(lines), m)) { rule.vars = asCISet(tok_splitAtComma(uncurly(m.get(0)))); popFirst(lines); } rule.out = lines; print("Got rule: " + rule); printStruct(rule); rules.add(rule); } for (S fact : tlft(dropJavaComments(sections.get("facts")))) { print("Got fact: " + fact); } } } sclass Gazelle_MiniEngine2 { int minScore = 50; // minimal percentage score for rule matching bool printMappings, printGroupedData, printRejectedVars; // what to debug-print // some parsing and formatting macros F1 formatForUser = func(S s) -> S { ai_superSimpleVerbCorrector(tok_dropCurlyBrackets(s)) }; F1 parse = func(S s) -> LS { codeTokens_lazy_uncurly(javaTokWithBrackets_cached(s)) }; // syntactic sugar for the macros S formatForUser(S s) { ret callF(formatForUser, s); } LS parse(S s) { ret callF(parse, s); } // rules are in => out + variables LPair rules; Map> ruleVariables = new Map; // returns solutions // data = section "rules" and section "input" (input statements) MultiMap run(S _data) { // parse rules from _data S data = mapEachLine ai_groupSimplestNounPhrases(_data); if (printGroupedData) print(data); SS sections = asCIMap(minusSignsSections(data)); rules = ai_findDoubleArrowRulesAsPairs(sections.get("Rules")); for (PairS rule : rules) ruleVariables.put(rule, ai_wordsInBothSidesOfPair_uncurly(rule)); // process input statements from _data and record rewrites that don't end in "fail" printAsciiHeading("REASONING"); new MultiMap solutions; for (S input : tlft(sections.get("Input"))) { print("\nInput: " + tok_dropCurlyBrackets(input)); temp tempIndent(); for (Pair in : interpretations(input)) { print("\nInterpretation: " + formatForUser(in.a)); Set out = litciset(); interpretRecursively(in.a, 5, out); if (!matchAny("fail", out)) solutions.put(input, in.a); } } // print solutions printAsciiHeading("RESULTS"); print(formatDoubleArrowPairs_horizontallyAligned(mapPairBoth(formatForUser, multiMapToPairs(solutions)))); ret solutions; } void interpretRecursively(S input, int level, Set out) { if (level <= 0) ret; LS interpretations = pairsA(interpretations(ai_groupSimplestNounPhrases(input))); temp tempIndent(); for (S in : addAllAndReturnNew(out, interpretations)) { print(" => " + formatForUser(in)); for (S s : lithashset(in, ai_superSimpleVerbCorrector(in))) interpretRecursively(s, level-1, out); } } LPair interpretations(S input) { LS tokI = parse(input); new LPair interpretations; for (PairS rule : rules) { LS tokR = parse(rule.a); final SS map = ciMapWithoutKeysEqualToValues(zipTwoListsToCIMap_strict(tokR, tokI)); if (map == null) continue; // Found matching rule int score = l(tokR)-l(map); L nonVars = withoutDollarVars(listMinusSet(keys(map), ruleVariables.get(rule))); if (printRejectedVars && nempty(nonVars)) print("Rejected vars: " + nonVars); if (nempty(nonVars)) score = 0; if (printMappings) print(" " + reverseMapCI_joinDuplicatesWithPlus(map) + " | " + rule.a); // Make consequence S c = rule.b; c = join(mapCodeTokens(javaTok(c), func(S s) -> S { getOrKeep_tryUncurlied(map, s) })); c = join(mapCodeTokens(javaTokWithBrackets(c), func(S s) -> S { getOrKeep_tryUncurlied(map, s) })); //c = javaTokWithBrackets_recursiveTransform(func(S s) -> S { getOrKeep(map, s) }, c); addPairIfBAtLeast(interpretations, c, ratioToIntPercent(score, l(tokR)), minScore); } ret interpretations; } }