zoukankan      html  css  js  c++  java
  • [Coding Made Simple] Matrix Chain Multiplication

    Given some matrices, in what order you would multiply them to minimize cost of multiplication.

     The following problem formulation is extracted from this link.

    Problem Formulation

    Note that although we can use any legal parenthesization, which will lead to a valid result. But, not all parenthesizations involve the same number of operations. To understand this point, consider the problem of a chain A1A2A3 of three matrices and suppose

    A1 be of dimension 10 × 100
    A
    2 be of dimension 100 × 5
    A
    3 be of dimension 5 × 50

    Then,

    MultCost[((A1 A2A3)] = (10 . 100 . 5) +  (10 . 5 . 50) = 7,500 scalar multiplications.

    MultCost[(A1 (A2 A3))] = (100 . 5 . 50) + (10 . 100 . 50) = 75,000 scalar multiplications.

    It is easy to see that even for this small example, computing the product according to first parenthesization is 10 times faster.

     

    The Chain Matrix Multiplication Problem

    Given a sequence of n matrices A1A2, ... An, and their dimensions p0p1p2, ..., pn, where where i = 1, 2, ..., n, matrix Ai has dimension p− 1 × pi, determine the order of multiplication that minimizes the the number of scalar multiplications.

     

    Equivalent formulation (perhaps more easy to work with!)

    Given n matrices, A1A2, ... An, where for 1 ≤ i ≤ nAi is a p− 1 × pi, matrix, parenthesize the product A1A2, ... An so as to minimize the total cost, assuming that the cost of multiplying an p− 1× pi matrix by a p× pi + 1 matrix using the naive algorithm is p− 1× p× pi + 1.

     

    Note that this algorithm does not perform the multiplications, it just figures out the best order in which to perform the multiplication operations.

     

    Solution 1. Simple recursive approach 

    The original problem can be solved by recursively solving its subproblems as follows.

    cost(i, j) is the min of cost(i, k) + cost(k + 1, j) + matrices[i].row * matrices[k].col * matrices[j].col for all k >= i && k < j.

    The base case is when i == j, the cost is 0 as it takes nothing to multipy 1 matrix.

     

    Once again the same with a lot of recursive algorithms, it has the overlapping subproblems issue.

    For example, to compute cost(0, 3), the following computations are done separately.

    cost(0, 2), cost(3, 3);

    cost(0,1), cost(2, 3);

    cost(0, 0), cost(1, 3);

    But in the process of computing cost(0,2), cost(0, 1) is computed, which is computed later in a different parenthess split. This 

    redundancy has way more presence as the input grows bigger. 

     

    Solution 2. Dynamic Programming, O(n^3) runtime, O(n^2) space 

    To avoid the redundany issue in solution 1, we should use dynamic programming.

    State: cost[i][j]: the min cost of multiplying matrices i to j.

    Function: same with the recursive formula.

     

     1 class Matrix {
     2     int row;
     3     int col;
     4     Matrix(int row, int col){
     5         this.row = row;
     6         this.col = col;
     7     }
     8 }
     9 public class Solution {
    10     public int matrixChainMultiRecursion(Matrix[] matrices) {
    11         if(matrices == null || matrices.length == 0) {
    12             return 0;
    13         }        
    14         return recursiveHelper(matrices, 0, matrices.length - 1);
    15     }
    16     private int recursiveHelper(Matrix[] matrices, int startIdx, int endIdx) {
    17         if(startIdx == endIdx){
    18             return 0;
    19         }
    20         int miniCost = Integer.MAX_VALUE;
    21         for(int i = startIdx; i < endIdx; i++){
    22             int leftCost = recursiveHelper(matrices, startIdx, i);
    23             int rightCost = recursiveHelper(matrices, i + 1, endIdx);
    24             int cost = leftCost + rightCost + matrices[startIdx].row * matrices[i].col * matrices[endIdx].col;
    25             miniCost = Math.min(cost, miniCost);
    26         }
    27         return miniCost;
    28     }
    29     public int matrixChainMultiDp(Matrix[] matrices) {
    30         if(matrices == null || matrices.length == 0) {
    31             return 0;
    32         }
    33         int[][] cost = new int[matrices.length][matrices.length];
    34         for(int i = 0; i < matrices.length; i++){
    35             int j = i;
    36             for(; j < matrices.length; j++){
    37                 cost[i][j] = Integer.MAX_VALUE;
    38             }
    39         }
    40         for(int i = 0; i < matrices.length; i++){
    41             cost[i][i] = 0;
    42         }
    43         for(int len = 2; len <= matrices.length; len++){
    44             for(int i = 0; i <= matrices.length - len; i++){
    45                 for(int j = i; j < i + len - 1; j++){
    46                     int c = cost[i][j] + cost[j + 1][i + len - 1] + matrices[i].row * matrices[j + 1].row * matrices[i + len - 1].col;
    47                     cost[i][i + len - 1] = Math.min(cost[i][i + len - 1], c);                    
    48                 }
    49             }
    50         }
    51         return cost[0][matrices.length - 1];
    52     }
    53     public static void main(String[] args) {
    54         Matrix m1 = new Matrix(2, 3);
    55         Matrix m2 = new Matrix(3, 6);
    56         Matrix m3 = new Matrix(6, 4);
    57         Matrix m4 = new Matrix(4, 5);
    58         Matrix[] matrices = {m1, m2, m3, m4};
    59         Solution sol = new Solution();
    60         System.out.println(sol.matrixChainMultiRecursion(matrices));
    61         System.out.println(sol.matrixChainMultiDp(matrices));        
    62     }
    63 }
  • 相关阅读:
    【Unity学习笔记】Unity网络游戏开发实战(一)---网络编程的开端:Echo程序
    【DX11学习笔记】GerstnerWave波浪模拟(基于GPU计算着色器的实现)
    【DX11学习笔记】粒子系统--爆炸特效
    【设计模式】(二)观察者模式是什么?
    【设计模式】(一)工厂模式是什么?
    【C++笔记】C++中常见智能指针auto_ptr、unique_ptr、shared_ptr和weak_ptr的用法
    【C++笔记】C++关联容器set和map的概述和操作
    【C++笔记】C++函数模版与类模版
    【C++笔记】C++中vector、stack、deque、list的简易实际使用方法
    python之赋值、浅拷贝、深拷贝
  • 原文地址:https://www.cnblogs.com/lz87/p/7283009.html
Copyright © 2011-2022 走看看