矩阵乘法序言 [英] Matrix Multiplication Prolog

查看:55
本文介绍了矩阵乘法序言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网上找到了这段代码,用于 Prolog 中的矩阵乘法,任何有Prolog经验的人都可以向我解释吗?

I found this code online for matrix multiplication in Prolog, can anyone who has experience in Prolog to explain it to me?

% SWI-Prolog has transpose/2 in its clpfd library
:- use_module(library(clpfd)).

% N is the dot product of lists V1 and V2.
dot(V1, V2, N) :- maplist(product,V1,V2,P), sumlist(P,N).

product(N1,N2,N3) :- N3 is N1*N2.

% Matrix multiplication with matrices represented
% as lists of lists. M3 is the product of M1 and M2
mmult(M1, M2, M3) :- transpose(M2,MT), maplist(mm_helper(MT), M1, M3).

mm_helper(M2, I1, M3) :- maplist(dot(I1), M2, M3).

推荐答案


% 开头的行是注释

大多数编程语言都有方法和函数.Prolog 具有谓词,可以成功或失败,并且可以在变量中传递值.

Most programming langues have methods and functions. Prolog has predicates which succeed or fail and can pass values along in variables.

谓词由它们的名称和元数表示,transpose/2.

Predicates are denoted by their name and arity as such, transpose/2.

大多数编程语言使用赋值,但 Prolog 使用统一.对于求解数学表达式的特殊情况,Prolog 有 is/2

Most programming languages use assignment, but Prolog uses unification. For the special case of solving math expressions Prolog has is/2

:- use_module(library(clpfd)).

是一个指令 :- 引入了一个名为 clpfd.clpfd 通常用于约束,但在这种情况下用于访问 transpose/2 谓词.

Is a directive :- that brings in a library named clpfd. clpfd is used for constraints normally but in this case is used to access the transpose/2 predicate.

dot(V1, V2, N) :- 
    maplist(product,V1,V2,P), 
    sumlist(P,N).

dot/3 是一个接受两个向量的谓词,我猜实现为 Prolog list 在这种情况下,并绑定 点积N.
maplist/4 将 product/3 谓词应用于 V1V2 创建列表 P.
sumlist/2P 并绑定 N.

dot/3 is a predicate that takes in two vectors, I am guessing implemented as Prolog list in this case, and binds the dot product as N.
maplist/4 applies the product/3 predicate to the values in V1 and V2 to create the list P.
sumlist/2 adds up the list of values in P and binds N.

product(N1,N2,N3) :- N3 is N1*N2.

product/3 是一个辅助谓词,用于取两个数字 N1N2 并将它们相乘.

product/3 is a helper predicate to take two numbers N1 and N2 and multiply them.

N3 is N1*N2 可以认为是 N3 = (N1 * N2)

mmult(M1, M2, M3) :- 
    transpose(M2,MT), 
    maplist(mm_helper(MT), M1, M3).

transpose/2 是典型的数组转置.
maplist/3 应用辅助谓词 mm_helper/3 使用 MTM1 绑定 M3.

transpose/2 is the typical array transpose.
maplist/3 applies the helper predicate mm_helper/3 using MT and M1 to bind M3.

mm_helper(M2, I1, M3) :- 
    maplist(dot(I1), M2, M3).

maplist/3dot/3应用于I1M2绑定M3.

我认为您从 RosettaCode 中获取了代码,或者它与此类交叉.

I take it you took the code from RosettaCode or it crossed paths with such.

示例运行:

?- mmult([[1,2],[3,4]],[[5,6],[7,8]],R).
R = [[19, 22], [43, 50]] ;
true.

验证示例.

来自评论.

I1 在 mm_helper 谓词中代表什么?

What does I1 represents in mm_helper predicate?

详情见下方轨迹

mm_helper/3 的签名是 mm_helper(M2, I1, M3) 所以第二个参数包含 I1.从跟踪中的行

The signature of mm_helper/3 is mm_helper(M2, I1, M3) so the second parameter contains I1. From the lines in the trace

Exit: (11) mm_helper([[5, 7], [6, 8]], [3, 4], [43, 50])

第二个参数是[3,4].

Call: (10) mm_helper([[5, 7], [6, 8]], [1, 2], _3596)

第二个参数是[1,2].

所以 I2 是第一个矩阵的行切片.

So I2 is a row slice of the first matrix.

