Return a np.array that encodes the optimal order of multiplications. The optimal order array is then used by `_multi_dot()` to do the multiplication. Also return the cost matrix if `return_costs` is `True` The implementation CLOSELY follows Cormen, "Introduction to Algorithms
(arrays, return_costs=False)
| 3003 | |
| 3004 | |
| 3005 | def _multi_dot_matrix_chain_order(arrays, return_costs=False): |
| 3006 | """ |
| 3007 | Return a np.array that encodes the optimal order of multiplications. |
| 3008 | |
| 3009 | The optimal order array is then used by `_multi_dot()` to do the |
| 3010 | multiplication. |
| 3011 | |
| 3012 | Also return the cost matrix if `return_costs` is `True` |
| 3013 | |
| 3014 | The implementation CLOSELY follows Cormen, "Introduction to Algorithms", |
| 3015 | Chapter 15.2, p. 370-378. Note that Cormen uses 1-based indices. |
| 3016 | |
| 3017 | cost[i, j] = min([ |
| 3018 | cost[prefix] + cost[suffix] + cost_mult(prefix, suffix) |
| 3019 | for k in range(i, j)]) |
| 3020 | |
| 3021 | """ |
| 3022 | n = len(arrays) |
| 3023 | # p stores the dimensions of the matrices |
| 3024 | # Example for p: A_{10x100}, B_{100x5}, C_{5x50} --> p = [10, 100, 5, 50] |
| 3025 | p = [a.shape[0] for a in arrays] + [arrays[-1].shape[1]] |
| 3026 | # m is a matrix of costs of the subproblems |
| 3027 | # m[i,j]: min number of scalar multiplications needed to compute A_{i..j} |
| 3028 | m = zeros((n, n), dtype=double) |
| 3029 | # s is the actual ordering |
| 3030 | # s[i, j] is the value of k at which we split the product A_i..A_j |
| 3031 | s = empty((n, n), dtype=intp) |
| 3032 | |
| 3033 | for l in range(1, n): |
| 3034 | for i in range(n - l): |
| 3035 | j = i + l |
| 3036 | m[i, j] = inf |
| 3037 | for k in range(i, j): |
| 3038 | q = m[i, k] + m[k + 1, j] + p[i] * p[k + 1] * p[j + 1] |
| 3039 | if q < m[i, j]: |
| 3040 | m[i, j] = q |
| 3041 | s[i, j] = k # Note that Cormen uses 1-based index |
| 3042 | |
| 3043 | return (s, m) if return_costs else s |
| 3044 | |
| 3045 | |
| 3046 | def _multi_dot(arrays, order, i, j, out=None): |
searching dependent graphs…