Matrix chain multiplication: Difference between revisions
Added FreeBASIC
m (→{{header|J}}: spaces) |
(Added FreeBASIC) |
||
(10 intermediate revisions by 9 users not shown) | |||
Line 1:
{{task|Discrete math}}
[[Category:Matrices]]
;Problem
Using the most
For instance, with four matrices, one can compute A(B(CD)), A((BC)D), (AB)(CD), (A(BC))D, (AB)C)D. The number of different ways to put the parens is a [[Catalan numbers|Catalan number]], and grows exponentially with the number of factors.
Line 27 ⟶ 28:
__TOC__
=={{header|11l}}==
{{trans|Nim}}
<syntaxhighlight lang="11l">T Optimizer
[Int] dims
[[Int]] m, s
F (dims)
.dims = dims
F findMatrixChainOrder()
V n = .dims.len - 1
.m = [[0] * n] * n
.s = [[0] * n] * n
L(lg) 1 .< n
L(i) 0 .< n - lg
V j = i + lg
.m[i][j] = 7FFF'FFFF
L(k) i .< j
V cost = .m[i][k] + .m[k + 1][j] + .dims[i] * .dims[k + 1] * .dims[j + 1]
I cost < .m[i][j]
.m[i][j] = cost
.s[i][j] = k
F optimalChainOrder(i, j)
I i == j
R String(Char(code' i + ‘A’.code))
E
R ‘(’(.optimalChainOrder(i, .s[i][j]))‘’
‘’(.optimalChainOrder(.s[i][j] + 1, j))‘)’
V Dims1 = [5, 6, 3, 1]
V Dims2 = [1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2]
V Dims3 = [1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]
L(dims) [Dims1, Dims2, Dims3]
V opt = Optimizer(dims)
opt.findMatrixChainOrder()
print(‘Dims: ’dims)
print(‘Order: ’opt.optimalChainOrder(0, dims.len - 2))
print(‘Cost: ’opt.m[0][dims.len - 2])
print(‘’)</syntaxhighlight>
{{out}}
<pre>
Dims: [5, 6, 3, 1]
Order: (A(BC))
Cost: 48
Dims: [1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2]
Order: ((((((((AB)C)D)E)F)G)(H(IJ)))(KL))
Cost: 38120
Dims: [1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]
Order: (A((((((BC)D)(((EF)G)H))I)J)K))
Cost: 1773740
</pre>
=={{header|Ada}}==
This example implements the pseudocode in the reference Wiki page. The pseudocode states that the index values for the array to multiply begin at 0 while the cost and order matrices employ index values beginning at 1. Ada supports this pseudocode directly because Ada allows the programmer to define the index range for any array type.
This Ada example is implemented using a simple package and a main procedure. The package specification is:
<
package mat_chain is
type Vector is array (Natural range <>) of Integer;
procedure Chain_Multiplication (Dims : Vector);
end mat_chain;
</syntaxhighlight>
The implementation or body of the package is:
<
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
Line 130 ⟶ 190:
end mat_chain;
</syntaxhighlight>
The main procedure is:
<
with Mat_Chain; use Mat_Chain;
with Ada.Text_IO; use Ada.Text_IO;
Line 147 ⟶ 207:
Chain_Multiplication(V3);
end chain_main;
</syntaxhighlight>
{{output}}
<pre>
Line 165 ⟶ 225:
=={{header|C}}==
{{trans|Kotlin}}
<
#include <limits.h>
#include <stdlib.h>
Line 236 ⟶ 296:
}
return 0;
}</
{{output}}
Line 255 ⟶ 315:
=={{header|C sharp|C#}}==
{{trans|Kotlin}}
<
class MatrixChainOrderOptimizer {
Line 314 ⟶ 374:
}
}
}</
{{output}}
Line 329 ⟶ 389:
Order : (A((((((BC)D)(((EF)G)H))I)J)K))
Cost : 1773740
</pre>
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cstdint>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
constexpr int32_t MAXIMUM_VALUE = 2'147'483'647;
std::vector<std::vector<int32_t>> cost;
std::vector<std::vector<int32_t>> order;
void print_vector(const std::vector<int32_t>& list) {
std::cout << "[";
for ( uint64_t i = 0; i < list.size() - 1; ++i ) {
std::cout << list[i] << ", ";
}
std::cout << list.back() << "]" << std::endl;
}
int32_t matrix_chain_order(const std::vector<int32_t>& dimensions) {
const uint64_t size = dimensions.size() - 1;
cost = { size, std::vector<int32_t>(size, 0) };
order = { size, std::vector<int32_t>(size, 0) };
for ( uint64_t m = 1; m < size; ++m ) {
for ( uint64_t i = 0; i < size - m; ++i ) {
int32_t j = i + m;
cost[i][j] = MAXIMUM_VALUE;
for ( int32_t k = i; k < j; ++k ) {
int32_t current_cost = cost[i][k] + cost[k + 1][j]
+ dimensions[i] * dimensions[k + 1] * dimensions[j + 1];
if ( current_cost < cost[i][j] ) {
cost[i][j] = current_cost;
order[i][j] = k;
}
}
}
}
return cost[0][size - 1];
}
std::string get_optimal_parenthesizations(const std::vector<std::vector<int32_t>>& order,
const uint64_t& i, const uint64_t& j) {
if ( i == j ) {
std::string result(1, char(i + 65));
return result;
} else {
std::stringstream stream;
stream << "(" << get_optimal_parenthesizations(order, i, order[i][j])
<< " * " << get_optimal_parenthesizations(order, order[i][j] + 1, j) << ")";
return stream.str();
}
}
void matrix_chain_multiplication(const std::vector<int32_t>& dimensions) {
std::cout << "Array Dimension = "; print_vector(dimensions);
std::cout << "Cost = " << matrix_chain_order(dimensions) << std::endl;
std::cout << "Optimal Multiply = "
<< get_optimal_parenthesizations(order, 0, order.size() - 1) << std::endl << std::endl;
}
int main() {
matrix_chain_multiplication({ 5, 6, 3, 1 });
matrix_chain_multiplication({ 1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2 });
matrix_chain_multiplication({ 1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10 });
}
</syntaxhighlight>
{{ out }}
<pre>
Array Dimension = [5, 6, 3, 1]
Cost = 48
Optimal Multiply = (A * (B * C))
Array Dimension = [1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2]
Cost = 38120
Optimal Multiply = ((((((((A * B) * C) * D) * E) * F) * G) * (H * (I * J))) * (K * L))
Array Dimension = [1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]
Cost = 1773740
Optimal Multiply = (A * ((((((B * C) * D) * (((E * F) * G) * H)) * I) * J) * K))
</pre>
=={{header|Fortran}}==
{{trans|Python}}
This is a translation of the Python iterative solution.
<
implicit none
contains
Line 391 ⟶ 534:
call optim([1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2])
call optim([1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10])
end program</
'''Output'''
Line 400 ⟶ 543:
1773740 (1*((((((2*3)*4)*(((5*6)*7)*8))*9)*10)*11))
</pre>
=={{header|FreeBASIC}}==
{{trans|VBA}}
This is a translation of the Python iterative solution.
<syntaxhighlight lang="vbnet">Dim Shared As Integer U(), V()
Sub Aux(i As Integer, j As Integer)
Dim As Integer k = U(i, j)
If k < 0 Then
Print Str(i);
Else
Print "(";
Aux(i, k)
Print "*";
Aux(i + k, j - k)
Print ")";
End If
End Sub
Sub Optimize(a() As Integer)
Dim As Integer i, j, k, c
Dim As Integer n = Ubound(a) - 1
Redim U(n, n), V(n, n)
For i = 1 To n
U(i, 1) = -1
V(i, 1) = 0
Next i
For j = 2 To n
For i = 1 To n - j + 1
V(i, j) = &H7FFFFFFF
For k = 1 To j - 1
c = V(i, k) + V(i + k, j - k) + a(i) * a(i + k) * a(i + j)
If c < V(i, j) Then
U(i, j) = k
V(i, j) = c
End If
Next k
Next i
Next j
Print V(1, n); " ";
Aux(1, n)
Print
Erase U, V
End Sub
Dim As Integer A1(1 To 4) = {5, 6, 3, 1}
Optimize(A1())
Dim As Integer A2(1 To 13) = {1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2}
Optimize(A2())
Dim As Integer A3(1 To 12) = {1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10}
Optimize(A3())
Sleep</syntaxhighlight>
{{out}}
<pre> 48(1*(2*3))
38120((((((((1*2)*3)*4)*5)*6)*7)*(8*(9*10)))*(11*12))
1773740(1*((((((2*3)*4)*(((5*6)*7)*8))*9)*10)*11))</pre>
=={{header|Go}}==
The first <code>for</code> loop is based on the pseudo and Java code from the
[[wp:Matrix_chain_multiplication#A_dynamic_programming_algorithm|Wikipedia article]].
<
import "fmt"
Line 479 ⟶ 681:
fmt.Println()
}
}</
{{out}}
<pre>
Line 510 ⟶ 712:
=={{header|Haskell}}==
<
import Data.Char (chr, ord)
import Data.Maybe (fromJust)
Line 550 ⟶ 752:
main :: IO ()
main = mapM_ printBlock mats</
{{out}}
<pre>for [5,6,3,1] we have 48 possibilities, z.B (a(bc))
Line 561 ⟶ 763:
Given J's incredible strengths with arrays and matrices, the author is certain there is a much more succinct and idiomatic approach available, but hasn't spent the time understanding how the Wikipedia algorithm works, so hasn't made an attempt at a more native J solution. Others on RC are welcome and invited to do so.
<
s =. m =. 0 $~ ,~ n=._1+#y
for_lmo. 1+i.<:n do.
Line 587 ⟶ 789:
k =. x {~ <y NB. y = i,j
'(' , (x poco i,k) , (x poco j ,~ 1+k) , ')'
)
Line 594 ⟶ 796:
smoutput 'Cost: ' , ": x: M {~ <0;_1
smoutput 'Order: ', S poco 0 , <:#M
)</
{{out}}
<
Cost: 48
Order: (A(BC))
Line 608 ⟶ 810:
optMM 1000 1 500 12 1 700 2500 3 2 5 14 10
Cost: 1773740
Order: (A((((((BC)D)(((EF)G)H))I)J)K))</
=={{header|Java}}==
Thanks to the Wikipedia page for a working Java implementation.
<
import java.util.Arrays;
Line 673 ⟶ 875:
}
</syntaxhighlight>
{{out}}
<pre>
Line 687 ⟶ 889:
Cost = 1773740
Optimal Multiply = (A * ((((((B * C) * D) * (((E * F) * G) * H)) * I) * J) * K))
</pre>
=={{header|jq}}==
{{trans|Wren}}
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''
<syntaxhighlight lang="jq"># Input: array of dimensions
# output: {m, s}
def optimalMatrixChainOrder:
. as $dims
| (($dims|length) - 1) as $n
| reduce range(1; $n) as $len ({m: [], s: []};
reduce range(0; $n-$len) as $i (.;
($i + $len) as $j
| .m[$i][$j] = infinite
| reduce range($i; $j) as $k (.;
($dims[$i] * $dims [$k + 1] * $dims[$j + 1]) as $temp
| (.m[$i][$k] + .m[$k + 1][$j] + $temp) as $cost
| if $cost < .m[$i][$j]
then .m[$i][$j] = $cost
| .s[$i][$j] = $k
else .
end ) )) ;
# input: {s}
def printOptimalChainOrder($i; $j):
if $i == $j
then [$i + 65] | implode #=> "A", "B", ...
else "(" +
printOptimalChainOrder($i; .s[$i][$j]) +
printOptimalChainOrder(.s[$i][$j] + 1; $j) + ")"
end;
def dimsList: [
[5, 6, 3, 1],
[1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2],
[1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]
];
dimsList[]
| "Dims : \(.)",
(optimalMatrixChainOrder
| "Order : \(printOptimalChainOrder(0; .s|length - 1))",
"Cost : \(.m[0][.s|length - 1])\n" )</syntaxhighlight>
{{out}}
<pre>
Dims : [5,6,3,1]
Order : (AB)
Cost : 90
Dims : [1,5,25,30,100,70,2,1,100,250,1,1000,2]
Order : ((((((((AB)C)D)E)F)G)(H(IJ)))K)
Cost : 37118
Dims : [1000,1,500,12,1,700,2500,3,2,5,14,10]
Order : (A(((((BC)D)(((EF)G)H))I)J))
Cost : 1777600
</pre>
Line 694 ⟶ 954:
'''Module''':
<
using OffsetArrays
Line 723 ⟶ 983:
end
end # module MatrixChainMultiplications</
'''Main''':
<
println(MatrixChainMultiplications.optim([1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]))</
{{out}}
Line 735 ⟶ 995:
=={{header|Kotlin}}==
This is based on the pseudo-code in the Wikipedia article.
<
lateinit var m: List<IntArray>
Line 784 ⟶ 1,044:
println("\nCost : ${m[0][s.size - 1]}\n")
}
}</
{{out}}
Line 802 ⟶ 1,062:
=={{header|Lua}}==
<
local function MatrixChainOrder(dims)
local m = {}
Line 858 ⟶ 1,118:
printOptimalChainOrder(s)
print("Cost : "..tostring(m[1][#s]).."\n")
end</
{{out}}
Line 877 ⟶ 1,137:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
{{trans|Fortran}}
<
optim[a_List] := Module[{u, v, n, c, r, s},
n = Length[a] - 1;
Line 919 ⟶ 1,179:
{r, s} = optim[{1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10}];
r
s</
{{out}}
<pre>38120
Line 925 ⟶ 1,185:
1773740
1*((((((2*3)*4)*(((5*6)*7)*8))*9)*10)*11)</pre>
=={{header|MATLAB}}==
{{trans|Fortran}}
<syntaxhighlight lang="matlab">function [r,s] = optim(a)
n = length(a)-1;
u = zeros(n,n);
Line 958 ⟶ 1,216:
s = sprintf("(%s*%s)",aux(u,i,k),aux(u,i+k,j-k));
end
end</
{{out}}
<
r =
Line 983 ⟶ 1,241:
s =
"(1*((((((2*3)*4)*(((5*6)*7)*8))*9)*10)*11))"</
=={{header|Nim}}==
{{trans|Kotlin}}
<
type Optimizer = object
Line 1,041 ⟶ 1,299:
echo "Order: ", opt.optimalChainOrder(0, dims.len - 2)
echo "Cost: ", opt.m[0][dims.len - 2]
echo ""</
{{out}}
Line 1,058 ⟶ 1,316:
=={{header|Perl}}==
{{trans|Raku}}
<
use feature 'say';
Line 1,104 ⟶ 1,362:
say matrix_mult_chaining(<1 5 25 30 100 70 2 1 100 250 1 1000 2>);
say matrix_mult_chaining(<1000 1 500 12 1 700 2500 3 2 5 14 10>);</
{{out}}
<pre>38120 ((((((((A1A2)A3)A4)A5)A6)A7)(A8(A9A10)))(A11A12))
Line 1,111 ⟶ 1,369:
=={{header|Phix}}==
As per the wp pseudocode
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">optimal_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #004080;">int</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">int</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">==</span><span style="color: #000000;">j</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #008000;">'A'</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">"("</span><span style="color: #0000FF;">&</span><span style="color: #000000;">optimal_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">&</span><span style="color: #000000;">optimal_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">")"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">optimal_matrix_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">dims</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dims</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">len</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">len</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">i</span> <span style="color: #008080;">to</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">cost</span> <span style="color: #0000FF;">:=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">dims</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">dims</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">dims</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]<</span><span style="color: #000000;">0</span>
<span style="color: #008080;">or</span> <span style="color: #000000;">cost</span><span style="color: #0000FF;"><</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cost</span><span style="color: #0000FF;">;</span>
<span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">;</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">optimal_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">25</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">30</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">70</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">100</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">250</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">1000</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">500</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">700</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2500</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Dims : %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Order : %s\nCost : %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">optimal_matrix_chain_order</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ti</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,171 ⟶ 1,433:
=== Enumeration of parenthesizations ===
<
def aux(n, k):
if n == 1:
Line 1,183 ⟶ 1,445:
for v in aux(n - i, k + i):
yield [u, v]
yield from aux(n, 0)</
'''Example''' (in the same order as in the task description)
<
print(u)
Line 1,194 ⟶ 1,456:
[[0, 1], [2, 3]]
[[0, [1, 2]], 3]
[[[0, 1], 2], 3]</
And here is the optimization step:
<
def cost(k):
if type(k) is int:
Line 1,214 ⟶ 1,476:
cmin = c
umin = u
return cmin, umin</
=== Recursive cost optimization ===
Line 1,220 ⟶ 1,482:
The previous function optim1 already used recursion, but only to compute the cost of a given parens configuration, whereas another function (a generator actually) provides these configurations. Here we will do both recursively in the same function, avoiding the computation of configurations altogether.
<
def aux(n, k):
if n == 1:
Line 1,242 ⟶ 1,504:
return m, p, q, u
s, p, q, u = aux(len(a) - 1, 0)
return s, u</
=== Memoized recursive call ===
Line 1,248 ⟶ 1,510:
The only difference between optim2 and optim3 is the [[:wp:https://en.wikipedia.org/wiki/Memoization|@memoize]] [https://www.python.org/dev/peps/pep-0318/ decorator]. Yet the algorithm is way faster with this. According to Wikipedia, the complexity falls from O(2^n) to O(n^3). This is confirmed by plotting log(time) vs log(n) for n up to 580 (this needs [https://docs.python.org/3/library/sys.html#sys.setrecursionlimit changing Python's recursion limit]).
<
h = {}
def g(*u):
Line 1,282 ⟶ 1,544:
return m, p, q, u
s, p, q, u = aux(len(a) - 1, 0)
return s, u</
=== Putting all together ===
<
u = [[1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2],
Line 1,301 ⟶ 1,563:
t2 = time.clock()
print("%s %10.3f %10d %s" % (f.__name__, 1000 * (t2 - t1), s, u))
print()</
'''Output''' (timings are in milliseconds)
Line 1,328 ⟶ 1,590:
In the previous solution, memoization is done blindly with a dictionary. However, we need to compute the optimal products for all sublists. A sublist is described by its first index and length (resp. i and j+1 in the following function), hence the set of all sublists can be described by the indices of elements in a triangular array u. We first fill the "solution" (there is no product) for sublists of length 1 (u[0]), then for each successive length we optimize using what when know about smaller sublists. Instead of keeping track of the optimal solutions, the single needed one is computed in the end.
<
global u
n = len(a) - 1
Line 1,356 ⟶ 1,618:
print(optim4([1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2]))
print(optim4([1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10]))</
'''Output'''
Line 1,365 ⟶ 1,627:
</pre>
=={{header|
<syntaxhighlight lang="rsplus">aux <- function(i, j, u) {
k <- u[[i, j]]
if (k < 0) {
i
} else {
paste0("(", Recall(i, k, u), "*", Recall(i + k, j - k, u), ")")
}
}
chain.mul <- function(a) {
n <- length(a) - 1
u <- matrix(0, n, n)
v <- matrix(0, n, n)
u[, 1] <- -1
for (j in seq(2, n)) {
for (i in seq(n - j + 1)) {
v[[i, j]] <- Inf
for (k in seq(j - 1)) {
s <- v[[i, k]] + v[[i + k, j - k]] + a[[i]] * a[[i + k]] * a[[i + j]]
if (s < v[[i, j]]) {
u[[i, j]] <- k
v[[i, j]] <- s
}
}
}
}
list(cost = v[[1, n]], solution = aux(1, n, u))
}
chain.mul(c(5, 6, 3, 1))
# $cost
# [1] 48
# $solution
# [1] "(1*(2*3))"
chain.mul(c(1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2))
# $cost
# [1] 38120
# $solution
# [1] "((((((((1*2)*3)*4)*5)*6)*7)*(8*(9*10)))*(11*12))"
chain.mul(c(1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10))
# $cost
# [1] 1773740
# $solution
# [1] "(1*((((((2*3)*4)*(((5*6)*7)*8))*9)*10)*11))"</syntaxhighlight>
=={{header|Racket}}==
'''Memoization'''
<
(define (memoize f)
Line 1,394 ⟶ 1,708:
#:combine (λ (left-answer right-answer _)
(list left-answer '× right-answer)))))]))))
(loop 0 (sub1 (vector-length dims))))</
'''Main'''
<
(begin (printf "~a: ~a\n" (~a (quote <x>) #:min-width 12) <x>) ...))
Line 1,407 ⟶ 1,721:
(solve #(1 5 25 30 100 70 2 1 100 250 1 1000 2))
(solve #(1000 1 500 12 1 700 2500 3 2 5 14 10))</
'''Output''' (timings are in milliseconds)
Line 1,426 ⟶ 1,740:
(formerly Perl 6)
This example is based on Moritz Lenz's code, written for Carl Mäsak's Perl 6 Coding Contest, in 2010. Slightly simplified, it fulfills the Rosetta Code task as well.
<syntaxhighlight lang="raku"
my @cp;
# @cp has a dual function:
Line 1,470 ⟶ 1,784:
say matrix-mult-chaining(<1 5 25 30 100 70 2 1 100 250 1 1000 2>);
say matrix-mult-chaining(<1000 1 500 12 1 700 2500 3 2 5 14 10>);</
{{out}}
Line 1,477 ⟶ 1,791:
=={{header|Rust}}==
<
fn main() {
Line 1,535 ⟶ 1,849:
}
}
}</
{{out}}
<pre>
Line 1,557 ⟶ 1,871:
Here is the equivalent of optim3 in Python's solution. Memoization is done with an [https://www.stata.com/help.cgi?mf_asarray associative array]. Multiple results are returned in a [https://www.stata.com/help.cgi?m2_struct structure]. The same effect as optim2 can be achieved by removing the asarray machinery.
<
struct ans {
real scalar p,q,s
Line 1,617 ⟶ 1,931:
optim((1,5,25,30,100,70,2,1,100,250,1,1000,2))
optim((1000,1,500,12,1,700,2500,3,2,5,14,10))
end</
'''Output'''
Line 1,631 ⟶ 1,945:
{{trans|Fortran}}
<
function aux(u,i,j) {
k = u[i,j]
Line 1,669 ⟶ 1,983:
optim((1,5,25,30,100,70,2,1,100,250,1,1000,2))
optim((1000,1,500,12,1,700,2500,3,2,5,14,10))
end</
'''Output'''
Line 1,683 ⟶ 1,997:
{{trans|Fortran}}
<
Option Base 1
Dim N As Long, U() As Long, V() As Long
Line 1,730 ⟶ 2,044:
Call Optimize(Array(1, 5, 25, 30, 100, 70, 2, 1, 100, 250, 1, 1000, 2))
Call Optimize(Array(1000, 1, 500, 12, 1, 700, 2500, 3, 2, 5, 14, 10))
End Sub</
'''Output'''
Line 1,742 ⟶ 2,056:
=={{header|Wren}}==
{{trans|Kotlin}}
<
var s = []
Line 1,792 ⟶ 2,106:
printOptimalChainOrder.call(0, s.count - 1)
System.print("\nCost : %(m[0][s.count - 1])\n")
}</
{{out}}
Line 1,811 ⟶ 2,125:
=={{header|zkl}}==
{{trans|Python}}
<
aux:=fcn(n,k,a){ // (int,int,list) --> (int,int,int,list)
if(n==1){
Line 1,849 ⟶ 2,163:
h[key]=r;
return(r);
}</
<
var letters=["A".."Z"].pump(String);
u.pump(String,
fcn(n){ if(List.isType(n)) String("(",pp(n),")") else letters[n] })
}
fcn prnt(s,u){ "%-9,d %s\n\t-->%s\n".fmt(s,u.toString(*,*),pp(u)).println() }</
<
prnt(s,u);
Line 1,862 ⟶ 2,176:
prnt(s,u);
optim3(T(5,6,3,1)) : prnt(_.xplode());</
{{out}}
<pre>
|