Prolog-Multiplying a list with a list of lists - list

I'm trying to simulate a product of a matrix with a vector using these two predicates:
eva([], [], []).
eva([A|A1], [W], [Res|R1]) :-
vectormultiplication(A, W, Res),
eva(A1, W, R1).
vectormultiplication([A], [W], [A*W]).
vectormultiplication([A|A1], [W|W1], [A*W|Out1]) :-
vectormultiplication(A1, W1, Out1).
Where the [A|A1] in eva is a matrix (or a list of lists), [W] is a vector (a list),and [Res|R1] is the resulting product. vectormultiplication is supposed to go multiply each list in the list with the vector W. However, this strategy just produces a false response. Is there anything apparent that I'm doing wrong here that prevents me from getting the desired product? I'm currently using SWI Prolog version 5.10

you have 2 other problems apart that evidenced by Daniel (+1): here a cleaned up source
eva([], _, []). % here [] was wrong
eva([A|A1], W, [Res|R1]) :- % here [W] was wrong
vectormultiplication(A, W, Res),
eva(A1, W, R1).
vectormultiplication([A], [W], [M]) :-
M is A*W.
vectormultiplication([A|A1], [W|W1], [M|Out1]) :-
M is A*W,
vectormultiplication(A1, W1, Out1).
test:
?- eva([[1,2],[3,5]],[5,6],R).
R = [[5, 12], [15, 30]]
when handling lists, it's worth to use maplist if available
eva(A, W, R) :-
maplist(vectormultiplication1(W), A, R).
vectormultiplication1(W, A, M) :-
maplist(mult, A, W, M).
mult(A, W, M) :-
M is A*W.
Note I changed the order of arguments of vectormultiplication1, because the vector is a 'constant' in that loop, and maplist append arguments to be 'unrolled'.

Well, your first problem is that you think A*W is going to do anything by itself. In Prolog, that's just going to create the expression A*W, no different from *(A,W) or foo(A, W)--without is/2 involved, no actual arithmetic reduction will take place. That's the only real problem I see in a quick glance.

Related

Prolog - Give out every nth element of a list

I'm working on a Prolog program which should load every nth element of a list into another list. For example:
?- pred([a,b,c,d,e,f,g,h,i,j],3,R) =>
R = [c,f,i]
Where pred is the predicate I'm attempting to implement.
But I honestly don't know how to do it. I know that I need a counter, which represents the current position of my Head, so it's gonna be a /4 predicate summarized into a /3 one later one, like
nth(list,number,result) :- nth(list,number,result,counter) or similiar.
Though, I don't know how to give the head a position number that can reset itself. Because once it hits n (let's say n=3, which is the c in the list), it has to turn back to 1 logically and count again up to 3, give out the element, and so on.
How can I work around these specific problems in my implementation?
An example of how this could be implemented:
nth_pos(L, N, R):-
nth_pos(L, 1, N, [], R).
nth_pos([], I, N, Acc, Acc).
nth_pos([H|T], I, N, Acc, R):-
I =:= N,
append(Acc, [H], Acc2),
I2 is 1,
nth_pos(T, I2, N, Acc2, R).
nth_pos([H|T], I, N, Acc, R):-
I < N,
I2 is I + 1,
nth_pos(T, I2, N, Acc, R).
Test-run:
?- nth_pos([a,b,c,d,e,f,g,h,i,j],3,R).
R = [c, f, i] .
?- nth_pos([a,b,c,d,e,f,g,h,i,j],1,R).
R = [a, b, c, d, e, f, g, h, i|...]
But I honestly don't know how to do it. I know that I need a counter,
which represents the current position of my Head, so it's gonna be a
/4 predicate summarized into a /3 one later one, like
nth(list,number,result) :- nth(list,number,result,counter) or
similiar.
Yes you are on the right track, note that an accumulator is used as well to build up the list so we get pred/5. Hope it helps. Note that this is not the only way to solve it.

Multiplying two lists in prolog

