Why this dynamic version of Fibonacci program is incredibly faster then this other? Prolog solutions -


i learning prolog using swi prolog , have doubt followings 2 solutions of fibonacci number calculation program:

the first 1 this:

fib(1,1).    fib(2,1).      fib(n,f) :- n > 2,                   n1 n-1,               fib(n1,f1),                  n2 n-2,                   fib(n2,f2),                  f f1+f2.  

it pretty clear me hw work, simple.

then have second version that, reading code, seems work previous 1 after have calculate fibonacci number of n save in prolog database asserta/2 predicate reuse after.

so example if calculate fibonacci number 10 , 11 when go calculate fibonacci number 12 aspect use result of previous 2 computations.

so code is:

:-dynamic fibdyn/2.  fibdyn(1,1). fibdyn(2,1).  fibdyn(n,f) :- n > 2,                n1 n-1,                fibdyn(n1,f1),                n2 n-2,                fibdyn(n2,f2),                f f1+f2,                asserta(fibdyn(n,f)). 

it seems me logic same of previous one:

f fibonacci number of n if n>2 , use recursion calculate fibonacci number of n (as in preious example)

i expect program faster if ask calculate number of fibonacci number number have calculated , put database fibonacci numbers of predecessors (or of them) seems me work in strange way: fast , able directly calculate numbers of fibonacci large integers (the other version goes wrong such large numbers)

the other strange thing if trace of query obtain this:

[trace]  ?- fibdyn(200,fib).    call: (6) fibdyn(200, _g1158) ? creep    exit: (6) fibdyn(200, 280571172992510140037611932413038677189525) ? creep fib = 280571172992510140037611932413038677189525 . 

as can see seems don't execute code of fibonacci predicate directly obtain result (from where?!?!)

instad if execute query (using first version), obtain program calculate it:

[trace]  ?- fib(3,fib).    call: (6) fib(3, _g1158) ? creep ^  call: (7) 3>2 ? creep ^  exit: (7) 3>2 ? creep ^  call: (7) _g1233 3+ -1 ? creep ^  exit: (7) 2 3+ -1 ? creep    call: (7) fib(2, _g1231) ? creep    exit: (7) fib(2, 1) ? creep ^  call: (7) _g1236 3+ -2 ? creep ^  exit: (7) 1 3+ -2 ? creep    call: (7) fib(1, _g1234) ? creep    exit: (7) fib(1, 1) ? creep ^  call: (7) _g1158 1+1 ? creep ^  exit: (7) 2 1+1 ? creep    exit: (6) fib(3, 2) ? creep fib = 2 . 

why? expect second version (the 1 use asserta predicate) calculate fibonacci number 2 number , use these value generate solution of following one.

for example have following situation: i have never yet calculate fibonacci number , ask calculate fibonacci number of n=4 calculate (as in second posted stacktrace).

so ask calculate fibonacci number of n=5 , use fibonacci of n=4 saved. ask calculate fibonacci number of n=6 , use saved fibonacci number of 4 , of 5

what missing? can me understand?

tl;dr: use retractall erase asserted facts memory.

change definition

:- dynamic fibdyn/2. :- retractall( fibdyn(_,_) ).  %% without this, you'll retain previous                                 %% facts if reload program fibdyn(1,1). fibdyn(2,1).  fibdyn(n,f) :- n > 2,                n1 n-1,                fibdyn(n1,f1),                n2 n-2,                fibdyn(n2,f2),                f f1+f2,                asserta( (fibdyn(n,f):-!) ). 

notice cut inside asserted rule. notice the retractall statement. without it, asserted facts remain in memory if reload program. that's probably reason why getting results immediately.

after you've run e.g. ?- fibdyn(10,x) once, can see asserted facts in database:

12 ?- listing(fibdyn). :- dynamic fibdyn/2.  fibdyn(10, 55) :- !. fibdyn(9, 34) :- !. fibdyn(8, 21) :- !. fibdyn(7, 13) :- !. fibdyn(6, 8) :- !. fibdyn(5, 5) :- !. fibdyn(4, 3) :- !. fibdyn(3, 2) :- !. fibdyn(1, 1). fibdyn(2, 1). fibdyn(a, d) :-         a>2,         b a+ -1,         fibdyn(b, e),         c a+ -2,         fibdyn(c, f),         d e+f,         asserta((fibdyn(a, d):-!)).  true. 

that why runs fast. difference in speed you're seeing the difference between exponential , linear time complexity algorithm.

next time call it, has access calculated results:

[trace] 15 ?- fibdyn(10,x).    call: (6) fibdyn(10, _g1068) ? creep    exit: (6) fibdyn(10, 55) ? creep x = 55.  [trace] 16 ?-  

this explains fibdyn(200,x) call trace output. you've tried after you've calculated once or twice before.

here's happens when next request 11th number:

[trace] 35 ?- fibdyn(11,x).    call: (6) fibdyn(11, _g1068) ? creep    call: (7) 11>2 ? creep    exit: (7) 11>2 ? creep    call: (7) _g1143 11+ -1 ? creep    exit: (7) 10 11+ -1 ? creep    call: (7) fibdyn(10, _g1144) ? creep    exit: (7) fibdyn(10, 55) ? creep    call: (7) _g1146 11+ -2 ? creep    exit: (7) 9 11+ -2 ? creep    call: (7) fibdyn(9, _g1147) ? creep    exit: (7) fibdyn(9, 34) ? creep    call: (7) _g1068 55+34 ? creep    exit: (7) 89 55+34 ? creep ^  call: (7) asserta((fibdyn(11, 89):-!)) ? creep ^  exit: (7) asserta((fibdyn(11, 89):-!)) ? creep    exit: (6) fibdyn(11, 89) ? creep x = 89.  [trace] 36 ?-  

and again:

[trace] 36 ?- fibdyn(11,x).    call: (6) fibdyn(11, _g1068) ? creep    exit: (6) fibdyn(11, 89) ? creep x = 89. 

Comments

Popular posts from this blog

php - Why I am getting the Error "Commands out of sync; you can't run this command now" -

linux - Does gcc have any options to add version info in ELF binary file? -

java - Are there any classes that implement javax.persistence.Parameter<T>? -