// for notes see #1028089 sclass PatternMaker1 { S comment, examplesText, counterexamplesText; transient Concepts cc; transient Set examples, counterexamples; transient new Lowest simplestFullSolutionCollector; TreeMap> bestPatternsByClass; S simplestFullSolution; // simplest pattern solving all examples Runnable strategy; // collectors transient new TreeMap bestByComplexity; transient Map> allByComplexity = autoTreeMap(() -> treeSetWithDuplicatesOverCalculatedField theoryScore()); sconcept Example { S text; bool pos; toString { ret text + "/" + pos; } } sconcept Theory { S pattern; transient simplyCached Cl solvedExamples() { ret filter(list(_concepts, Example.class), e -> e.pos == mmo2_match(pattern, e.text)); } transient simplyCached Cl unsolvedExamples() { ret setMinusSet(list(_concepts, Example.class), solvedExamples()); } bool isFullSolution() { ret empty(unsolvedExamples()); } int score() { ret l(solvedExamples()); } transient simplyCached int complexityClass() { ret numberOfWords2(pattern); } } // end of Theory *() {} *(S *examplesText, S *counterexamplesText) {} *(LS examples, LS counterexamples) { examplesText = lines(examples); counterexamplesText = lines(counterexamples); } void prepare { cc = new Concepts; clearCollectors(); indexConceptFieldCI(cc, Example.class, 'text); indexConceptFieldCI(cc, Theory.class, 'pattern); setField(simplestFullSolution := null); simplestFullSolutionCollector.clear(); examples = asLinkedHashSet(tlftj(examplesText)); counterexamples = asLinkedHashSet(tlftj(counterexamplesText)); Set intersection = setIntersection(examples, counterexamples); if (nempty(intersection)) ret with infoBox("Error: Examples appear in both lists, e.g. " + first(intersection)); for (S s : examples) uniqCI(cc, Example.class, text := s, pos := true); for (S s : counterexamples) uniqCI(cc, Example.class, text := s, pos := false); int nExamples = countConcepts(cc, Example.class); print("Have " + nExamples(nExamples)); } void think { prepare(); strategy = makeStrategy(); pcallF(strategy); afterThink(); } void afterThink { print("Have " + nTheories(countConcepts(cc, Theory.class))); setField(bestPatternsByClass := mapValues(t -> scoredNonPercent(t.score(), t.pattern), bestByComplexity)); doneThinking(); } swappable Runnable makeStrategy() { ret new Strategy1; } runnable class Strategy1 { // positive examples to pattern for (S s : examples) addPatterns(ai_inputExampleToPossibleMMOPatterns1(s)); // combine some pattern pairs from complexity classes 1-2 twice { for (Theory a : allByComplexity.get(1)) for (int n = 1; n <= 2; n++) for (Theory b : allByComplexity.get(n)) addPattern(mmo2_combineWithOr(a.pattern, b.pattern)); } } Map theoryToMap(Theory t) { ret t == null ? null : litorderedmap( "Pattern" := t.pattern, "Complexity class" := t.complexityClass(), "Solved examples" := l(t.solvedExamples()) + " of " + countConcepts(cc, Example.class), "Unsolved" := joinWithComma(quoteAll(collect text(t.unsolvedExamples())))); } void addPatterns(Iterable l) { fOr (S s : l) addPattern(s); } void addPattern(S pattern) { addToCollectors(uniqCI_returnIfNew(cc, Theory.class, +pattern)); } void tryPattern(S pattern) { addPattern(pattern); } int theoryScore(Theory t) { ret t == null ? 0 : t.score(); } void clearCollectors { bestByComplexity.clear(); allByComplexity.clear(); } void addToCollectors(Theory t) { if (t == null) ret; putIfHigherByCalculatedField theoryScore(bestByComplexity, t.complexityClass(), t); allByComplexity.get(t.complexityClass()).add(t); if (t.isFullSolution() && simplestFullSolutionCollector.put(t, t.complexityClass())) setField(simplestFullSolution := t.pattern); } void printBestByClass() { for (int complexity, Theory t : bestByComplexity) { print("Best theory for complexity " + complexity + ": " + shorten(100, str(theoryToMap(t)))); } } !include #1028121 // setField + change event doneThinking; }