Question

I have two predicates in Prolog, the first one does return a correct dot product of two lists(vectors w/e) ... the second is when you take a list times a list of lists(matrix) which will return a list. The second one fails when I try to pass anything such as ([1,2],[[3,4],[5,6],[7,8]], X). Anyone well versed in Prolog see my mistake? I am kinda stuck since tracing and prolog itself just returns a fail all the time.

getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
    getDotProd(T1,T2,N1),
    N is N1 + (H1 * H2).



vecTimesMatrix(_,[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    N is getDotProd(List, MH, _),
    vecTimesMatrix(List, Mtail, N).

Updated Code thus far now:

getDotProd([],[],0.0).
getDotProd([H1|T1],[H2|T2], N):-
    getDotProd(T1,T2,N1),
    N is N1 + (H1 * H2).



vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    getDotProd(List, MH, N),
    vecTimesMatrix(List, Mtail, N).
Was it helpful?

Solution

Your remaining problem is in your vecTimesMatrix predicate:

vecTimesMatrix([],[[]],[]).
vecTimesMatrix([List], [MH|Mtail],[N]):-
    getDotProd(List, MH, N),
    vecTimesMatrix(List, Mtail, N).

Issues:

  1. In the second clause, the first argument is given as [List] which would imply a list of a single element (List). Subsequent calls to getDotProd and vecTimesMatrix in the clause indicate that this should simply be List.
  2. In the second clause, the third argument is shown simply as a list of one argument: [N]. So the third argument never "builds" a list. Additionally, the recursive call to vecTimesMatrix has N as its third argument, and that argument had already been instantiated by the prior query to getDotProd as the dot product of the vector List and the vectory MH. Logically, the recursive call should be saying that the vector product of List with Mtail is the tail of the final product.
  3. The base case assumes that the first argument reduces to [], but this is not so. List always remains as-is throughout the recursive process. So instead of [] you should have _ (it will keep its value, but you don't care about it in the base case).
  4. The base case has as a second argument [[]], but that's not the correct form for an empty list. That's actually a list consisting of one element, that element being the empty list. In reality, even though the second argument is a "list of lists", the empty list is still [].

Putting it all together (and renaming predicates per de facto conventions using underscores rather than camel case):

get_dot_prod([], [], 0.0).            % Dot product of empty vectors is 0.0
                                      %   (Dot prod of vectors of unequal length
                                      %   is not defined and will fail)
get_dot_prod([H1|T1], [H2|T2], N) :-  % N is dot product of [H1|T1] [H2|T2] if...
    get_dot_prod(T1, T2, N1),         % N1 is dot product of T1 T2, and
    N is N1 + (H1 * H2).              % N is N1 + (H1*H2) [evaluated]

vec_times_matrix(_, [], []).          % Product of any vector with
                                      %   empty matrix is empty
vec_times_matrix(List, [MH|Mtail], [N|Ntail]):-
                                      % [N|Ntail] is List x [MH|Mtail] if...
    get_dot_prod(List, MH, N),        % N is dot product of List and MH, and
    vec_times_matrix(List, Mtail, Ntail). % Ntail is List x Mtail

This will yield:

| ?- vec_times_matrix([1,2],[[1,0],[0,1]], M).

M = [1.0,2.0] ? a

no
| ?- vec_times_matrix([1,2],[[1,0],[0,1],[1,1]], M).

M = [1.0,2.0,3.0] ? a

(1 ms) no

I added the comments in the code above to illustrate, in a simple way, how to think of the prolog predicate logic, which aids in defining them. As was pointed out already, the prolog "predicate" doesn't act as a "function". It describes a logical relation between entities which will either succeed or fail.

Once you learn to think how prolog thinks (relationally), you'll find it more enjoyable. :)

OTHER TIPS

There are several problems in your code. First, you define both getDotProd/4 and getDotProd/3 predicates. The first one is a typo. I.e. you base case for the getDotProd/3 predicate have a duplicated argument and it should be:

getDotProd([], [], 0).

Second, in the second predicate, vecTimesMatrix/3, you have a goal, a call to the built-in predicate is/2, that will cause an exception:

N is getDotProd(List, MH, _)

You cannot define your own functions on standard Prolog. You need to replace that goal with:

getDotProd(List, MH, N)

There are other problems but this should help you progress.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top