2

I am trying to export the evaluation of the factorial of 500000 to a file, for which I compile the following program:

fact(N, NF) :-
   fact(1, N, 1, NF).

fact(X, X, F, F) :-
   !.
fact(X, N, FX, F) :-
   X1  is X + 1,
   FX1 is FX * X1,
   fact(X1, N, FX1, F).

Next I write:

?- fact(1, 500000, 1, F).

Next:

?- open('Factorial.txt', write, Stream), write(Stream, $F), close(Stream).
ERROR: $F was not bound by a previous query

Accomplishing tests, I verified that only this procedure works even:

?- fact(1, 5772, 1, F).

Why when I try to export the factorial of a bigger number than 5772 I obtain this:

ERROR: $F was not bound by a previous query

How do I solve this problem? I will be grateful for any help you can provide.

false
  • 10,264
  • 13
  • 101
  • 209
  • 3
    Have you tried defining an predicate instead of using the [tag:prolog-toplevel]? The toplevel/shell/interface might hit some limits even though the computation runs just fine... – repeat Oct 29 '17 at 04:21
  • 2
    As @repeat said, the toplevel remebers only 'not too big' terms – CapelliC Oct 29 '17 at 05:39

2 Answers2

4

Option 1: Pipe the output to a file

One of the easiest ways to achieve this requires no modifications at all:

You can invoke SWI-Prolog using the -g option, so that it not only loads the file, but also runs a given Prolog goal. For example, if you store your definition in fact.pl, you can run:

swipl -g 'fact(1,50 000,1,F),portray_clause(F),halt' fact.pl

You can then pipe the program's output into a file, using for example:

swipl -g 'fact(1,50 000,1,F),portray_clause(F),halt' fact.pl > fact.out

Option 2: Run a toplevel query that writes the file

The second option is to simply combine the queries you showed in such a way that they do not rely on specific toplevel features which are not portable in any case:

?- fact(1, 50 000, 1, F),
   open('Factorial.txt', write, Stream),
   write(Stream, F),
   close(Stream).

Correctness of fact/2

Independent of all this, your definition of fact/2 is not correct because it says that there is only a single solution:

?- fact(N, F).
N = F, F = 1.

Try to define this relation in such a way that it gives correct results also for this so-called most general query!

mat
  • 40,498
  • 3
  • 51
  • 78
-3

5772! is approximately 8 x 10^19205, so I am surprised your PROLOG implementation could handle numbers this big, though I am not surprised it choked on 500000!, which is approximately 10^2632341. More likely, your recursion exceeded your maximum PROLOG stack size.

In either case this is not likely to be feasible in PROLOG, so try using the GNU Multiple Precision Arithmetic Library (GMP) in C or C++ and just multiplying instead of recursing.

  • 3
    The code provided is properly tail-recursive, so I do not see how this stack size limited... please elaborate! – repeat Oct 29 '17 at 04:12