// unify two compounds terms with deep structure. unification fails func BenchmarkUnifyDeepFail(b *testing.B) { x := read.Term_(`a(b(c(d(e(f(g(h(i(j))))))))).`) y := read.Term_(`a(b(c(d(e(f(g(h(i(x))))))))).`) env := term.NewBindings() for i := 0; i < b.N; i++ { _, _ = x.Unify(env, y) } }
func TestAsserta(t *testing.T) { db0 := NewDatabase() db1 := db0.Asserta(NewAtom("alpha")) db2 := db1.Asserta(NewAtom("beta")) db3 := db2.Asserta(read.Term_(`foo(one,two) :- alpha.`)) t.Logf(db3.String()) // helpful for debugging // do we have the right number of clauses? if db0.ClauseCount() != 0 { t.Errorf("db0: wrong number of clauses: %d", db0.ClauseCount()) } if db1.ClauseCount() != 1 { t.Errorf("db0: wrong number of clauses: %d", db0.ClauseCount()) } if db2.ClauseCount() != 2 { t.Errorf("db0: wrong number of clauses: %d", db0.ClauseCount()) } if db3.ClauseCount() != 3 { t.Errorf("db0: wrong number of clauses: %d", db0.ClauseCount()) } // is alpha/0 present where it should be? if cs := db1.Candidates_(NewAtom("alpha")); len(cs) != 1 { t.Errorf("db1: can't find alpha/0") } if cs := db2.Candidates_(NewAtom("alpha")); len(cs) != 1 { t.Errorf("db2: can't find alpha/0") } if cs := db3.Candidates_(NewAtom("alpha")); len(cs) != 1 { t.Errorf("db3: can't find alpha/0") } // is beta/0 present where it should be? if _, err := db1.Candidates(NewAtom("beta")); err == nil { t.Errorf("db1: shouldn't have found beta/0") } if cs := db2.Candidates_(NewAtom("beta")); len(cs) != 1 { t.Errorf("db2: can't find beta/0") } if cs := db3.Candidates_(NewAtom("beta")); len(cs) != 1 { t.Errorf("db3: can't find beta/0") } // is foo/2 present where it should be? term := read.Term_(`foo(one,two).`) if _, err := db1.Candidates(term); err == nil { t.Errorf("db1: shouldn't have found foo/2") } if _, err := db2.Candidates(term); err == nil { t.Errorf("db2: shouldn't have found foo/2") } if cs := db3.Candidates_(term); len(cs) != 1 { t.Errorf("db3: can't find foo/2") } }
func BenchmarkTrue(b *testing.B) { m := NewMachine() g := read.Term_(`true.`) for i := 0; i < b.N; i++ { _ = m.ProveAll(g) } }
func BenchmarkAppend(b *testing.B) { m := NewMachine().Consult(` append([], A, A). % test same variable name as other clauses append([A|B], C, [A|D]) :- append(B, C, D). `) g := read.Term_(`append([a,b,c], [d,e], List).`) for i := 0; i < b.N; i++ { _ = m.ProveAll(g) } }
// traditional, naive reverse benchmark // The Art of Prolog by Sterling, etal says that reversing a 30 element // list using this technique does 496 reductions. From this we can // calculate a rough measure of Golog's LIPS. func BenchmarkNaiveReverse(b *testing.B) { m := NewMachine().Consult(` append([], A, A). append([A|B], C, [A|D]) :- append(B, C, D). reverse([],[]). reverse([X|Xs], Zs) :- reverse(Xs, Ys), append(Ys, [X], Zs). `) g := read.Term_(`reverse([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30], As).`) for i := 0; i < b.N; i++ { _ = m.ProveAll(g) } }
// test performance of a standard maplist implementation func BenchmarkMaplist(b *testing.B) { m := NewMachine().Consult(` always_a(_, a). maplist(C, A, B) :- maplist_(A, B, C). maplist_([], [], _). maplist_([B|D], [C|E], A) :- call(A, B, C), maplist_(D, E, A). `) g := read.Term_(`maplist(always_a, [1,2,3,4,5], As).`) for i := 0; i < b.N; i++ { _ = m.ProveAll(g) } }
func BenchmarkDCGish(b *testing.B) { m := NewMachine().Consult(` name([alice |X], X). name([bob |X], X). name([charles |X], X). name([david |X], X). name([eric |X], X). name([francis |X], X). name([george |X], X). name([harry |X], X). name([ignatius|X], X). name([john |X], X). name([katie |X], X). name([larry |X], X). name([michael |X], X). name([nancy |X], X). name([oliver |X], X). `) g := read.Term_(`name([george,the,third], Rest).`) for i := 0; i < b.N; i++ { _ = m.ProveAll(g) } }
func TestPureProlog(t *testing.T) { // find all t/*.pl files file, err := os.Open("t") MaybePanic(err) names, err := file.Readdirnames(-1) useModule := read.Term_(`:- use_module(library(tap)).`) env := term.NewBindings() // run tests found in each file for _, name := range names { if name[0] == '.' { continue // skip hidden files } //t.Logf("-------------- %s", name) openTest := func() *os.File { f, err := os.Open("t/" + name) MaybePanic(err) return f } // which tests does the file have? pastUseModule := false tests := make([]term.Term, 0) terms := read.TermAll_(openTest()) for _, s := range terms { x := s.(term.Callable) if pastUseModule { if x.Arity() == 2 && x.Name() == ":-" { tests = append(tests, x.Arguments()[0]) } else { tests = append(tests, x) } } else { // look for use_module(library(tap)) declaration _, err := s.Unify(env, useModule) if err == nil { pastUseModule = true //t.Logf("found use_module directive") } } } // run each test in this file m := NewMachine().Consult(openTest()) for _, test := range tests { x := test.(term.Callable) //t.Logf("proving: %s", test) canProve := m.CanProve(test) if x.Arity() > 0 && x.Arguments()[0].String() == "fail" { if canProve { t.Errorf("%s: %s should fail", name, test) } } else { if !canProve { t.Errorf("%s: %s failed", name, test) } } } } }
func (m *machine) readTerm(src interface{}) Term { return read.Term_(src) }
func BenchmarkUnificationHash(b *testing.B) { x := read.Term_(`a(b(c(d(e(f(g(h(i(j))))))))).`) for i := 0; i < b.N; i++ { _ = term.UnificationHash([]term.Term{x}, 64, true) } }
func BenchmarkRead(b *testing.B) { for i := 0; i < b.N; i++ { _ = read.Term_(`reverse([1,2,3,4,5,6,7], Xs).`) } }