Download Jar. Uses 3874K of libraries. Click here for Pure Java version (10167L/74K).
1 | !7 |
2 | |
3 | static Map<S, Set<S>> theSet; |
4 | static new LinkedHashSet<Updatable> allObjects; |
5 | static long changes; |
6 | static new MultiMap<S, Pair<S>> groupingsByA; |
7 | static new MultiMap<S> subClasses; |
8 | |
9 | static S groupings = [[ |
10 | <preposition> + <noun> = <adverbial_phrase> |
11 | <determiner> + <noun> = <noun> |
12 | <adverb> + <verb_phrase> = <verb_phrase> |
13 | <verb> = <verb_phrase> |
14 | <verb> + <noun> = <verb_phrase> |
15 | <noun> + <verb_phrase> = <sentence> |
16 | <adverbial_phrase> + <sentence> = <sentence> |
17 | ]]; |
18 | |
19 | sclass Updatable { |
20 | void update {} |
21 | |
22 | void setField(S field, O value) { |
23 | if (eq(get(this, field), value)) ret; |
24 | set(this, field, value); |
25 | change(); |
26 | } |
27 | } |
28 | |
29 | sclass Expectation { |
30 | S ifClass; |
31 | Runnable action; |
32 | |
33 | *() {} |
34 | *(S *ifClass, Runnable *action) {} |
35 | } |
36 | |
37 | sclass Word extends Updatable { |
38 | S text; // or null if unknown |
39 | new LinkedHashSet<Word> prev; |
40 | new LinkedHashSet<Word> next; |
41 | L<Word> constituents; // if group |
42 | new L<Expectation> expectations; |
43 | new L<Expectation> fulfilledExpectations; |
44 | new TreeSet<S> classes; |
45 | int classesConvertedToTraits; |
46 | new LinkedHashSet<Word> groups; // I am part of |
47 | new L<Trait> traits; |
48 | |
49 | void update { |
50 | // Add direct word classes |
51 | if (text != null) |
52 | for (S c : reverseLookupInMapToSets(theSet, text)) |
53 | addClass(c); |
54 | |
55 | // Make text for group |
56 | if (isGroup() && text == null) { |
57 | L<S> l = collect(constituents, 'text); |
58 | if (!anyNull(l)) setField(text := joinWithSpace(l)); |
59 | } |
60 | |
61 | // Process expectations |
62 | for (Expectation e : cloneList(expectations)) { |
63 | //print("Checking expected class " + e.ifClass); |
64 | if (classes.contains(e.ifClass)) { |
65 | moveElementFromCollectionToCollection(e, expectations, fulfilledExpectations); |
66 | change(); |
67 | callF(e.action); |
68 | } |
69 | } |
70 | |
71 | if (l(classes) > classesConvertedToTraits) { |
72 | for (fS c : dropFirst(classesConvertedToTraits, classes)) |
73 | addTraitsForClass(c); |
74 | classesConvertedToTraits = l(classes); |
75 | } |
76 | |
77 | for (Trait t : iterateListConcurrently(traits)) |
78 | t.update(); |
79 | } |
80 | |
81 | bool isGroup() { ret constituents != null; } |
82 | |
83 | bool addClass(S c) { |
84 | if (!classes.add(c)) false; |
85 | change(); |
86 | long n; |
87 | do { |
88 | n = changes; |
89 | // optimizable |
90 | for (S d : iterateListConcurrently(asList(classes))) |
91 | for (S e : subClasses.get(d)) |
92 | if (classes.add(e)) change(); |
93 | } while (changes != n); |
94 | true; |
95 | } |
96 | |
97 | void addExpectation(Expectation e) { |
98 | //print("addExpectation " + e); |
99 | expectations.add(e); |
100 | change(); |
101 | } |
102 | |
103 | void addTraitsForClass(S c) { |
104 | for (PairS p : groupingsByA.get(c)) |
105 | addTrait(LinkWithTo(p.a, p.b)); |
106 | } |
107 | |
108 | void addTrait(Trait t) { |
109 | set(t, w := this); |
110 | traits.add(t); |
111 | } |
112 | } |
113 | |
114 | static Word makeGroup(Word a, Word b, S newClass) { |
115 | //print("makeGroup " + a.text + " / " + b.text); |
116 | L<Word> list = ll(a, b); |
117 | |
118 | // look for existing group |
119 | for (Word g : a.groups) |
120 | if (eq(g.constituents, list)) { |
121 | if (g.addClass(newClass)) |
122 | print("Added class " + newClass + " to existing group: " + a.text + " + " + b.text); |
123 | ret g; |
124 | } |
125 | |
126 | // new group |
127 | print("Making group " + newClass + " " + a.text + " + " + b.text); |
128 | print(" prev=" + sfu(collect(a.prev, 'text))); |
129 | print(" next=" + sfu(collect(b.next, 'text))); |
130 | new Word g; |
131 | allObjects.add(g); |
132 | g.addClass(newClass); |
133 | g.constituents = list; |
134 | for (Word w : list) |
135 | w.groups.add(g); |
136 | g.prev.addAll(a.prev); |
137 | g.next.addAll(b.next); |
138 | for (Word prev : a.prev) prev.next.add(g); |
139 | for (Word next : b.next) next.prev.add(g); |
140 | ret g; |
141 | } |
142 | |
143 | sclass Trait extends Updatable { |
144 | Word w; |
145 | } |
146 | |
147 | sclass LinkWithTo extends Trait { |
148 | S linkWith, linkTo; // classes |
149 | int expectationsSentToNext; |
150 | |
151 | *() {} |
152 | *(S *linkWith, S *linkTo) {} |
153 | |
154 | void update { |
155 | if (l(w.next) > expectationsSentToNext) { |
156 | for (final Word next : dropFirst(expectationsSentToNext, w.next)) |
157 | next.addExpectation(Expectation(linkWith, r { |
158 | makeGroup(w, next, linkTo) |
159 | })); |
160 | expectationsSentToNext = l(w.next); |
161 | } |
162 | } |
163 | } |
164 | |
165 | p-exp { |
166 | fS sentence = "In the movies Dracula always wears a cape"; |
167 | L<S> rawWords = printStruct(words(sentence)); |
168 | |
169 | theSet = ai_englishWordCategoriesWithElements(); |
170 | parseGroupings(); |
171 | |
172 | new L<Word> words; |
173 | for (S w : rawWords) |
174 | words.add(nu(Word, text := w)); |
175 | for (int i = 0; i < l(words)-1; i++) |
176 | linkWords(words.get(i), words.get(i+1)); |
177 | //printStruct(first(words)); |
178 | |
179 | addAll(allObjects, words); |
180 | long lastChanges; |
181 | do { |
182 | lastChanges = changes; |
183 | print(n2(changes, "change")); |
184 | for (Updatable w : cloneList(allObjects)) |
185 | w.update(); |
186 | } while (lastChanges != changes); |
187 | |
188 | //for (Word w : words) printStruct(cloneForPrinting(w)); |
189 | for (Word w : words) print(" " + textAndClasses(w)); |
190 | print(); |
191 | |
192 | L<Word> groups = [Word w : instancesOf(Word, allObjects) | w.constituents != null]; |
193 | print(); |
194 | print(n2(groups, "group")); |
195 | for (Word g : groups) { |
196 | print("Group: " + textAndClasses(g)); |
197 | print(" " + grouped(g)); |
198 | } |
199 | |
200 | assertNempty([Word g : groups | eq(g.text, sentence) && g.classes.contains("<sentence>")]); |
201 | print("OK"); |
202 | } |
203 | |
204 | sS textAndClasses(Word w) { |
205 | ret w.text + " (" + joinWithComma(w.classes) + ")"; |
206 | } |
207 | |
208 | svoid linkWords(Word a, Word b) { |
209 | a.next.add(b); |
210 | b.prev.add(a); |
211 | } |
212 | |
213 | static O cloneForPrinting(Word w) { |
214 | ret cloneWithoutFields(w, 'prev, 'next, 'constituents); |
215 | } |
216 | |
217 | svoid change() { ++changes; } |
218 | |
219 | svoid parseGroupings() { |
220 | for (S s : tlft(groupings)) { |
221 | L<S> tok = javaTokWithAngleBracketsC(s); |
222 | if (l(tok) == 5) |
223 | groupingsByA.put(tok.get(0), pair(tok.get(2), tok.get(4))); |
224 | else if (l(tok) == 3) |
225 | subClasses.put(tok.get(0), tok.get(2)); |
226 | } |
227 | } |
228 | |
229 | sS grouped(Word g) { |
230 | if (g.constituents == null) ret g.text; |
231 | new L<S> l; |
232 | for (Word w : g.constituents) |
233 | l.add(curlyBraceIfMultipleTokens(grouped(w))); |
234 | ret joinWithSpace(l); |
235 | } |
Began life as a copy of #1017342
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1017348 |
Snippet name: | Intelligent Words v2 [OK] |
Eternal ID of this version: | #1017348/31 |
Text MD5: | 20445a528c7a8441f8ccf94577551323 |
Transpilation MD5: | 86ab5c8f51f0b96387f956ce84d3daa1 |
Author: | stefan |
Category: | javax / a.i. |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2018-07-17 23:16:03 |
Source code size: | 6119 bytes / 235 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 431 / 1208 |
Version history: | 30 change(s) |
Referenced in: | [show references] |