1 | concepts. |
2 | |
3 | !include #1005279 // Str, concept, mergeStrs |
4 | |
5 | concept AThing { |
6 | new Ref thing; |
7 | |
8 | *() {} |
9 | *(Concept thing) { this.thing.set(thing); } |
10 | } |
11 | |
12 | concept DefiniteThing {} |
13 | |
14 | static AThing aThing(S name) { |
15 | ret uniqueConcept(AThing.class, "thing", concept(name)); |
16 | } |
17 | |
18 | // "main" has a number of "part"s. |
19 | concept HasMulti { |
20 | new Ref main; |
21 | new Ref part; |
22 | } |
23 | |
24 | // "main" has exactly "count" "part"s. |
25 | concept MultiCount { |
26 | new Ref main; |
27 | new Ref part; |
28 | int count; |
29 | } |
30 | |
31 | // "main" has a "part". |
32 | concept HasA { |
33 | new Ref main; |
34 | new Ref part; |
35 | } |
36 | |
37 | // "main" has "part". |
38 | concept Has { |
39 | new Ref main; |
40 | new Ref part; |
41 | } |
42 | |
43 | concept IsA { |
44 | new Ref thing; |
45 | new Ref type; |
46 | } |
47 | |
48 | concept TheXOfY { |
49 | new Ref x; |
50 | new Ref y; |
51 | } |
52 | |
53 | concept Question { |
54 | S originalText; |
55 | } |
56 | |
57 | concept OpenQuestion { |
58 | new Ref<Question> question; |
59 | } |
60 | |
61 | concept AnsweredQuestion { |
62 | new Ref<Question> question; |
63 | new Ref answer; |
64 | } |
65 | |
66 | concept ConceptList { |
67 | new RefL<Concept> list; |
68 | |
69 | *() {} |
70 | *(L l) { list.addAll_(l); } |
71 | |
72 | void addAll(L l) { |
73 | list.addAll(l); |
74 | } |
75 | } |
76 | |
77 | concept HowManyAreIn extends Question { |
78 | new Ref main; |
79 | new Ref part; |
80 | } |
81 | |
82 | concept DoesXHaveAY extends Question { |
83 | new Ref x; |
84 | new Ref y; |
85 | } |
86 | |
87 | concept WhatDoesXHave extends Question { |
88 | new Ref thing; |
89 | } |
90 | |
91 | concept Yes {} |
92 | concept No {} |
93 | |
94 | svoid processRulesMulti { |
95 | for (int i = 0; i < 1000; i++) { |
96 | long n = changes; |
97 | processRules(); |
98 | long n2 = changes; |
99 | if (n2 > n) |
100 | print(n(n2-n, "change") + " (concepts: " + countConcepts() + ")"); |
101 | else |
102 | ret; |
103 | } |
104 | print("safety limit reached (1000 iterations)"); |
105 | } |
106 | |
107 | svoid answerQuestion(Question question, Concept answer) { |
108 | cdelete(OpenQuestion.class, "question", question); |
109 | uniqueConcept(AnsweredQuestion.class, "question", question, "answer", answer); |
110 | } |
111 | |
112 | svoid answerQuestion(Question question, bool answer) { |
113 | answerQuestion(question, uniqueConcept(answer ? Yes.class : No.class)); |
114 | } |
115 | |
116 | svoid printConcepts { |
117 | print(); |
118 | for (Concept c : allConcepts()) |
119 | printConcept(c); |
120 | } |
121 | |
122 | svoid printConcept(Concept c) { |
123 | print(renderConcept(c)); |
124 | } |
125 | |
126 | static S renderConcept(Concept.Ref ref) { |
127 | ret renderConcept(ref.get()); |
128 | } |
129 | |
130 | static S renderConcept(Concept c) { |
131 | new StringBuilder buf; |
132 | if (c == null) buf.append("null"); |
133 | /*else if (c instanceof ConceptList) { |
134 | for (Concept c2 : ((ConceptList) c).list) |
135 | buf.append(renderConcept(c2) + "\n"); |
136 | }*/ else { |
137 | buf.append(c.id + " " + shortDynamicClassName(c)); |
138 | for (S field : listFields(c)) { |
139 | O val = cget(c, field); |
140 | if (val != null) { |
141 | buf.append(" " + field + "="); |
142 | buf.append(renderConceptShort(val)); |
143 | } |
144 | } |
145 | } |
146 | ret str(buf); |
147 | } |
148 | |
149 | static S renderConceptShort(O val) { |
150 | if (val instanceof Str) |
151 | ret quote(((Str) val).name); |
152 | else if (val instanceof AThing) |
153 | ret "a " + renderConceptShort(((AThing) val).thing.get()); |
154 | else if (val instanceof Concept) |
155 | ret shortDynamicClassName(val) + ((Concept) val).id; |
156 | else |
157 | ret struct(val); |
158 | } |
159 | |
160 | static S renderQuestion(Concept.Ref<Question> q) { |
161 | ret renderQuestion(q.get()); |
162 | } |
163 | |
164 | static S renderQuestion(Question q) { |
165 | ret q.originalText + " (" + shortDynamicClassName(q) + ")"; |
166 | } |
167 | |
168 | svoid printQuestionsAndAnswers { |
169 | L<OpenQuestion> open = list(OpenQuestion.class); |
170 | if (nempty(open)) { |
171 | printAsciiHeading("Open questions"); |
172 | for (OpenQuestion oq : open) |
173 | printIndent(renderQuestion(oq.question)); |
174 | } |
175 | |
176 | L<AnsweredQuestion> answered = list(AnsweredQuestion.class); |
177 | if (nempty(answered)) { |
178 | printAsciiHeading("Answered questions"); |
179 | for (AnsweredQuestion aq : answered) { |
180 | printIndent(2, renderQuestion(aq.question)); |
181 | Concept a = aq.answer.get(); |
182 | if (a instanceof ConceptList) |
183 | for (Concept c2 : ((ConceptList) a).list) |
184 | printIndent(4, renderConcept(c2)); |
185 | else |
186 | printIndent(4, renderConcept(a)); |
187 | } |
188 | } |
189 | } |
190 | |
191 | static bool logic_parse(S s) { |
192 | new Matches m; |
193 | if "the plural of * is *" { |
194 | assertEqic(m.unq(1), plural(m.unq(0))); |
195 | assertEqic(m.unq(0), singular(m.unq(1))); |
196 | true; |
197 | } |
198 | |
199 | if "a * has *" { |
200 | Concept main = aThing(m.unq(0)); |
201 | Concept part = concept(singularFromPlural(m.unq(1))); |
202 | uniqueConcept(HasMulti.class, "main", main, "part", part); |
203 | true; |
204 | } |
205 | |
206 | if "a * has a *" { |
207 | Concept main = aThing(m.unq(0)); |
208 | Concept part = concept(m.unq(1)); |
209 | uniqueConcept(HasA.class, "main", main, "part", part); |
210 | true; |
211 | } |
212 | |
213 | if "the number of * in a * is *" { |
214 | Concept main = aThing(m.unq(1)); |
215 | Concept part = concept(singularFromPlural(m.unq(0))); |
216 | int n = parseInt(m.unq(2)); |
217 | uniqueConcept(MultiCount.class, "main", main, "part", part, "count", n); |
218 | true; |
219 | } |
220 | |
221 | if "let's assume * is a *" || "* is a *" { |
222 | Concept thing = concept(m.unq(0)); |
223 | Concept type = aThing(m.unq(1)); |
224 | uniqueConcept(IsA.class, "thing", thing, "type", type); |
225 | true; |
226 | } |
227 | |
228 | if "how many * are in *" { |
229 | Concept main = concept(m.unq(1)); |
230 | Concept part = concept(singularFromPlural(m.unq(0))); |
231 | uniqueConcept(OpenQuestion.class, "question", |
232 | uniqueConcept(HowManyAreIn.class, "originalText", s, "main", main, "part", part)); |
233 | true; |
234 | } |
235 | |
236 | if "what does * have" { |
237 | Concept thing = concept(m.unq(0)); |
238 | newQ(uniqueConcept(WhatDoesXHave.class, "originalText", s, "thing", thing)); |
239 | true; |
240 | } |
241 | |
242 | if "does * have a *" { |
243 | Concept x = concept(m.unq(0)); |
244 | Concept y = concept(m.unq(1)); |
245 | newQ(uniqueConcept(DoesXHaveAY.class, "originalText", s, "x", x, "y", y)); |
246 | true; |
247 | } |
248 | |
249 | if "* is a synonym of *" { |
250 | mergeStrs(concept(m.unq(0)), concept(m.unq(1))); |
251 | true; |
252 | } |
253 | |
254 | if (trim(s).endsWith("?")) { |
255 | uniqueConcept(OpenQuestion.class, "question", |
256 | uniqueConcept(Question.class, "originalText", s)); |
257 | true; |
258 | } |
259 | |
260 | false; |
261 | } |
262 | |
263 | static void newQ(Question q) { |
264 | uniqueConcept(OpenQuestion.class, "question", q); |
265 | } |
266 | |
267 | static void logic_processRules { |
268 | // Infer statements. |
269 | |
270 | // x is a y && a y has n z => x has n z |
271 | |
272 | for (IsA isA : list(IsA.class)) { |
273 | Concept x = isA.thing.get(), y = isA.type.get(); |
274 | for (MultiCount mc : conceptsWhere(MultiCount.class, "main", y)) |
275 | uniqueConcept(MultiCount.class, "main", x, "part", mc.part, "count", mc.count); // todo: automate the copying |
276 | } |
277 | |
278 | // x is a y && a y has a z => x has a z |
279 | for (IsA isA : list(IsA.class)) { |
280 | Concept x = isA.thing.get(), y = isA.type.get(); |
281 | for (HasA h : conceptsWhere(HasA.class, "main", y)) |
282 | uniqueConcept(HasA.class, "main", x, "part", h.part); |
283 | } |
284 | |
285 | // x has a y => x has "the y of x" |
286 | for (HasA h : list(HasA.class)) |
287 | if (h.main.get() instanceof DefiniteThing) |
288 | uniqueConcept(Has.class, "main", h.main, "part", |
289 | uniqueConcept(TheXOfY.class, "x", h.part, "y", h.main)); |
290 | |
291 | // Answer questions. |
292 | |
293 | for (OpenQuestion oq : list(OpenQuestion.class)) { |
294 | Question _q = oq.question.get(); |
295 | |
296 | if (_q instanceof HowManyAreIn) { |
297 | HowManyAreIn q = cast _q; |
298 | MultiCount mc = conceptWhere(MultiCount.class, "main", q.main, "part", q.part); |
299 | if (mc != null) |
300 | answerQuestion(q, mc); |
301 | } |
302 | |
303 | if (_q instanceof WhatDoesXHave) { |
304 | WhatDoesXHave q = cast _q; |
305 | new ConceptList l; |
306 | l.addAll(conceptsWhere(HasA.class, "main", q.thing)); |
307 | l.addAll(conceptsWhere(Has.class, "main", q.thing)); |
308 | answerQuestion(q, l); |
309 | } |
310 | |
311 | if (_q instanceof DoesXHaveAY) { |
312 | DoesXHaveAY q = cast _q; |
313 | if (hasConcept(HasA.class, "main", q.x, "part", q.y)) |
314 | answerQuestion(q, true); |
315 | } |
316 | } |
317 | } |
318 | |
319 | svoid logic_main { |
320 | L<S> sentences = sentencesFromHTML(input); |
321 | print(numberLines(sentences)); |
322 | |
323 | for (S s : sentences) { |
324 | if (!logic_parse(s)) |
325 | print("? " + s); |
326 | } |
327 | |
328 | processRulesMulti(); |
329 | printConcepts(); |
330 | printQuestionsAndAnswers(); |
331 | if (countConcepts(OpenQuestion.class) == 0) |
332 | print("\nAll questions answered!"); |
333 | else |
334 | print("\nOpen questions remaining."); |
335 | } |
Began life as a copy of #1005253
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1005254 |
Snippet name: | Logic 3 [Include, with synonyms] |
Eternal ID of this version: | #1005254/1 |
Text MD5: | 2d63ecffbf9446f20f48106c6c223707 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-10-29 02:37:32 |
Source code size: | 8181 bytes / 335 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 550 / 502 |
Referenced in: | [show references] |