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
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.
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).
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.
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.
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.