442 - Matrix Chain Multiplication

本文介绍了一种算法问题——矩阵链乘法,旨在找到最佳的矩阵乘法顺序以减少计算成本。文章通过示例详细解释了如何判断矩阵相乘的有效性及计算所需的基乘次数,并提供了一个使用栈实现的具体解决方案。

 Matrix Chain Multiplication 

Suppose you have to evaluate an expression like A*B*C*D*E where A,B,C,D and E are matrices. Since matrix multiplication is associative, the order in which multiplications are performed is arbitrary. However, the number of elementary multiplications needed strongly depends on the evaluation order you choose.

For example, let A be a 50*10 matrix, B a 10*20 matrix and C a 20*5 matrix. There are two different strategies to compute A*B*C, namely (A*B)*C and A*(B*C).

The first one takes 15000 elementary multiplications, but the second one only 3500.

Your job is to write a program that determines the number of elementary multiplications needed for a given evaluation strategy.

Input Specification

Input consists of two parts: a list of matrices and a list of expressions.

The first line of the input file contains one integer n ( tex2html_wrap_inline28 ), representing the number of matrices in the first part. The next n lines each contain one capital letter, specifying the name of the matrix, and two integers, specifying the number of rows and columns of the matrix.

The second part of the input file strictly adheres to the following syntax (given in EBNF):

SecondPart = Line { Line } <EOF>
Line       = Expression <CR>
Expression = Matrix | "(" Expression Expression ")"
Matrix     = "A" | "B" | "C" | ... | "X" | "Y" | "Z"

Output Specification

For each expression found in the second part of the input file, print one line containing the word "error" if evaluation of the expression leads to an error due to non-matching matrices. Otherwise print one line containing the number of elementary multiplications needed to evaluate the expression in the way specified by the parentheses.

Sample Input

9
A 50 10
B 10 20
C 20 5
D 30 35
E 35 15
F 15 5
G 5 10
H 10 20
I 20 25
A
B
C
(AA)
(AB)
(AC)
(A(BC))
((AB)C)
(((((DE)F)G)H)I)
(D(E(F(G(HI)))))
((D(EF))((GH)I))

Sample Output

0
0
0
error
10000
error
3500
15000
40500
47500
15125
 

题意:有许多个矩阵。给你一个表达式,是矩阵相乘的表达式。然后让你判断是否满足矩阵相乘的条件,如果满足,求出一共计算了多少次基本的乘法

首先要知道矩阵相乘的要求。矩阵A(M*N) 矩阵B (N*L) 即要求相乘的两矩阵的前一个列和后一个行相同,而乘法一共做了M*N*L次。

这和计算机对算术表达式计算的原理一样。用一个栈来记录操作数,用一个栈来记录操作符。而记录操作数的栈要用数组,分别记录行和列。具体见代码吧。还是比较简单的一道题

还有就是处理这类题目的时候一定要记得最后是否为空栈,以及最后清空栈。


#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
#include<string>
#include<ctype.h>
using namespace std;
struct node
{
    int x;
    int y;
};
int main ()
{
    int n,i,j,sum=0,m[30][2];
    char str[100];
    node A,B;
    cin>>n;
    for (i=0; i<n; i++)
        scanf("%s%d%d",str,&m[i][0],&m[i][1]);
    while(cin>>str)
    {
        bool flag=true;
        sum=0;
        stack<node> sn;
        stack<char> op;
        int len=strlen(str);
        for (i=0; i<len; i++)
        {
            if (isalpha(str[i]))
            {
                node temp;
                temp.x=m[str[i]-65][0];
                temp.y=m[str[i]-65][1];
                sn.push(temp);
            }
            else if (str[i]=='(') op.push(str[i]);
            else
            {
                op.pop();
                B=sn.top();
                sn.pop();
                A=sn.top();
                sn.pop();
                if (A.y==B.x)
                {
                    sum+=A.x*A.y*B.y;
                    A.y=B.y;
                    sn.push(A);
                }
                else
                {
                    flag=false;
                    break;
                }
            }
            if (!flag) break;
        }
        if (!flag) cout<<"error"<<endl;
        else cout<<sum<<endl;
    }
    return 0;
}