小心你的要求,你可能会得到比预期更多的东西?:)

Be careful of what you ask for, you might get more than expected? :)

完整的运行轨迹:

这只是因为评论中有一个问题.

This is only here because of a question in the comment.

[trace]  ?- mmult([[1,2],[3,4]],[[5,6],[7,8]],R).


   Call: (8) mmult([[1, 2], [3, 4]], [[5, 6], [7, 8]], _3238)
   Unify: (8) mmult([[1, 2], [3, 4]], [[5, 6], [7, 8]], _3238)
   Call: (9) clpfd:transpose([[5, 6], [7, 8]], _3536)
   Unify: (9) clpfd:transpose([[5, 6], [7, 8]], _3536)
   Call: (10) error:must_be(list(list), [[5, 6], [7, 8]])
   Unify: (10) error:must_be(list(list), [[5, 6], [7, 8]])
   Exit: (10) error:must_be(list(list), [[5, 6], [7, 8]])
   Call: (10) clpfd:lists_transpose([[5, 6], [7, 8]], _3540)
   Unify: (10) clpfd:lists_transpose([[5, 6], [7, 8]], _3540)
   Call: (11) clpfd:'__aux_maplist/2_same_length+1'([[7, 8]], [5, 6])
   Unify: (11) clpfd:'__aux_maplist/2_same_length+1'([[7, 8]], [5, 6])
   Call: (12) lists:same_length([5, 6], [7, 8])
   Unify: (12) lists:same_length([5, 6], [7, 8])
   Exit: (12) lists:same_length([5, 6], [7, 8])
   Call: (12) clpfd:'__aux_maplist/2_same_length+1'([], [5, 6])
   Unify: (12) clpfd:'__aux_maplist/2_same_length+1'([], [5, 6])
   Exit: (12) clpfd:'__aux_maplist/2_same_length+1'([], [5, 6])
   Exit: (11) clpfd:'__aux_maplist/2_same_length+1'([[7, 8]], [5, 6])
^  Call: (11) apply:foldl(transpose_, [5, 6], _3548, [[5, 6], [7, 8]], _3552)
^  Unify: (11) apply:foldl(clpfd:transpose_, [5, 6], _3554, [[5, 6], [7, 8]], _3558)
   Call: (12) apply:foldl_([5, 6], _3552, clpfd:transpose_, [[5, 6], [7, 8]], _3558)
   Unify: (12) apply:foldl_([5, 6], [_3536|_3538], clpfd:transpose_, [[5, 6], [7, 8]], _3564)
   Call: (13) clpfd:transpose_(5, _3536, [[5, 6], [7, 8]], _3562)
   Unify: (13) clpfd:transpose_(5, _3536, [[5, 6], [7, 8]], _3562)
   Call: (14) clpfd:'__aux_maplist/4_list_first_rest+0'([[5, 6], [7, 8]], _3536, _3560)
   Unify: (14) clpfd:'__aux_maplist/4_list_first_rest+0'([[5, 6], [7, 8]], [_3542|_3544], [_3548|_3550])
   Call: (15) clpfd:list_first_rest([5, 6], _3542, _3548)
   Unify: (15) clpfd:list_first_rest([5, 6], 5, [6])
   Exit: (15) clpfd:list_first_rest([5, 6], 5, [6])
   Call: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[7, 8]], _3544, _3550)
   Unify: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[7, 8]], [_3554|_3556], [_3560|_3562])
   Call: (16) clpfd:list_first_rest([7, 8], _3554, _3560)
   Unify: (16) clpfd:list_first_rest([7, 8], 7, [8])
   Exit: (16) clpfd:list_first_rest([7, 8], 7, [8])
   Call: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([], _3556, _3562)
   Unify: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([], [], [])
   Exit: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([], [], [])
   Exit: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[7, 8]], [7], [[8]])
   Exit: (14) clpfd:'__aux_maplist/4_list_first_rest+0'([[5, 6], [7, 8]], [5, 7], [[6], [8]])
   Exit: (13) clpfd:transpose_(5, [5, 7], [[5, 6], [7, 8]], [[6], [8]])
   Call: (13) apply:foldl_([6], _3538, clpfd:transpose_, [[6], [8]], _3588)
   Unify: (13) apply:foldl_([6], [_3566|_3568], clpfd:transpose_, [[6], [8]], _3594)
   Call: (14) clpfd:transpose_(6, _3566, [[6], [8]], _3592)
   Unify: (14) clpfd:transpose_(6, _3566, [[6], [8]], _3592)
   Call: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[6], [8]], _3566, _3590)
   Unify: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[6], [8]], [_3572|_3574], [_3578|_3580])
   Call: (16) clpfd:list_first_rest([6], _3572, _3578)
   Unify: (16) clpfd:list_first_rest([6], 6, [])
   Exit: (16) clpfd:list_first_rest([6], 6, [])
   Call: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([[8]], _3574, _3580)
   Unify: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([[8]], [_3584|_3586], [_3590|_3592])
   Call: (17) clpfd:list_first_rest([8], _3584, _3590)
   Unify: (17) clpfd:list_first_rest([8], 8, [])
   Exit: (17) clpfd:list_first_rest([8], 8, [])
   Call: (17) clpfd:'__aux_maplist/4_list_first_rest+0'([], _3586, _3592)
   Unify: (17) clpfd:'__aux_maplist/4_list_first_rest+0'([], [], [])
   Exit: (17) clpfd:'__aux_maplist/4_list_first_rest+0'([], [], [])
   Exit: (16) clpfd:'__aux_maplist/4_list_first_rest+0'([[8]], [8], [[]])
   Exit: (15) clpfd:'__aux_maplist/4_list_first_rest+0'([[6], [8]], [6, 8], [[], []])
   Exit: (14) clpfd:transpose_(6, [6, 8], [[6], [8]], [[], []])
   Call: (14) apply:foldl_([], _3568, clpfd:transpose_, [[], []], _3618)
   Unify: (14) apply:foldl_([], [], clpfd:transpose_, [[], []], [[], []])
   Exit: (14) apply:foldl_([], [], clpfd:transpose_, [[], []], [[], []])
   Exit: (13) apply:foldl_([6], [[6, 8]], clpfd:transpose_, [[6], [8]], [[], []])
   Exit: (12) apply:foldl_([5, 6], [[5, 7], [6, 8]], clpfd:transpose_, [[5, 6], [7, 8]], [[], []])
