3

New to prolog.

edit: using swi-prolog

I want to recursively do what the multiplication method already does in prolog without actually using the multiplication method.

The algorithm I want to implement it looks something like:

    multn(N1, N2, output){
    if (n2 <=0) return output;
    else
        multn(N1, (N2-1), output + N1)
    }

Ex: 4*4 = 4+4+4+4 = 16

edit*: only passing in positive numbers for this algo.

my knowledge db looks like:

    multn(Num1, 0, Result) :- Result is 0.

    multn(Num1, Num2, Result) :- 
        NewNum2 = Num2 - 1, 
        multn(Num1, NewNum2, NewResult),
        Result is Num1 + NewResult.

However, when I call:

    ?- multn(2,2,R).

It goes on forever, why is this not stopping at the above base case?

Help is much appreciated.

mat
  • 40,498
  • 3
  • 51
  • 78
John
  • 31
  • 3
  • 1
    As a beginner, start with [tag:successor-arithmetics]. Then switch to `library(clpfd)`. Recommended book: Art of Prolog – false May 04 '16 at 03:34
  • Ive been reading through successor-arithmetics and clpfd and am still struggling to grasp it, if you could offer any insight into solving just this specific problem, I would really appreciate it. – John May 04 '16 at 05:16
  • 1
    Please read above tag! The very first/popular question is exactly about this! – false May 04 '16 at 08:39
  • what's the reason you haven't written `NewNum2 is Num2 - 1` ? – CapelliC May 04 '16 at 08:42
  • Still new to prolog, that fixed it, what exactly is the difference between = and is? Doesn't = mean bind? similar to another language like java? – John May 04 '16 at 09:17
  • we can use **!** in `multn(_, 0, 0):- !.` to stop rebuild other results ? – Ans Piter May 04 '16 at 09:33
  • 2
    Using `!/0` destroys relational properties of this predicate: Always also try the most general query, in this case: `?- multn(X, Y, Z).`. I agree with what @false said. For the case of multplication, I recommend to start with CLP(FD) constraints right away, since `s/1` terms quickly become quite hard to use. – mat May 04 '16 at 09:43
  • `is/2` *evaluates arithmetic expressions* and unifies the first argument with the evaluation of the expression given in the second argument. Quite different. `=/2` is the *unification* operation. It attempts to unify the first and second arguments as Prolog terms. – lurker May 04 '16 at 11:16

1 Answers1

3

For integer arithmetic, use constraints. All serious Prolog systems provide them. For example, for SICStus Prolog, put :- use_module(library(clpfd)) in your initialisation file to make CLP(FD) constraints available in all your programs.

Using CLP(FD) constraints and some small modifications, your initial program becomes:

int_int_prod(_, 0, 0).
int_int_prod(Num1, Num2, Result) :- 
        NewNum2 #= Num2 - 1, 
        int_int_prod(Num1, NewNum2, NewResult),
        Result #= Num1 + NewResult.

And now the point: You obviously meant your clauses to be mutually exclusive.

Insert Num2 #> 0 at an appropriate place to do that!

false
  • 10,264
  • 13
  • 101
  • 209
mat
  • 40,498
  • 3
  • 51
  • 78
  • if we add `Num2 #> 0` in the appropriate place, which is suitable for these conditions : `Num2 #> 0 -> ` or `Num2 #> 0 ,` – Ans Piter May 04 '16 at 10:10
  • 1
    `(->)/2` almost always leads to declarative problems: It can only be safely used if its argument is ground; otherwise, you risk losing solutions by committing prematurely. In this case, simply add `Num #> 0` as one of the goals: It is a necessary condition for this clause to apply. – mat May 05 '16 at 08:31