我正在尝试编写一个从用户接受系统变量的Matlab程序,但是有多个变量而不是系统参数。具体而言,三个方程中的六个变量:
w - d - M = 0
l - d - T = 0
N - T + M = 0
这可以用矩阵形式表示为A*x=0
其中
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
x = [w l N d T M]';
我希望能够在给定已知变量子集的情况下解决该系统。例如,如果用户提供d
,T
,M
,则系统可以轻松解决其他三个变量。如果用户提供w
,N
,M
,那么它就会成为可解决的3自由度系统。等等。 (如果用户超出或者指定了系统,那么当然可能会产生错误。)
鉴于这些组合中的任何一个,(先验的)使用矩阵代数来计算未知量是很简单的。但我不知道如何解决一般情况,除了使用符号工具箱(出于兼容性原因,我不愿意这样做)。
当我开始使用这种方法时,我认为这一步很容易,但我的线性代数是生锈的;我错过了一些简单的东西吗?
答案 0 :(得分:4)
首先,让x
成为未知值为NaN
的向量。这允许您使用ISNAN来查找未知数的缺失。如果仅为用户指定的术语计算A*x
,则会为您提供一列常量b。将这些常数带到等式的右边,你有一个A*x = -b
形式的等式。
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
idx = ~isnan(x);
b = A(:,idx)*x(idx); % user provided constants
z = A(:,~idx)\(-b); % solution of Ax = -b
x(~idx) = z;
例如,使用输入x = [NaN NaN NaN 1 1 1]'
,您会得到结果[2 2 0 1 1 1]'
。这使用MLDIVIDE,我对线性代数不够精通,无法知道PINV或其他更好的东西。
答案 1 :(得分:3)
给定线性系统
A = [1 0 0 -1 0 -1;
0 1 0 -1 -1 0;
0 0 1 0 -1 1];
A*x = 0
x的元素被标识为:
x = [w l N d T M]';
现在,假设{d,T,M}具有已知的固定值。我们需要的是x中这些元素的索引。我们已经选择了x的第4,第5和第6个元素。
known_idx = [4 5 6];
unknown_idx = setdiff(1:6,known_idx);
现在,让我为这些已知变量挑选一些任意数字。
xknown = [1; -3; 7.5];
我们将A分为两个子矩阵,对应于已知和未知变量。
Aknown = A(:,known_idx);
Aunknown = A(:,unknown_idx);
现在,将已知值移到相等的右侧,然后求解。看到Aknown是一个3x3矩阵,所以问题(希望)很好。
xunknown = Aunknown\(-Aknown*xknown)
xunknown =
-8.5
2
10.5
将所有内容合并到最终解决方案中。
x = zeros(6,1);
x(known_idx) = xknown;
x(unknown_idx) = xunknown;
x =
-8.5
2
10.5
1
-3
7.5
请注意,我已将这一切扩展为几行,以更清楚地显示正在发生的事情。但是我可以用一两行代码完成所有这些工作,我想要简约。
最后,看看我选择了其他一些数字作为知识,例如{l,d,T},那么得到的系统将是单数。所以你必须注意那个事件。对Aunknown等级的测试可能有助于解决问题。或者您可以选择使用pinv来构建解决方案。
答案 2 :(得分:0)
方程组是固定的吗?如果将三个方程中存在的变量存储在每个等式的列表中,该怎么办:
(w, d, M)
(l, d, T)
(N, T, M)
然后您获得用户输入,您可以计算每个等式中给出的变量数量:
User input: w, N, M
Given variables:
(w, d, M) -> 2
(l, d, T) -> 0
(N, T, M) -> 1
这可以从第一个等式中给你d
。因此,您最终会得到两个包含两个变量的方程式,并且您知道必须解决的方程式系统。
对于单个方程组,它基本上是您自己的简单符号求解器。