import cvxpy as cp import numpy as np import pandas as pd data = pd.read_excel('附件1.xlsx') X = data.iloc[1:, 1:2] Y = data.iloc[1:, 2:3] W = data.iloc[2:, 3:4] # 收集点垃圾量(i=1..n) xi = X.values.flatten() # 转换为一维数组 (n,) yi = Y.values.flatten() # 转换为一维数组 (n,) wi = W.values.flatten() # 转换为一维数组 (n,) # 定义参数 n = 30 # 收集点数量(i=1..n,0为处理厂) K = 30 # 车辆总数 Q = 5 # 最大载重 # 计算距离矩阵dij(i,j=0..n) dij = np.zeros((n+1, n+1)) for i in range(n+1): for j in range(n+1): dij[i, j] = np.sqrt((xi[i] - xi[j])**2 + (yi[i] - yi[j])**2) x = cp.Variable((n+1, n+1, K), boolean=True) # x_ijv: 车辆v从i到j y = cp.Variable((n, K), boolean=True) # y_iv: 车辆v服务收集点i(i=1..n,索引0..n-1) z = cp.Variable(K, boolean=True) # z_v: 使用车辆v u = cp.Variable((n+1, K), nonneg=True) # u_iv: 车辆v访问i后的累计载重(i=0..n,u[0,v]=0) objective = cp.Minimize(cp.sum(cp.sum(cp.sum(dij @ x, axis=2), axis=1), axis=0)) # 约束条件 constraints = [] # 1. 每个收集点被 exactly 一辆车服务(i=1..n,对应y的索引0..n-1) for i in range(n): constraints.append(cp.sum(y[i, :]) == 1) # 2. 流量守恒(i=1..n,处理厂i=0的约束在6中) for i in range(1, n+1): # 收集点i(1..n,y索引i-1) for v in range(K): constraints.append(cp.sum(x[i, :, v]) == y[i-1, v]) # 离开i的次数等于服务i的次数 constraints.append(cp.sum(x[:, i, v]) == y[i-1, v]) # 进入i的次数等于服务i的次数 # 3. 载重约束 for v in range(K): constraints.append(cp.sum(wi * y[:, v]) <= Q * z[v]) # 4. MTZ约束(子回路消除) for v in range(K): constraints.append(u[0, v] == 0) # 处理厂出发时载重为0 for i in range(1, n+1): # 收集点i(1..n,wi[i-1]) constraints.append(u[i, v] >= wi[i-1]) # 载重下限 constraints.append(u[i, v] <= Q) # 载重上限 for j in range(1, n+1): if i != j: constraints.append(u[i, v] - u[j, v] + Q * x[i, j, v] <= Q - wi[j-1]) # 5. 车辆使用约束:服务收集点则使用车辆 for i in range(n): for v in range(K): constraints.append(y[i, v] <= z[v]) # 6. 出发返回约束(处理厂i=0,出发到收集点1..n,返回从收集点1..n到0) for v in range(K): constraints.append(cp.sum(x[0, 1:, v]) == z[v]) # 出发次数等于车辆使用 constraints.append(cp.sum(x[1:, 0, v]) == z[v]) # 返回次数等于车辆使用 # 建立问题并求解 problem = cp.Problem(objective, constraints) problem.solve() # 输出结果(示例,需根据实际需求处理) print("最优目标值:", problem.value) print("使用的车辆:", z.value)D:\python\python.exe D:\35433\Documents\数模练习\电工杯\问题1.py D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 1 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 2 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 3 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 4 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 5 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 6 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 7 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 8 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 9 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 10 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 11 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 12 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 13 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 14 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 15 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 16 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 17 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 18 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 19 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 20 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 21 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 22 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 23 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 24 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 25 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 26 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 27 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 28 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 29 times so far. D:\python\Lib\site-packages\cvxpy\expressions\expression.py:674: UserWarning: This use of ``*`` has resulted in matrix multiplication. Using ``*`` for matrix multiplication has been deprecated since CVXPY 1.1. Use ``*`` for matrix-scalar and vector-scalar multiplication. Use ``@`` for matrix-matrix and matrix-vector multiplication. Use ``multiply`` for elementwise multiplication. This code path has been hit 30 times so far. D:\python\Lib\site-packages\cvxpy\reductions\solvers\solving_chain_utils.py:41: UserWarning: The problem has an expression with dimension greater than 2. Defaulting to the SCIPY backend for canonicalization.
最新发布
05-25
### CVXPY 中矩阵乘法的正确实现方式 在 CVXPY 1.1 及以上版本中,`*` 操作符被重新定义为逐元素乘法(element-wise multiplication),而不是传统的矩阵乘法。因此,在涉及矩阵乘法的操作时,直接使用 `*` 将引发警告或错误。为了消除这些警告并提高代码的兼容性和性能,建议采用以下方法: #### 使用 '@' 运算符 CVXPY 支持 Python 的标准矩阵乘法运算符 `@`,该运算符能够高效地完成矩阵间的乘法操作。这是推荐的方式之一,因为它不仅语义清晰,而且与 NumPy 和 PyTorch 等库保持一致[^1]。 ```python import cvxpy as cp # 定义变量和参数 X = cp.Variable((3, 2)) A = cp.Parameter((2, 3), value=np.random.randn(2, 3)) # 正确使用 @ 实现矩阵乘法 expression = A @ X ``` 此代码片段展示了如何通过 `@` 来替代旧版中的 `*`,从而避免不必要的警告。 #### 使用 `cp.matmul` 除了 `@` 外,还可以显式调用 `cvxpy.matmul()` 函数来进行矩阵乘法。这种方式更加灵活,尤其适用于复杂表达式的构建场景[^1]。 ```python # 显式调用 matmul 方法 expression = cp.matmul(A, X) ``` 需要注意的是,无论是 `@` 还是 `cp.matmul`,都支持广播机制,这意味着当两个张量维度匹配时,它们会自动扩展以适应计算需求[^1]。 #### 避免误用 'multiply' 尽管 `np.multiply` 或者其对应的 CVXPY 版本可用于逐元素乘法,但它并不适合处理传统意义上的矩阵乘法问题。例如,下面的例子演示了两者的区别: ```python # 错误示范:试图用 multiply 替代矩阵乘法 C = np.array([[1, 2], [3, 4]]) D = np.array([[5, 6], [7, 8]]) wrong_result = np.multiply(C, D) # 结果是一个逐元素相乘后的数组 correct_result = C @ D # 执行真正的矩阵乘法 ``` 显然,只有后者才是正确的做法[^4]。 最后值得注意的一点在于输入数据结构的选择上——如果确认所有参与运算的数据均为二维形式,则可以直接选用效率更高的专用函数;但如果存在高维情况或者不确定具体形状的话,则应优先考虑那些具备广泛适用性的解决方案,比如前述提到过的两种主流途径[^3]。 ### 性能考量 从性能角度来看,`@` 和 `cp.matmul` 均经过高度优化,能够在大多数情况下提供最佳表现。然而实际应用过程中还需关注以下几个方面: - **稀疏性**:若待求解模型含有大量零值项,则需特别指定相应属性以便充分利用内存空间减少冗余计算; - **批量化处理能力**:现代硬件架构往往偏好批量作业模式,故设计算法阶段也应当考虑到这一点进而合理规划数据流走向。 综上所述,在升级至最新版 CVXPY 后遇到此类提示信息时,请果断切换到现代化接口上来满足规范要求的同时兼顾执行速度上的优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值