I am currently working with prolog and want to multiply two lists together but in a certian way. For example:
[1,2,3] and [4,5,6] are my two lists.
I want to preform the following actions:
(1*4)+(2*5)+(3*6) = 32
Such that the first element of each list is multiplied to each other then added with the second elements multiplied together etc.
Is this possible to go in Prolog?
I know in other languages you can do a recursive function with takes the head of the list and the tail (the rest of the entries). This allows for a simple multiplication but I do not think that is possible in prolog?
Using built-ins:
mult(X, Y, Z) :- Z is X * Y.
sum_prod(A, B, SumProd) :-
maplist(mult, A, B, Prods),
sumlist(Prods, SumProd). % In GNU Prolog this is sum_list
Using simple recursion:
sum_prod([A|As], [B|Bs], SumProd) :-
sum_prod(As, Bs, SP),
SumProd is SP + A*B.
sum_prod([], [], 0).
Using tail recursion:
sum_prod(A, B, SumProd) :-
sum_prod(A, B, 0, SumProd).
sum_prod([A|As], [B|Bs], Acc, SumProd) :-
Acc1 is Acc + A*B,
sum_prod(As, Bs, Acc1, SumProd).
sum_prod([], [], Acc, Acc).
If all items of your lists are integers and your Prolog implementation offers clpfd, you can simply use the
clpfd built-in predicate scalar_product/4, like this:
?- scalar_product([1,2,3],[4,5,6],#=,Product).
Product = 32.
Edit:
You may also be interested in the related question "Prolog: Multiplying 2 lists with 1 of them not instantiated?", particularly in this answer.
as an alternative to 'hand coded' loops, using library(aggregate) and nth1/3:
sum_prod(A,B,S) :-
aggregate(sum(M), I^X^Y^(nth1(I,A,X), nth1(I,B,Y), M is X*Y), S).

How can i find pairs in a list, Prolog?

I have a problem,
I have a list with numeric elements such as in the example.
I´d like to find all pairs, and count it. (Every Element can only be one part of one pair)
?- num_pairs([4,1,1,1,4],N).
N=1;
Can anyone help me to solve this problem??
You need several things to make it work:
An ability to count the number an item is repeated in a list
An ability to remove all elements matching a value from the list
An ability to conditionally increment a number
Here is how you can count:
count([], _, 0).
count([H|T], H, R) :- count(T, H, RT), R is RT + 1.
count([H|T], X, R) :- H \= X, count(T, X, R).
Deletion can be done with SWI's delete/3 predicate; this is a built predicate.
Adding one conditionally requires two rules - one when the count equals one, and another one for when the count does not equal one.
add_if_count_is_one(H, T, RT, R) :- count(T, H, 1), R is RT + 1.
add_if_count_is_one(H, T, R, R) :- count(T, H, X), X \= 1.
Finally, counting pairs could look like this:
num_pairs([], 0).
num_pairs([H|T], R) :- delete(T, H, TT),
num_pairs(TT, RT),
add_if_count_is_one(H, T, RT, R).
An empty list has no pairs; when an item is counted as part of a pair, its copies are removed from the rest of the list.
Here is this running program on ideone.

Prolog sum all the number in the list.

How to sum all odd positioned elements in a list
example [1,2,3,4,5,6,7,8,9] = 25
odd([],0].
odd([Z],Z).
odd([X,Y|T], Sum+1):- odd(T,Sum).
but it return me 1+3+5+7+9.
In prolog you have to use the is operator when you want to evaluate arithmetic expressions. Since you use the + symbol outside of an arithmetic scope it is not interpreted specially. This appears to be homework, so I'll give a simplified example:
add(A, B, C) :- C is A + B.
The code above adds A and B and stores the result in C.
What you construct when you write Sum+1 is a term with functor '+'/2 and arguments Sum and 1.
In Prolog, when you want to calculate a sum, you need to use the predicate is/2.
In your code, you should also add cuts to remove unnecessary choicepoints, and add X to the rest of the sum, not 1:
odd([],0) :- !.
odd([Z],Z) :- !.
odd([X,_|T],Sum):- odd(T,Sum0), Sum is Sum0+X.
Using an accumulator would allow you to make the code tail-recursive...
Get a list with the odd elements, then sum that list:
divide([], [], []).
divide([H|T], [H|L1], L2) :- divide(T, L2, L1).
sum(L, Sum) :- sum(L, 0, Sum).
sum([], Acu, Acu).
sum([H|T], Acu, Acu1) :-
Acu2 is Acu + H,
sum(T, Acu2, Acu1).
sum_odd(L, Sum) :-
divide(L, Odds, _),
sum(Odds, Sum).
:- sum_odd([1,2,5,6,8,9,1], Sum), writeln(Sum).
sum([],0).
sum([H|T],N) :-
sum(T,M), N is H + M.

Prolog list operation

Here's my problem (by example since that's quicker):
?- enum_list([alpha, beta, gamma, beta, beta, delta, epsilon, alpha], L).
L = [alpha1, beta1, gamma, beta2, beta3, delta, epsilon, alpha2].
The problem is simple when I am allowed to reorder the list (just sort the list, group same elements into lists, enum the lists if they are longer than 1). But I want to keep the order. Any ideas?
How about:
enum_list(L, E):-
enum_list(L, E, [], _).
enum_list([], [], B, B).
enum_list([X|Tail], [Y|NTail], B, NB):-
select(X-C, B, MB),
succ(C, C1),
atom_concat(X, C1, Y),
!,
enum_list(Tail, NTail, [X-C1|MB], NB).
enum_list([X|Tail], [Y|NTail], B, NB):-
enum_list(Tail, NTail, [X-1|B], NB),
(member(X-1, NB) -> Y=X ; atom_concat(X, 1, Y)).
It iterates through the list and keeps a set of count of occurrences of each item so it knows when and what to append for each item to get the name.