Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

589
LINES

< > BotCompany Repo | #1002855 // class Prolog (old 2)

JavaX fragment (include) [tags: archive]

1  
!752
2  
3  
static final class Prolog {
4  
  boolean upperCaseVariables = false; // true for SNL, false for NL
5  
  long varCount;
6  
  boolean showStuff;
7  
  new L<Entry> stack;
8  
  Trail sofar = null;
9  
  new L<Clause> program;
10  
  new L<L<Clause>> programByArity;
11  
  long steps;
12  
  new L<Native> natives;
13  
  
14  
  // stats
15  
  int maxLevelSeen; // maximum stack level reached during computation
16  
  long topUnifications;
17  
18  
  static interface Native {
19  
    public boolean yo(Prolog p, Lisp term);
20  
  }
21  
  
22  
  static class Var extends Lisp {
23  
    long id;
24  
    Lisp instance;
25  
    
26  
    *(S name) {
27  
      super(name);
28  
      instance = this;
29  
    }
30  
    
31  
    *(long id) {
32  
      super("___");
33  
      this.id = id;
34  
      instance = this;
35  
    }
36  
    
37  
    void reset() { instance = this; }
38  
    
39  
    public String toString() {
40  
      if (instance != this)
41  
        ret instance.toString();
42  
      ret isUserVar() ? getName() : "_" + id;
43  
    }
44  
    
45  
    boolean isUserVar() {
46  
      ret id == 0;
47  
    }
48  
    
49  
    S getName() {
50  
      ret head;
51  
    }
52  
    
53  
    Lisp getValue() {
54  
      Lisp l = instance;
55  
      while (l instanceof Var) {
56  
        Var v = cast l;
57  
        if (v.instance == v)
58  
          ret v;
59  
        l = v.instance;
60  
      }
61  
      ret l;
62  
    }
63  
  }
64  
  
65  
  class Clause {
66  
    Lisp head;
67  
    Goal body;
68  
    
69  
    *(Lisp *head, Goal *body) {}
70  
    *(Lisp *head) {}
71  
    
72  
    Clause copy() {
73  
      return new Clause(Prolog.this.copy(head), body == null ? null : body.copy());
74  
    }
75  
    
76  
    public String toString() {
77  
      //ret head + " :- " + (body == null ? "true" : body);
78  
      ret body == null ? head.toString() : head + " :- " + body;
79  
    }
80  
  }
81  
82  
  class Trail {
83  
    Var tcar;
84  
    Trail tcdr;
85  
    
86  
    *(Var *tcar, Trail *tcdr) {}
87  
  }
88  
  
89  
  Trail Trail_Note() { return sofar; }
90  
  void Trail_Push(Var x) { sofar = new Trail(x, sofar); }
91  
  void Trail_Undo(Trail whereto) {
92  
    for (; sofar != whereto; sofar = sofar.tcdr)
93  
      sofar.tcar.reset();
94  
  }
95  
  
96  
  static class TermVarMapping {
97  
    new L<Var> vars;
98  
    
99  
    *(L<Var> *vars) {}
100  
    *(Var... vars) { this.vars.addAll(asList(vars)); }
101  
    
102  
    void showanswer() {
103  
      print("TRUE.");
104  
      for (Var v : vars)
105  
        print("  " + v.getName() + " = " + v);
106  
    }
107  
  }
108  
      
109  
  class Goal {
110  
    Lisp car;
111  
    Goal cdr;
112  
    
113  
    *(Lisp *car, Goal *cdr) {}
114  
    *(Lisp *car) {}
115  
    
116  
    public String toString() {
117  
      ret cdr == null ? car.toString() : car + "; " + cdr;
118  
    }
119  
    
120  
    Goal copy() {
121  
      return new Goal(Prolog.this.copy(car),
122  
        cdr == null ? null : cdr.copy());
123  
    }
124  
    
125  
    Goal append(Goal l) {
126  
      return new Goal(car, cdr == null ? null : cdr.append(l));
127  
    }
128  
    
129  
  } // class Goal
130  
  
131  
  boolean unify(Lisp thiz, Lisp t) {
132  
    if (thiz == null) fail("thiz=null");
133  
    if (t == null) fail("t=null");
134  
    
135  
    if (thiz instanceof Var) { // TermVar::unify
136  
      Var v = cast thiz;
137  
      if (v.instance != v)
138  
        return unify(v.instance, t);
139  
      Trail_Push(v);
140  
      v.instance = t;
141  
      return true;
142  
    }
143  
    
144  
    // TermCons::unify
145  
    return unify2(t, thiz);
146  
  }
147  
  
148  
  boolean unify2(Lisp thiz, Lisp t) { 
149  
    if (thiz instanceof Var)
150  
      return unify(thiz, t);
151  
   
152  
    int arity = thiz.size();
153  
    if (neq(thiz.head, t.head) || arity != t.size())
154  
      return false;
155  
    for (int i = 0; i < arity; i++)
156  
      if (!unify(thiz.get(i), t.get(i)))
157  
        return false;
158  
    return true;
159  
  }
160  
  
161  
  Lisp copy(Lisp thiz) {
162  
    if (thiz instanceof Var) {
163  
      Var v = cast thiz;
164  
      if (v.instance == v) {
165  
        Trail_Push(v);
166  
        v.instance = newVar();
167  
      }
168  
      return v.instance;
169  
    }
170  
    
171  
    // copy2 (copy non-var)
172  
    Lisp l = new Lisp(thiz.head);
173  
    for (Lisp arg : thiz)
174  
      l.add(copy(arg));
175  
    ret l;
176  
  }
177  
  
178  
  Var newVar() {
179  
    ret new Var(++varCount);
180  
  }
181  
  
182  
  Var newVar(S name) {
183  
    ret new Var(name);
184  
  }
185  
  
186  
  Clause clause(Lisp head, Goal body) {
187  
    ret prologify(new Clause(head, body));
188  
  }
189  
  
190  
  Clause clause(Lisp rule) {
191  
    L<Lisp> ops = snlSplitOps(rule);
192  
    if (showStuff)
193  
      print("clause(Lisp): " + rule + " => " + structure(ops)); 
194  
      
195  
    if (!empty(ops) && last(ops).is("then *")) {
196  
      Lisp head = last(ops).get(0);
197  
      Goal goal = null;
198  
      
199  
      // TODO: check the actual words (if/and/...)
200  
      for (int i = l(ops)-2; i >= 0; i--)
201  
        goal = new Goal(ops.get(i).get(0), goal);
202  
        
203  
      ret clause(head, goal);
204  
    } else
205  
      ret clause(rule, (Lisp) null);
206  
  }
207  
  
208  
  Clause clause(Lisp head, Lisp body) {
209  
    ret clause(head, body == null ? null : new Goal(body));
210  
  }
211  
  
212  
  Lisp prologify(Lisp term) {
213  
    ret prologify(term, new HashMap);
214  
  }
215  
  
216  
  Clause prologify(Clause c) {
217  
    new HashMap vars;
218  
    c = new Clause(
219  
      prologify(c.head, vars),
220  
      prologify(c.body, vars));
221  
    if (showStuff)
222  
      print("Clause made: " + structure_seen(c));
223  
    ret c;
224  
  }
225  
  
226  
  Goal prologify(Goal goal, Map<S, Var> vars) {
227  
    if (goal == null) ret null;
228  
    ret new Goal(
229  
      prologify(goal.car, vars),
230  
      prologify(goal.cdr, vars));
231  
  }
232  
  
233  
  boolean isVar(Lisp term) {
234  
    ret upperCaseVariables ? snlIsVar(term) : nlIsVar(term);
235  
  }
236  
  
237  
  Lisp prologify(Lisp term, Map<S, Var> vars) {
238  
    if (term == null) ret null;
239  
    if (isVar(term)) {
240  
      Var v = vars.get(term.head);
241  
      if (v == null)
242  
        vars.put(term.head, v = newVar(term.head));
243  
      ret v;
244  
    } else {
245  
      Lisp l = new Lisp(term.head);
246  
      for (Lisp arg : term)
247  
        l.add(prologify(arg, vars));
248  
      ret l;
249  
    }
250  
  }
251  
  
252  
  L<Var> findVars(Goal g) {
253  
    new IdentityHashMap<Var, Boolean> map;
254  
    while (g != null) {
255  
      findVars(g.car, map);
256  
      g = g.cdr;
257  
    }
258  
    ret asList(map.keySet());
259  
  }
260  
  
261  
  L<Var> findVars(Lisp term) {
262  
    new IdentityHashMap<Var, Boolean> map;
263  
    findVars(term, map);
264  
    ret asList(map.keySet());
265  
  }
266  
  
267  
  void findVars(Lisp term, IdentityHashMap<Var, Boolean> map) {
268  
    if (term instanceof Var)
269  
      map.put((Var) term, Boolean.TRUE);
270  
    else
271  
      for (Lisp arg : term)
272  
        findVars(arg, map);
273  
  }
274  
  
275  
  static Map<S, Var> makeVarMap(L<Var> vars) {
276  
    new HashMap<S, Var> map;
277  
    for (Var v : vars)
278  
      map.put(v.getName(), v);
279  
    ret map;
280  
  }
281  
  
282  
  // Executor stack entry
283  
  static class Entry {
284  
    Goal goal;
285  
    int programIdx = -1; // -1 is natives
286  
    Trail trail;
287  
    boolean trailSet;
288  
    boolean cutPoint;
289  
    
290  
    *(Goal *goal) {}
291  
  }
292  
  
293  
  void start(Lisp goal) {
294  
    start(new Goal(prologify(goal)));
295  
  }
296  
  
297  
  // warning: doesn't prologify the goal
298  
  void start(Goal goal) {
299  
    if (showStuff)
300  
      print("start: " + structure_seen(goal));
301  
    steps = 0;
302  
    stack = new L;
303  
    Trail_Undo(null);
304  
    stackAdd(new Entry(goal));
305  
  }
306  
    
307  
  int level() {
308  
    ret l(stack)-1;
309  
  }
310  
  
311  
  boolean done() {
312  
    ret empty(stack);
313  
  }
314  
315  
  boolean gnext(Goal g) {  
316  
    Goal gdash = g.cdr;
317  
    if (gdash == null)
318  
      ret true;
319  
    else {
320  
      stackAdd(new Entry(gdash));
321  
      ret false;
322  
    }
323  
  }
324  
  
325  
  void stackPop() {
326  
    Entry e = popLast(stack);
327  
    if (e.trailSet)
328  
      Trail_Undo(e.trail);
329  
  }
330  
  
331  
  void backToCutPoint() {
332  
    if (showStuff)
333  
      print("back to cut point.");
334  
    while (!empty(stack) && !last(stack).cutPoint) {
335  
      if (showStuff)
336  
        print("cut: dropping " + structure(last(stack)));
337  
      stackPop();
338  
    }
339  
    for (int i = 0; i < 2; i++) {
340  
      if (!empty(stack)) {
341  
        if (showStuff)
342  
          print("cut: dropping " + i + " " + structure(last(stack)));
343  
        stackPop();
344  
      }
345  
    }
346  
  }
347  
348  
  boolean step() {
349  
    if (done()) fail("done!"); // safety
350  
    
351  
    ++steps;
352  
    Entry e = last(stack);
353  
    
354  
    if (e.trailSet) {
355  
      Trail_Undo(e.trail);
356  
      e.trailSet = false;
357  
    }
358  
    
359  
    e.trail = Trail_Note();
360  
    e.trailSet = true;
361  
    
362  
    // cut operator - suceeds first time
363  
    if (e.goal.car.is("!", 0)) {
364  
      if (showStuff)
365  
        print("cut " + e.programIdx + ". " + structure(e.goal));
366  
      if (e.programIdx == -1) {
367  
        ++e.programIdx;
368  
        ret gnext(e.goal);
369  
      } else if (e.programIdx == 0) {
370  
        ++e.programIdx;
371  
        // fails 2nd time and cuts
372  
        //e.goal.car.head = "false"; // super-hack :D
373  
        backToCutPoint();
374  
        ret false;
375  
      } else {
376  
        stackPop();
377  
        ret false;
378  
      }
379  
    }
380  
381  
    if (e.programIdx >= l(program)) { // program loop ends
382  
      removeLast(stack);
383  
      ret false;
384  
    }
385  
      
386  
    if (e.programIdx == -1) {
387  
      if (showStuff)
388  
        print(indent(level()) + "solve@" + level() + ": " + e.goal);
389  
      ++e.programIdx;
390  
        
391  
      // try native functions
392  
      if (goNative(e.goal.car)) {
393  
        if (showStuff)
394  
          print(indent(level()) + "native!");
395  
          
396  
        ret gnext(e.goal);
397  
      }
398  
      
399  
      ret false;
400  
    }
401  
      
402  
    // now in program loop
403  
    
404  
    Clause c = program.get(e.programIdx).copy();
405  
    ++e.programIdx;
406  
    Trail_Undo(e.trail);
407  
    if (showStuff)
408  
      print(indent(level()) + "  try:" + c);
409  
    ++topUnifications;
410  
    if (unify(e.goal.car, c.head)) {
411  
      Goal gdash = c.body == null ? e.goal.cdr : c.body.append(e.goal.cdr);
412  
      if (gdash == null)
413  
        ret true;
414  
      else {
415  
        Entry e2 = new Entry(gdash);
416  
        if (c.body != null)
417  
          e2.cutPoint = true;
418  
        stackAdd(e2);
419  
        ret false;
420  
      }
421  
    } else
422  
      if (showStuff)
423  
        print(indent(level()) + "  nomatch.");
424  
        
425  
    ret false;
426  
  }
427  
  
428  
  void stackAdd(Entry e) {
429  
    stack.add(e);
430  
    int n = l(stack);
431  
    if (n > maxLevelSeen) maxLevelSeen = n;
432  
  }
433  
  
434  
  void addClause(Lisp c) {
435  
    addClause(clause(c));
436  
  }
437  
  
438  
  void addClause(Clause c) {
439  
    program.add(c);
440  
    int arity = c.head.size();
441  
    while (arity >= l(programByArity))
442  
      programByArity.add(new L);
443  
    programByArity.get(arity).add(c);
444  
  }
445  
  
446  
  boolean canSolve(Lisp goal) {
447  
    ret canSolve(new Goal(prologify(goal)));
448  
  }
449  
  
450  
  boolean canSolve(Goal goal) {
451  
    start(goal);
452  
    while (!done())
453  
      if (step())
454  
        ret true;
455  
    ret false;
456  
  }
457  
  
458  
  // return variable map or null if unsolved
459  
  Map<S, Lisp> solve(Lisp goal) {
460  
    Goal g = new Goal(prologify(goal));
461  
    if (!canSolve(g))
462  
      ret null;
463  
    ret getUserVarMap();
464  
  }
465  
  
466  
  Map<S, Lisp> getUserVarMap() {
467  
    Goal g = stack.get(0).goal;
468  
    new HashMap<S, Lisp> map;
469  
    for (Var v : findVars(g))
470  
      if (v.isUserVar())
471  
        map.put(v.getName(), v.getValue());
472  
    ret map;
473  
  }
474  
  
475  
  Map<S, Lisp> nextSolution() {
476  
    while (!done())
477  
      if (step())
478  
        ret getUserVarMap();
479  
    ret null;
480  
  }
481  
  
482  
  void addTheory(S text) {
483  
    for (Lisp part : nlParseToTheory(text))
484  
      addClause(part);
485  
  }
486  
  
487  
  // shouldn't use anymore
488  
  void addClauses(Lisp tree) {
489  
    if (isJuxta(tree) && snlSplitOps(tree) == null)
490  
      for (Lisp part : tree)
491  
        addClause(part);
492  
    else
493  
      addClause(tree);
494  
  }
495  
  
496  
  boolean goNative(Lisp term) {
497  
    term = resolve(term);
498  
    
499  
    for (Native n : natives) {
500  
      Trail t = Trail_Note();
501  
      boolean result;
502  
      try {
503  
        result = n.yo(this, term);
504  
      } catch (Exception e) {
505  
        Trail_Undo(t);
506  
        continue;
507  
      }
508  
      if (!result) {
509  
        Trail_Undo(t);
510  
        continue;
511  
      }
512  
      ret true;
513  
    }
514  
515  
    if (term.is("nativeTest", 0))
516  
      ret true;
517  
      
518  
    if (term.is("true", 0))
519  
      ret true;
520  
      
521  
    if (term.is("isQuoted", 1)) {
522  
      Lisp x = term.get(0);
523  
      ret !(x instanceof Var) && x.isLeaf() && isQuoted(x.head);
524  
    }
525  
      
526  
    ret false;
527  
  }
528  
  
529  
  boolean unifyOrRollback(Lisp a, Lisp b) {
530  
    Trail t = Trail_Note();
531  
    if (unify(a, b)) ret true;
532  
    Trail_Undo(t);
533  
    ret false;
534  
  }
535  
  
536  
  // resolve all variables
537  
  Lisp resolve(Lisp term) {
538  
    if (term instanceof Var)
539  
      ret ((Var) term).getValue();
540  
      
541  
    // smart recurse
542  
    for (int i = 0; i < term.size(); i++) {
543  
      Lisp l = term.get(i);
544  
      Lisp r = resolve(l);
545  
      if (l != r) {
546  
        Lisp x = new Lisp(term.head);
547  
        for (int j = 0; j < i; j++)
548  
          x.add(term.get(j));
549  
        x.add(r);
550  
        for (i++; i < term.size(); i++)
551  
          x.add(resolve(term.get(i)));
552  
        ret x;
553  
      }
554  
    }
555  
    
556  
    ret term;
557  
  }
558  
  
559  
  // looks for a bodyless rule in the program that matches the term
560  
  boolean containsStatement(Lisp term) {
561  
    for (Clause c : program)
562  
      if (c.body == null && eq(c.head, term))
563  
        ret true;
564  
    ret false;
565  
  }
566  
  
567  
  // closed == contains no variables
568  
  boolean isClosedTerm(Lisp term) {
569  
    if (term instanceof Var)
570  
      ret false;
571  
    else
572  
      for (Lisp arg : term)
573  
        if (!isClosedTerm(arg))
574  
          ret false;
575  
    ret true;
576  
  }
577  
  
578  
  void addNative(Native n) {
579  
    natives.add(n);
580  
  }
581  
  
582  
  L<Lisp> getStackTerms() {
583  
    new L<Lisp> l;
584  
    for (Entry e : stack)
585  
      l.add(e.goal.car);
586  
    ret l;
587  
  }
588  
  
589  
} // class Prolog

Author comment

Began life as a copy of #1002826

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: #1002855
Snippet name: class Prolog (old 2)
Eternal ID of this version: #1002855/1
Text MD5: a5b70fc1297d6502ac2412c5223baa63
Author: stefan
Category: javax
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2016-03-05 17:46:07
Source code size: 13202 bytes / 589 lines
Pitched / IR pitched: No / No
Views / Downloads: 544 / 485
Referenced in: [show references]