Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Matrix_Chain.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
46# ifndef MATRIX_CHAIN_H
47# define MATRIX_CHAIN_H
48
49# include <limits>
50# include <string>
51# include <cstddef>
52
53# include <ah-errors.H>
54# include <tpl_array.H>
55
56namespace Aleph
57{
65
66
67 namespace matrix_chain_detail
68 {
69 inline size_t checked_add(const size_t a, const size_t b,
70 const char *ctx)
71 {
72 ah_runtime_error_if(a > std::numeric_limits<size_t>::max() - b)
73 << "matrix_chain_order: overflow while computing " << ctx;
74 return a + b;
75 }
76
77 inline size_t checked_mul(const size_t a, const size_t b,
78 const char *ctx)
79 {
80 if (a == 0 or b == 0)
81 return 0;
82
83 ah_runtime_error_if(a > std::numeric_limits<size_t>::max() / b)
84 << "matrix_chain_order: overflow while computing " << ctx;
85 return a * b;
86 }
87
88 inline size_t scalar_cost(const size_t di, const size_t dk,
89 const size_t dj)
90 {
91 const size_t lhs = checked_mul(di, dk, "dims[i] * dims[k+1]");
92 return checked_mul(lhs, dj, "dims[i] * dims[k+1] * dims[j+1]");
93 }
94
95 inline void build_parens(const Array<Array<size_t>> & s,
96 size_t i, size_t j,
97 std::string & out)
98 {
99 if (i == j)
100 {
101 out += "A";
102 out += std::to_string(i + 1);
103 return;
104 }
105 out += "(";
106 build_parens(s, i, s[i][j], out);
107 out += " ";
108 build_parens(s, s[i][j] + 1, j, out);
109 out += ")";
110 }
111 } // namespace matrix_chain_detail
112
113
129 {
130 ah_domain_error_if(dims.size() < 2)
131 << "matrix_chain_order: dims must have at least 2 entries";
132 for (const size_t dim : dims)
134 << "matrix_chain_order: matrix dimensions must be positive";
135
136 const size_t n = dims.size() - 1; // number of matrices
137 if (n == 1)
138 return Matrix_Chain_Result{0, "A1", Array<Array<size_t>>()};
139
140 // dp[i][j] = min cost of multiplying matrices i..j (0-based)
142 dp.reserve(n);
143 for (size_t i = 0; i < n; ++i)
144 {
146 for (size_t j = 0; j < n; ++j)
147 row(j) = 0;
148 dp.append(std::move(row));
149 }
150
152 split.reserve(n);
153 for (size_t i = 0; i < n; ++i)
154 {
156 for (size_t j = 0; j < n; ++j)
157 row(j) = 0;
158 split.append(std::move(row));
159 }
160
161 // chain length l = 2..n
162 for (size_t l = 2; l <= n; ++l)
163 for (size_t i = 0; i <= n - l; ++i)
164 {
165 const size_t j = i + l - 1;
166 dp[i][j] = std::numeric_limits<size_t>::max();
167 for (size_t k = i; k < j; ++k)
168 {
169 const size_t mul_cost =
171 const size_t subtotal =
172 matrix_chain_detail::checked_add(dp[i][k], dp[k + 1][j], "dp[i][k] + dp[k+1][j]");
173 const size_t cost =
174 matrix_chain_detail::checked_add(subtotal, mul_cost, "dp + scalar multiplications");
175 if (cost < dp[i][j])
176 {
177 dp[i][j] = cost;
178 split[i][j] = k;
179 }
180 }
181 }
182
183 std::string parens;
185
186 return Matrix_Chain_Result{
187 dp[0][n - 1], std::move(parens),
188 std::move(split)
189 };
190 }
191
192
204 [[nodiscard]] inline size_t
209} // namespace Aleph
210
211# endif // MATRIX_CHAIN_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:266
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:315
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_dim_function > > dim(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4052
size_t checked_add(const size_t a, const size_t b, const char *ctx)
size_t scalar_cost(const size_t di, const size_t dk, const size_t dj)
size_t checked_mul(const size_t a, const size_t b, const char *ctx)
void build_parens(const Array< Array< size_t > > &s, size_t i, size_t j, std::string &out)
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Matrix_Chain_Result matrix_chain_order(const Array< size_t > &dims)
Compute optimal matrix-chain multiplication order.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
size_t matrix_chain_min_cost(const Array< size_t > &dims)
Compute only the minimum multiplication cost.
std::vector< std::string > & split(const std::string &s, const char delim, std::vector< std::string > &elems)
Split a std::string by a single delimiter character.
Result of matrix-chain multiplication optimization.
Array< Array< size_t > > split
Split table for reconstruction.
size_t min_multiplications
Minimum scalar multiplications.
std::string parenthesization
Optimal parenthesization string.
static int * k
Dynamic array container with automatic resizing.
DynList< int > l