^  Exit: (11) apply:foldl(clpfd:transpose_, [5, 6], [[5, 7], [6, 8]], [[5, 6], [7, 8]], [[], []])
   Exit: (10) clpfd:lists_transpose([[5, 6], [7, 8]], [[5, 7], [6, 8]])
   Exit: (9) clpfd:transpose([[5, 6], [7, 8]], [[5, 7], [6, 8]])
   Call: (9) '__aux_maplist/3_mm_helper+1'([[1, 2], [3, 4]], _3238, [[5, 7], [6, 8]])
   Unify: (9) '__aux_maplist/3_mm_helper+1'([[1, 2], [3, 4]], [_3596|_3598], [[5, 7], [6, 8]])
   Call: (10) mm_helper([[5, 7], [6, 8]], [1, 2], _3596)
   Unify: (10) mm_helper([[5, 7], [6, 8]], [1, 2], _3596)
   Call: (11) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], _3596, [1, 2])
   Unify: (11) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], [_3602|_3604], [1, 2])
   Call: (12) dot([1, 2], [5, 7], _3602)
   Unify: (12) dot([1, 2], [5, 7], _3602)
   Call: (13) '__aux_maplist/4_product+0'([1, 2], [5, 7], _3626)
   Unify: (13) '__aux_maplist/4_product+0'([1, 2], [5, 7], [_3608|_3610])
   Call: (14) product(1, 5, _3608)
   Unify: (14) product(1, 5, _3608)
   Call: (15) _3608 is 1*5
   Exit: (15) 5 is 1*5
   Exit: (14) product(1, 5, 5)
   Call: (14) '__aux_maplist/4_product+0'([2], [7], _3610)
   Unify: (14) '__aux_maplist/4_product+0'([2], [7], [_3620|_3622])
   Call: (15) product(2, 7, _3620)
   Unify: (15) product(2, 7, _3620)
   Call: (16) _3620 is 2*7
   Exit: (16) 14 is 2*7
   Exit: (15) product(2, 7, 14)
   Call: (15) '__aux_maplist/4_product+0'([], [], _3622)
   Unify: (15) '__aux_maplist/4_product+0'([], [], [])
   Exit: (15) '__aux_maplist/4_product+0'([], [], [])
   Exit: (14) '__aux_maplist/4_product+0'([2], [7], [14])
   Exit: (13) '__aux_maplist/4_product+0'([1, 2], [5, 7], [5, 14])
   Call: (13) backward_compatibility:sumlist([5, 14], _3602)
   Unify: (13) backward_compatibility:sumlist([5, 14], _3602)
   Call: (14) lists:sum_list([5, 14], _3602)
   Unify: (14) lists:sum_list([5, 14], _3602)
   Exit: (14) lists:sum_list([5, 14], 19)
   Exit: (13) backward_compatibility:sumlist([5, 14], 19)
   Exit: (12) dot([1, 2], [5, 7], 19)
   Call: (12) '__aux_maplist/3_dot+1'([[6, 8]], _3604, [1, 2])
   Unify: (12) '__aux_maplist/3_dot+1'([[6, 8]], [_3644|_3646], [1, 2])
   Call: (13) dot([1, 2], [6, 8], _3644)
   Unify: (13) dot([1, 2], [6, 8], _3644)
   Call: (14) '__aux_maplist/4_product+0'([1, 2], [6, 8], _3668)
   Unify: (14) '__aux_maplist/4_product+0'([1, 2], [6, 8], [_3650|_3652])
   Call: (15) product(1, 6, _3650)
   Unify: (15) product(1, 6, _3650)
   Call: (16) _3650 is 1*6
   Exit: (16) 6 is 1*6
   Exit: (15) product(1, 6, 6)
   Call: (15) '__aux_maplist/4_product+0'([2], [8], _3652)
   Unify: (15) '__aux_maplist/4_product+0'([2], [8], [_3662|_3664])
   Call: (16) product(2, 8, _3662)
   Unify: (16) product(2, 8, _3662)
   Call: (17) _3662 is 2*8
   Exit: (17) 16 is 2*8
   Exit: (16) product(2, 8, 16)
   Call: (16) '__aux_maplist/4_product+0'([], [], _3664)
   Unify: (16) '__aux_maplist/4_product+0'([], [], [])
   Exit: (16) '__aux_maplist/4_product+0'([], [], [])
   Exit: (15) '__aux_maplist/4_product+0'([2], [8], [16])
   Exit: (14) '__aux_maplist/4_product+0'([1, 2], [6, 8], [6, 16])
   Call: (14) backward_compatibility:sumlist([6, 16], _3644)
   Unify: (14) backward_compatibility:sumlist([6, 16], _3644)
   Call: (15) lists:sum_list([6, 16], _3644)
   Unify: (15) lists:sum_list([6, 16], _3644)
   Exit: (15) lists:sum_list([6, 16], 22)
   Exit: (14) backward_compatibility:sumlist([6, 16], 22)
   Exit: (13) dot([1, 2], [6, 8], 22)
   Call: (13) '__aux_maplist/3_dot+1'([], _3646, [1, 2])
   Unify: (13) '__aux_maplist/3_dot+1'([], [], [1, 2])
   Exit: (13) '__aux_maplist/3_dot+1'([], [], [1, 2])
   Exit: (12) '__aux_maplist/3_dot+1'([[6, 8]], [22], [1, 2])
   Exit: (11) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], [19, 22], [1, 2])
   Exit: (10) mm_helper([[5, 7], [6, 8]], [1, 2], [19, 22])
   Call: (10) '__aux_maplist/3_mm_helper+1'([[3, 4]], _3598, [[5, 7], [6, 8]])
   Unify: (10) '__aux_maplist/3_mm_helper+1'([[3, 4]], [_3686|_3688], [[5, 7], [6, 8]])
   Call: (11) mm_helper([[5, 7], [6, 8]], [3, 4], _3686)
   Unify: (11) mm_helper([[5, 7], [6, 8]], [3, 4], _3686)
   Call: (12) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], _3686, [3, 4])
   Unify: (12) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], [_3692|_3694], [3, 4])
   Call: (13) dot([3, 4], [5, 7], _3692)
   Unify: (13) dot([3, 4], [5, 7], _3692)
   Call: (14) '__aux_maplist/4_product+0'([3, 4], [5, 7], _3716)
   Unify: (14) '__aux_maplist/4_product+0'([3, 4], [5, 7], [_3698|_3700])
   Call: (15) product(3, 5, _3698)
   Unify: (15) product(3, 5, _3698)
   Call: (16) _3698 is 3*5
   Exit: (16) 15 is 3*5
   Exit: (15) product(3, 5, 15)
   Call: (15) '__aux_maplist/4_product+0'([4], [7], _3700)
   Unify: (15) '__aux_maplist/4_product+0'([4], [7], [_3710|_3712])
   Call: (16) product(4, 7, _3710)
   Unify: (16) product(4, 7, _3710)
   Call: (17) _3710 is 4*7
   Exit: (17) 28 is 4*7
   Exit: (16) product(4, 7, 28)
   Call: (16) '__aux_maplist/4_product+0'([], [], _3712)
   Unify: (16) '__aux_maplist/4_product+0'([], [], [])
   Exit: (16) '__aux_maplist/4_product+0'([], [], [])
   Exit: (15) '__aux_maplist/4_product+0'([4], [7], [28])
   Exit: (14) '__aux_maplist/4_product+0'([3, 4], [5, 7], [15, 28])
   Call: (14) backward_compatibility:sumlist([15, 28], _3692)
   Unify: (14) backward_compatibility:sumlist([15, 28], _3692)
   Call: (15) lists:sum_list([15, 28], _3692)
   Unify: (15) lists:sum_list([15, 28], _3692)
   Exit: (15) lists:sum_list([15, 28], 43)
   Exit: (14) backward_compatibility:sumlist([15, 28], 43)
   Exit: (13) dot([3, 4], [5, 7], 43)
   Call: (13) '__aux_maplist/3_dot+1'([[6, 8]], _3694, [3, 4])
   Unify: (13) '__aux_maplist/3_dot+1'([[6, 8]], [_3734|_3736], [3, 4])
   Call: (14) dot([3, 4], [6, 8], _3734)
   Unify: (14) dot([3, 4], [6, 8], _3734)
   Call: (15) '__aux_maplist/4_product+0'([3, 4], [6, 8], _3758)
   Unify: (15) '__aux_maplist/4_product+0'([3, 4], [6, 8], [_3740|_3742])
   Call: (16) product(3, 6, _3740)
   Unify: (16) product(3, 6, _3740)
   Call: (17) _3740 is 3*6
   Exit: (17) 18 is 3*6
   Exit: (16) product(3, 6, 18)
   Call: (16) '__aux_maplist/4_product+0'([4], [8], _3742)
   Unify: (16) '__aux_maplist/4_product+0'([4], [8], [_3752|_3754])
   Call: (17) product(4, 8, _3752)
   Unify: (17) product(4, 8, _3752)
   Call: (18) _3752 is 4*8
   Exit: (18) 32 is 4*8
   Exit: (17) product(4, 8, 32)
   Call: (17) '__aux_maplist/4_product+0'([], [], _3754)
   Unify: (17) '__aux_maplist/4_product+0'([], [], [])
   Exit: (17) '__aux_maplist/4_product+0'([], [], [])
   Exit: (16) '__aux_maplist/4_product+0'([4], [8], [32])
   Exit: (15) '__aux_maplist/4_product+0'([3, 4], [6, 8], [18, 32])
   Call: (15) backward_compatibility:sumlist([18, 32], _3734)
   Unify: (15) backward_compatibility:sumlist([18, 32], _3734)
   Call: (16) lists:sum_list([18, 32], _3734)
   Unify: (16) lists:sum_list([18, 32], _3734)
   Exit: (16) lists:sum_list([18, 32], 50)
   Exit: (15) backward_compatibility:sumlist([18, 32], 50)
   Exit: (14) dot([3, 4], [6, 8], 50)
   Call: (14) '__aux_maplist/3_dot+1'([], _3736, [3, 4])
   Unify: (14) '__aux_maplist/3_dot+1'([], [], [3, 4])
   Exit: (14) '__aux_maplist/3_dot+1'([], [], [3, 4])
   Exit: (13) '__aux_maplist/3_dot+1'([[6, 8]], [50], [3, 4])
   Exit: (12) '__aux_maplist/3_dot+1'([[5, 7], [6, 8]], [43, 50], [3, 4])
   Exit: (11) mm_helper([[5, 7], [6, 8]], [3, 4], [43, 50])
   Call: (11) '__aux_maplist/3_mm_helper+1'([], _3688, [[5, 7], [6, 8]])
   Unify: (11) '__aux_maplist/3_mm_helper+1'([], [], [[5, 7], [6, 8]])
   Exit: (11) '__aux_maplist/3_mm_helper+1'([]

这篇关于矩阵乘法序言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