Dot product Prolog/3 need Hint for the SUM - list

Good Day I am doing the problema of arithmetic in prolog and Yes its the dot Product I have Searched and found a mess of code that did not equal to what the book is asking me. Its a /3 so this is what i have so far but i need to sum the result of the product of both list. Any hint on what should be recommended to do?
dot([HD|TL],[HD2|TL2],Result):-
Mul is HD2 * HD,
dot(TL,TL2,Mul),
Result is Mul + Reuslt2.
dot([],[],0).

Your problems are that you're using Mul twice where you mean to use it once, and Reuslt2 doesn't exist anywhere. Probably what you mean is:
dot([], [], 0).
dot([H1|T1], [H2|T2], Result) :-
Prod is H1 * H2,
dot(T1, T2, Remaining),
Result is Prod + Remaining.

You use SWI-Prolog, so you can try :
:- use_module(library(lambda)).
my_dot(L1,L2,R) :-
foldl(\X^Y^Z^T^(T is X*Y + Z), L1,L2,0,R).

Related

How to simplify algebra equations represented as list of list

With Prolog I want to simplify algebra expression represented as as list of list:
algebra equation
f = 3x+2
list of list
[[3,1],[2,0]]
3 and 2 are coefficients
1 and 0 are exponents
That should be obvious.
I am looking for some tips or suggestions on how to code the simplifications for this example:
f = 3x+2x+1+2
[[3,1],[2,1],[1,0],[2,0]]
simplified:
f = 5x+3
[[5,1],[3,0]]
I have tried some built in functions but did not get the proper idea about how to use them.
One liner, similar to what's proposed by joel76:
simplify(I,O) :-
bagof([S,E],L^(bagof(C,member([C,E],I),L),sum_list(L,S)),O).
The inner bagof collects C (coefficients) given E (exponents), the resulting list L is summed into S, and paired with E becomes [S,E], an element (monomial) of O.
If you omit the universal quantification specifier (that is L^) you get single monomials on backtracking.
You can solve your problem in this way:
simplify(_,_,S,S,[]):- !.
simplify(L,I,Sum,NTot,[[I,S]|T]):-
Sum =< NTot,
findall(X,member([X,I],L),LO),
length(LO,N),
S1 is Sum + N,
sum_list(LO,S),
I1 is I+1,
simplify(L,I1,S1,NTot,T).
write_function([]).
write_function([[D,V]|T]):-
write(' + '),write(V),write('x^'),write(D),
write_function(T).
test:-
L = [[3,1],[2,1],[1,0],[2,0]],
length(L,N),
simplify(L,0,0,N,LO),
LO = [[D,V]|T],
write('f='),write(V),write('x^'),write(D),
write_function(T).
The main predicate is simplify/5 which uses findall/3 to find all the coefficients with the same degree and then sums them using sum_list/2. Then you can write the result in a fancy way using write_function/1.
In SWI-Prolog You can use aggregate :
pred(>, [_,X], [_,Y]) :- X > Y.
pred(<, [_,X], [_,Y]) :- X < Y.
pred(=, [_,X], [_,X]).
simplify(In, Out) :-
aggregate(set([S,X]), aggregate(sum(P), member([P,X], In), S), Temp),
predsort(pred, Temp, Out).
For example :
?- simplify([[3,1],[2,1],[1,0],[2,0]], Out).
Out = [[5, 1], [3, 0]] ;
false.

Calculate Area Tangent Circumferences - Prolog

I have the following function that calculates an area.
It receives three parameters, the first is an n representing the number of cases, the 2nd representing the radio of circumferences, and the 3rd is l giving me back the result.
The problem I have is that when the 1st input is greater than 1 it does not work.
This my code:
as(1, [X], A) :-
A is (sqrt(3.0) * (X*X)) - (3.14 * (X*X))/2.
as(N, [H|_T], A) :-
A is (sqrt(3.0) * (H*H)) - (3.14 * (H*H))/2,
N1 is N-1,
as(N1-1, T, A).
An example of how it should work is:
?- as(4, [1,1,1,1], R).
R = 0.162050807568877130000 ;
R = 0.162050807568877130000 ;
R = 0.162050807568877130000 ;
R = 0.162050807568877130000.
If you could help me, I would be grateful ...
Is there a reason this version isn't sufficient to your needs?
as([H|_], A):-
A is (sqrt(3.0) * (H*H)) - (3.14 * (H*H))/2.
as([_|T], A) :- as(T, A).
Or maybe this?
area(H, Area) :-
Area is (sqrt(3.0) * (H*H)) - (3.14 * (H*H))/2.
as(List, Area) :- member(Ratio, List), area(Ratio, Area).
I don't understand why you need to worry about N at all.
Matching both N and [X] leads to redundancy. You shouldn't have to repeat your formula.
You have a lot of singleton errors: _T in the head, and then T in the body which will not work.
You are passing N1-1 to the recursive call, which will not cause it to be evaluated—but you already evaluated N-1 in the previous expression, so just pass N1 here. Again, I don't see the point of this at all.
I think it's a good idea to use succ(N1, N) instead of adding or subtracting one, because it works in both directions (not relevant here, of course).
It feels a bit icky to be combining the list traversal with the calculation to me. I would in general break things down so that the calculation is separate from the data structure insofar as that can be done. This is a universal maxim of programming.
Since you want to compute the area for every measurement anyway, would it not be opportune to get a list of areas corresponding to the list of radio measurements? The structure of your predicate as/3 seems to indicate that you were thinking along those lines. And you could easily achieve that by using maplist/3:
:- use_module(library(apply)). % needed for maplist
% a single measurement and the corresponding area
area(X, A) :-
A is (sqrt(3.0) * (X*X)) - (3.14 * (X*X))/2.
areas(Xs,As) :-
maplist(area,Xs,As). % area/2 mapped to Xs results in As
Querying this predicate yields the desired results but in a list:
?- areas([1,1,5,3],As).
As = [0.16205080756887713, 0.16205080756887713, 4.051270189221931, 1.4584572681198935].

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

Prolog-Multiplying a list with a list of lists

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.

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.