2

I need to write a program, which calculates product of product in range: enter image description here

I written the following code:

mult(N,N,R,R).
mult(N,Nt,R,Rt):-N1=Nt+1,R1=Rt*(1/(log(Nt))),mult(N,N1,R,R1).

This should implement basic product from Nt to N of 1/ln(j). As far as I understand it's got to be stopped when Nt and N are equal. However, I can't get it working due to:

?- mult(10,2,R,1), write(R).
ERROR: Out of global stack

The following error. Is there any other way to implement loop not using default libraries of SWI-Prolog?

false
  • 10,264
  • 13
  • 101
  • 209
vladfau
  • 1,003
  • 11
  • 22

2 Answers2

2

Your program never terminates! To see this consider the following failure-slice of your program:

mult(N,N,R,R) :- false.
mult(N,Nt,R,Rt):-
   N1=Nt+1,
   R1=Rt*(1/(log(Nt))),
   mult(N,N1,R,R1), false.

This new program does never terminate, and thus the original program doesn't terminate. To see that this never terminates, consider the two (=)/2 goals. In the first, the new variable N1 is unified with something. This will always succeed. Similarly, the second goal with always succeed. There will never be a possibility for failure prior to the recursive goal. And thus, this program never terminates.

You need to add some goal, or to replace existing goals. in the visible part. Maybe add N > Nt.

Further, it might be a good idea to replace the two (=)/2 goals by (is)/2. But this is not required for termination, strictly speaking.

Community
  • 1
  • 1
false
  • 10,264
  • 13
  • 101
  • 209
  • Isn't it obligatory to use `is` in this case? I thought something like: `a(5).` `a(N):- a(N+1).` a call like `a(0)` would never terminate. Is that wrong? Does `0+1+1+1+1+1` unify with 5? My prolog-foo might be more forgotten that I'd thought – vmg Nov 23 '14 at 18:15
  • 1
    `a(5)` never terminates, it misses again a goal like `N >= 0` or the like. – false Nov 23 '14 at 18:17
  • 1
    Oh ok, I got it now. Starting out-of-bounds for the answer would never terminate. – vmg Nov 23 '14 at 18:20
  • 1
    @vmg: If you claim that your definition terminates, you definitely have still not understood the issue, for your definition might produce an error, but it will never terminate... – false Nov 23 '14 at 18:22
  • Well, I'm mostly never sure but I think it does terminate, even your version terminates if you change the `=` to `is` and define your first clause as `mult(N,N,R,R) :- !, false.` with a cut – vmg Nov 23 '14 at 18:31
  • 1
    @vmg: You are changing now the program. But even in that case (with cut) it does not always terminate! – false Nov 23 '14 at 18:45
  • 1
    Even in that case, `mult(10,2,1,1)` loops without a goal like `N > Nt` suggested above. Cut is not a solution. – false Nov 23 '14 at 18:48
0

Out of global stack means you entered a too-long chain of recursion, possibly an infinite one.

The problem stems from using = instead of is in your assignments.

mult(N,N,R,R).
mult(N,Nt,R,Rt):-N1 is Nt+1, R1 is Rt*(1/(log(Nt))), mult(N,N1,R,R1). 

You might want to insert a cut in your first clause to avoid going on after getting an answer.

If you have a graphical debugger (like the one in SWI) try setting 'trace' and 'debug' on and running. You'll soon realize that performing N1 = Nt+1 giving Ntas 2 yields the term 2+1. Since 2+1+1+1+(...) will never unify with with 10, that's the problem right there.

vmg
  • 4,176
  • 2
  • 20
  • 33
  • 1
    That is definitely not enough, your program loops as well! – false Nov 23 '14 at 18:08
  • Does it? I'm running it and I get R = 0.03694679293917323 as answer. `9 ?- mult(10,2,R,1).` `R = 0.03694679293917323.` – vmg Nov 23 '14 at 18:11
  • 1
    Please try: `?- mult(10,2,R,1), R = 1` which should fail, but it loops with your definition. – false Nov 23 '14 at 18:13
  • Huh, it works here (it correctly fails). Are you running it with the cut in the first clause? – vmg Nov 23 '14 at 18:18
  • 1
    Then you have some other definition! In above, both `(is)/2` goals will never fail, and thus you always have a loop! – false Nov 23 '14 at 18:20