Matrix 用Prolog实现矩阵乘法

Matrix 用Prolog实现矩阵乘法,matrix,prolog,Matrix,Prolog,我必须编写一个谓词,即谓词product/3,它接收两个矩阵并返回它们的矩阵乘法(如果可能),否则将失败。(这意味着如果矩阵满足要求[n x p][p x y],则返回与维度的乘法[n x y]) 例如: product(M1, M2, R) ?- product([[1,2],[3,4],[5,6]], [[1,1,1],[1,1,1]], M). M = [[3, 3, 3], [7, 7, 7], [11, 11, 11]]; No 为此,我有两个代码,分别为矩阵

我必须编写一个谓词,即谓词
product/3
,它接收两个矩阵并返回它们的矩阵乘法(如果可能),否则将失败。(这意味着如果矩阵满足要求
[n x p][p x y]
,则返回与维度的乘法
[n x y]

例如:

product(M1, M2, R)
    ?- product([[1,2],[3,4],[5,6]], [[1,1,1],[1,1,1]], M).
    M = [[3, 3, 3], [7, 7, 7], [11, 11, 11]];
    No
为此,我有两个代码,分别为矩阵
rowI
上的第n行和第n列
columnI
编制索引(我在下面的代码中解释了它们是如何工作的)

我不知怎么想,抓住了
M1
(将是每一行)的头,然后在
M2
中为每一列相乘,在添加相乘后,这个列表将成为新行。所以(C必须是一个计数器,从1开始到
M2
的长度,然后
mult
我只是想让它乘以列表。(mult在这一点上没有定义,只是一个猜测)

在这里,我试图解释我的想法。但是可能有一种更简单的方法。你认为呢?

压缩代码(借助于高阶结构maplist和foldl)。 我故意不计算表达式,因此结果可以在更一般的上下文中重用:

:- module(matrix_multiply,
    [matrix_multiply/3
    ,dot_product/3
    ]).
:- use_module(library(clpfd), [transpose/2]).

%%  matrix_multiply(+X,+Y,-M) is det.
%
%   X(N*P),Y(P*M),M(N*M)
%
matrix_multiply(X,Y,M) :-
    transpose(Y,T),
    maplist(row_multiply(T),X,M).

row_multiply(T,X,M) :-
    maplist(dot_product(X),T,M).

dot_product([X|Xs],[T|Ts],M) :-
    foldl(mul,Xs,Ts,X*T,M).
mul(X,T,M,M+X*T).
编辑

用法(保存在名为matrix_multiply.pl的文件中):

数值计算由
、映射列表(映射列表(is)、C、R)
明确请求。 R表示符号表达式,C表示值

编辑

需要注意的是,clpfd:transpose的依赖关系很容易删除:这里有一个基于nth/3和library(yall)的替代“一行”定义

有关
:- module(matrix_multiply,
    [matrix_multiply/3
    ,dot_product/3
    ]).
:- use_module(library(clpfd), [transpose/2]).

%%  matrix_multiply(+X,+Y,-M) is det.
%
%   X(N*P),Y(P*M),M(N*M)
%
matrix_multiply(X,Y,M) :-
    transpose(Y,T),
    maplist(row_multiply(T),X,M).

row_multiply(T,X,M) :-
    maplist(dot_product(X),T,M).

dot_product([X|Xs],[T|Ts],M) :-
    foldl(mul,Xs,Ts,X*T,M).
mul(X,T,M,M+X*T).
?- [matrix_multiply].
?- matrix_multiply([[1,2],[3,4],[5,6]], [[1,1,1],[1,1,1]],R),maplist(maplist(is),C,R).
R = [[1*1+2*1, 1*1+2*1, 1*1+2*1], [3*1+4*1, 3*1+4*1, 3*1+4*1], [5*1+6*1, 5*1+6*1, 5*1+6*1]],
C = [[3, 3, 3], [7, 7, 7], [11, 11, 11]].
mat_transpose([R1|Rs],T) :- findall(V,(
    nth1(Col,R1,_),
    maplist({Col}/[R,C]>>nth1(Col,R,C),[R1|Rs],V)),T).