Libraryless. Click here for Pure Java version (7809L/50K/164K).
1 | !759 |
2 | |
3 | !include #1002884 // Prolog with shared clauses |
4 | !include #1002933 // Natives |
5 | |
6 | static boolean showLog, printTimings = true; |
7 | static Prolog p; |
8 | static Prolog parsingInterpreter; |
9 | //static O theoryBot; |
10 | static Method getTheoryMethod; |
11 | |
12 | p { |
13 | new Prolog p; |
14 | parsingInterpreter = p; |
15 | p.addNatives(new IntMul, new IntDiv, new IntAdd, new IntMinus); |
16 | p.addNatives(new GreaterThan, new HeadExists, new TheoriesList); |
17 | p.addNatives(new tocons, new fromcons, new LessThan, new arg, new Arity); |
18 | p.addNatives(new operator, new Unquote, new IsQuoted, new IsWord, new RemoveWord, new GetTheory, new TextOfTheory); |
19 | p.addNatives(new Solve1, new Think, new MemorizeImpl, new RewriteWithTheory, new NLSafeParse); |
20 | p.addNatives(new StartsWith); |
21 | } |
22 | |
23 | static class CacheEntry { |
24 | S text; |
25 | Lisp parsed; |
26 | L<Prolog.Clause> program; |
27 | |
28 | *(S *text) { |
29 | } |
30 | |
31 | Lisp getParsed() { |
32 | if (parsed == null) |
33 | parsed = nlParse(text); |
34 | ret parsed; |
35 | } |
36 | |
37 | L<Prolog.Clause> getProgram() { |
38 | if (program == null) |
39 | program = parsingInterpreter.parseProgram(text); |
40 | ret program; |
41 | } |
42 | } |
43 | |
44 | static new Map<CIString, CacheEntry> parseCache; |
45 | |
46 | static S getTheoryFromBot(S name) ctex { |
47 | if (getTheoryMethod != null) |
48 | ret (S) getTheoryMethod.invoke(null, name); |
49 | ret (S) callOpt(theoryBot(), "getTheoryOpt", name); |
50 | } |
51 | |
52 | static void cacheGetTheoryMethod() { |
53 | getTheoryMethod = findMethod(theoryBot(), "getTheoryOpt", ""); |
54 | } |
55 | |
56 | static S findTheory(S name) { |
57 | ret getTheoryFromBot(name); |
58 | } |
59 | |
60 | static S saveTheory(S name, S text) { |
61 | ret (S) callOpt(theoryBot(), "saveTheory", name, text); |
62 | } |
63 | |
64 | static Lisp getParsedTheory(S name) { |
65 | CacheEntry entry = getCacheEntry(name); |
66 | ret entry == null ? null : entry.getParsed(); |
67 | } |
68 | |
69 | static L<Prolog.Clause> getProgram(S name) { |
70 | CacheEntry entry = getCacheEntry(name); |
71 | ret entry == null ? null : entry.getProgram(); |
72 | } |
73 | |
74 | static CacheEntry getCacheEntry(S name) { |
75 | S text = findTheory(name); |
76 | if (text == null) ret null; |
77 | |
78 | CacheEntry entry = parseCache.get(new CIString(name)); |
79 | if (entry == null || neq(entry.text, text)) { |
80 | entry = new CacheEntry(text); |
81 | parseCache.put(new CIString(name), entry); |
82 | } |
83 | ret entry; |
84 | } |
85 | |
86 | static S prettyPrintTerms(L<Lisp> l, boolean outerBrackets) { |
87 | new L<S> out; |
88 | for (Lisp term : l) { |
89 | S s = nlUnparse(term, !outerBrackets); |
90 | //out.add(outerBrackets ? "[" + s + "]" : s); |
91 | out.add(s); |
92 | } |
93 | ret joinLines(out); |
94 | } |
95 | |
96 | static void loadTheories(Prolog p, L<S> theoryNames) { |
97 | if (theoryNames.contains("signed")) { |
98 | theoryNames.remove("signed"); |
99 | theoryNames.addAll(getLiveTheories()); |
100 | } |
101 | |
102 | if (theoryNames.contains("signedstefan")) { |
103 | theoryNames.remove("signedstefan"); |
104 | theoryNames.addAll(getLiveTheories ("stefanreich")); |
105 | } |
106 | |
107 | cacheGetTheoryMethod(); |
108 | try { |
109 | for (S t : asSet(theoryNames)) { // todo: ignore case |
110 | loadTheoryImpl(p, t); |
111 | long n = getTheoryCounter(t); |
112 | for (long i = 1; i <= n; i++) |
113 | loadTheoryImpl(p, t + "." + i); |
114 | } |
115 | } finally { |
116 | getTheoryMethod = null; |
117 | } |
118 | } |
119 | |
120 | static long getTheoryCounter(S name) { |
121 | //ret (long) call(theoryBot(), "getTheoryCounter", name); |
122 | S text = findTheory(name + ".count"); |
123 | ret isEmpty(text) ? 0 : parseLong(text); |
124 | } |
125 | |
126 | static void loadTheoryImpl(Prolog p, S name) { |
127 | L<Prolog.Clause> program = getProgram(name); |
128 | if (program != null) |
129 | p.addProgram(program, name); |
130 | } |
131 | |
132 | static S solutionPrettyPrint(Map<S, Lisp> solution) { |
133 | S s = "FALSE"; |
134 | if (solution != null) { |
135 | new L<S> l; |
136 | solution = new TreeMap(solution); // sort |
137 | for (S var : solution.keySet()) |
138 | l.add(var + " = " + nlUnparse(solution.get(var), false)); |
139 | s = "TRUE.\n" + slackSnippetOpt(joinLines(l)); |
140 | } |
141 | /*if (showStack) |
142 | s += "\nStack:" + slackSnippetOpt(prettyPrintTerms(p.getStackTerms(), false));*/ |
143 | if (showLog) { |
144 | L<S> usedTheories = p.getUsedTheories(); |
145 | L<S> lines = litlist("Used theories: " + join(", ", usedTheories)); |
146 | L<Lisp> mem = p.getMemorizedStatements(); |
147 | if (nempty(mem)) { |
148 | lines.add("Thoughts:"); |
149 | for (Lisp x : mem) |
150 | lines.add(" " + nlUnparse(x)); |
151 | } |
152 | lines.addAll(p.log); |
153 | s += "\n" + slackSnippet(lines); |
154 | } |
155 | ret s; |
156 | } |
157 | |
158 | static Prolog newProlog(L<S> theoryNames) { |
159 | ret p = newSubProlog(theoryNames, showLog); |
160 | } |
161 | |
162 | static Prolog newProlog(L<S> theoryNames, boolean showLog) { |
163 | ret p = newSubProlog(theoryNames, showLog); |
164 | } |
165 | |
166 | static Prolog newSubProlog(L<S> theoryNames, boolean showLog) { |
167 | long startTime = now(); |
168 | int parses = nlParse_count.get(); |
169 | |
170 | Prolog p = new Prolog; |
171 | if (showLog) |
172 | p.logOn(); |
173 | |
174 | p.copyProgramFrom(parsingInterpreter); // natives! |
175 | |
176 | long t2 = now(); |
177 | loadTheories(p, theoryNames); |
178 | if (printTimings) { |
179 | parses = nlParse_count.get()-parses; |
180 | long end = now(); |
181 | long time = end-startTime; |
182 | t2 = end-t2; |
183 | print("Making prolog interpreter with " + l(theoryNames) + " theories: " + time + " ms (" + parses + " parses, " + t2 + " ms in loadTheories)"); |
184 | } |
185 | ret p; |
186 | } |
187 | |
188 | // n = how many solutions to print |
189 | static S solve(Lisp question, L<S> theoryNames, int n) { |
190 | new StringBuilder buf; |
191 | |
192 | question = new EvalTransform().evalTransformQuestion(question); |
193 | |
194 | newProlog(theoryNames); |
195 | |
196 | time { |
197 | try { |
198 | Map<S, Lisp> solution = p.solve(question); |
199 | if (solution == null) |
200 | buf.append("FALSE in " + structure(theoryNames) + (p.log != null ? "\n" + slackSnippet(p.log) : "")); |
201 | else { |
202 | buf.append(solutionPrettyPrint(solution) + "\n"); |
203 | |
204 | while (--n > 0) { |
205 | solution = p.nextSolution(); |
206 | if (solution == null) break; |
207 | buf.append(solutionPrettyPrint(solution) + "\n"); |
208 | } |
209 | |
210 | if (p.nextSolution() != null) |
211 | buf.append("[more]"); |
212 | else |
213 | buf.append("[done]"); |
214 | } |
215 | } catch (Exception e) { |
216 | ret e + "\n" + slackSnippet(p.log); |
217 | } |
218 | } |
219 | |
220 | buf.append(" " + lastTiming() + " ms"); |
221 | |
222 | ret str(buf); |
223 | } |
224 | |
225 | static L<S> nlParseStringList(Lisp tree) { |
226 | if (tree.isLeaf()) |
227 | ret litlist(unquote(tree.raw())); |
228 | new L<S> l; |
229 | for (Lisp t : tree) { |
230 | if (!t.isLeaf()) continue; // huh? |
231 | S s = t.head; |
232 | if (eq(s, ",") /*|| eq(s, "and")*/) continue; |
233 | l.add(unquote(s)); |
234 | } |
235 | ret l; |
236 | } |
237 | |
238 | static L<S> getTheoryNames() { |
239 | ret (L) callOpt(theoryBot(), "getTheoryNames"); |
240 | } |
241 | |
242 | static L<S> getLiveTheories() { |
243 | ret concatLists ( |
244 | getLiveTheories (getUserName ()), |
245 | getLiveTheories ("stefanreich")); |
246 | } |
247 | |
248 | static L<S> getLiveTheories(S user) { |
249 | ret empty(user) ? litlist() : (L) callOpt(theoryBot(), "getTheoriesSignedByAs", user, "live"); |
250 | } |
251 | |
252 | static S solve(S s, boolean showLog) { |
253 | main.showLog = showLog; |
254 | |
255 | s = s.trim(); |
256 | int n = 1; |
257 | int i = s.indexOf(']'); |
258 | if (i >= 2) { |
259 | S s2 = dropPrefix("[", substring(s, 0, i)); |
260 | if (isInteger(s2)) { |
261 | n = parseInt(s2); |
262 | s = s.substring(i+1).trim(); |
263 | } |
264 | } |
265 | |
266 | Lisp tree = nlParse(s); |
267 | |
268 | //ret structure(tree); |
269 | |
270 | new Map<S, Lisp> m; |
271 | if (nlMatch("$text in $theory", tree, m)) { |
272 | print("text in theory"); |
273 | Lisp question = m.get("text"); |
274 | Lisp t = m.get("theory"); |
275 | L<S> theoryNames = nlParseStringList(t); |
276 | ret solve(question, theoryNames, n); |
277 | } |
278 | |
279 | if (nlMatch("theory $t", tree, m)) { |
280 | print("theory"); |
281 | S theoryName = unquote(m.get("t").raw()); |
282 | ret solve(nlParse(findTheory(theoryName)), litstringlist("signed"), n); |
283 | } |
284 | |
285 | if (nlMatch("$text", tree, m)) { |
286 | print("text"); |
287 | Lisp question = m.get("text"); |
288 | ret solve(question, litstringlist("signed"), n); |
289 | } |
290 | |
291 | ret "hm?"; |
292 | } |
293 | |
294 | synchronized answer { |
295 | if "top unifications" |
296 | ret p == null ? "-" : str(p.topUnifications); |
297 | |
298 | if (!attn()) ret null; |
299 | |
300 | if (swic(s, "solve ")) exceptionToUser { |
301 | s = dropPrefixIgnoreCase("solve ", s); |
302 | ret solve(s, false); |
303 | } |
304 | |
305 | if (swic(s, "eval ")) exceptionToUser { |
306 | s = trim(dropPrefixIgnoreCase("eval ", s)); |
307 | S var = nlMakeUnusedVar(s); |
308 | s = var + " = " + s; |
309 | ret solve(s, false); |
310 | } |
311 | |
312 | if (swic(s, "log ")) exceptionToUser { |
313 | s = dropPrefixIgnoreCase("log ", s); |
314 | ret solve(s, true); |
315 | } |
316 | |
317 | if (swic(s, "say ")) exceptionToUser { |
318 | s = dropPrefixIgnoreCase("say ", s); |
319 | |
320 | new Map<S, Lisp> mm; |
321 | if (nlMatch("$text in $theory", s, mm)) { |
322 | Lisp question = mm.get("text"); |
323 | Lisp t = mm.get("theory"); |
324 | s = "[[think [user says " + nlUnparse(question, false) + "]] and [say $x]] in " + nlUnparse(t, false); |
325 | print("s = " + s); |
326 | ret solve(s, true); |
327 | } |
328 | ret "woot syntax"; |
329 | } |
330 | |
331 | if "produce *" exceptionToUser { |
332 | ret produce(m.unq(0)); |
333 | } |
334 | |
335 | if "my program" exceptionToUser { |
336 | S user = getUserName(); |
337 | if (empty(user)) ret "go to slack please"; |
338 | p = new Prolog; |
339 | loadTheories(p, getLiveTheories()); |
340 | ret p.showProgram(); |
341 | } |
342 | |
343 | if "log" exceptionToUser { |
344 | ret slackSnippet(p.log); |
345 | } |
346 | |
347 | if "rewrite * with *" exceptionToUser { |
348 | ret rewrite(m.unq(0), m.unq(1), null); |
349 | } |
350 | |
351 | if "rewrite * with * as *" exceptionToUser { |
352 | ret rewrite(m.unq(0), m.unq(1), m.unq(2)); |
353 | } |
354 | |
355 | if "time findTheory" exceptionToUser { |
356 | time { |
357 | //theoryBot = getBot("#1002762"); |
358 | cacheGetTheoryMethod(); |
359 | try { |
360 | for (int i = 0; i < 1000; i++) |
361 | findTheory("and"); |
362 | } finally { |
363 | //theoryBot = null; |
364 | getTheoryMethod = null; |
365 | } |
366 | } |
367 | ret (lastTiming()/1000.0) + " ms"; |
368 | } |
369 | } |
370 | |
371 | static S rewrite(S tname1, S tname2, S tname3) { |
372 | newProlog(litlist(tname1, "signed"), true); |
373 | L<Prolog.Clause> rewriteTheory = p.parseProgram(findTheory(tname2)); |
374 | L<Lisp> rewritten = p.rewriteWith(rewriteTheory); |
375 | S text = prettyPrintTerms(rewritten, true); |
376 | if (tname3 == null) |
377 | ret slackSnippet(text) + "\n" + slackSnippet(p.log); |
378 | ret saveTheory(tname3, text); |
379 | } |
380 | |
381 | static S produce(S theoryName) { |
382 | S outName = theoryName + ".out"; |
383 | |
384 | showLog = false; |
385 | newProlog(litlist(theoryName)); |
386 | S question = "say $x"; |
387 | Lisp out = lisp("[]"); |
388 | p.start(question); |
389 | int max = 100; |
390 | while (out.size() < max) { |
391 | Map<S, Lisp> solution = p.nextSolution(); |
392 | if (solution == null) break; |
393 | out.add(solution.get("$x")); |
394 | } |
395 | |
396 | ret (out.size() >= max ? "WARNING MAXED OUT\n" : "") + saveTheory(outName, nlUnparse(out)); |
397 | } |
398 | |
399 | static void incrementTheory(S name, Lisp value) { |
400 | call(theoryBot(), "incrementTheory", name, nlUnparse(value)); |
401 | } |
402 | |
403 | static O theoryBot() { |
404 | ret /*or(theoryBot,*/ getBot("#1002762")/*)*/; |
405 | } |
Began life as a copy of #1002837
download show line numbers debug dex old transpilations
Travelled to 13 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt
No comments. add comment
Snippet ID: | #1002841 |
Snippet name: | Prolog Bot (LIVE!) |
Eternal ID of this version: | #1002841/1 |
Text MD5: | 4dfaa70d562d8b64a2960c408c85c4d2 |
Transpilation MD5: | 203c344b63b31321293fa6752eea54bd |
Author: | stefan |
Category: | eleu / nl |
Type: | JavaX source code |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2016-10-19 02:03:03 |
Source code size: | 10756 bytes / 405 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 1378 / 1872 |
Referenced in: | [show references] |