Variables Matlab:从符号表达式和/或系统中查找特定变量
我有一个由三个符号方程组成的系统:Variables Matlab:从符号表达式和/或系统中查找特定变量,variables,matlab,equation,symbolic-math,Variables,Matlab,Equation,Symbolic Math,我有一个由三个符号方程组成的系统: (1) Ua = (Un*Ga -ia -(U2 -Ug2)*G3)/Ga; (2) U2 = (Ug2*G3 -(Uc2m - Ua)*Ca*Fs)/(Ca*Fs + G3); (3) Ug2 = ((Ua -Uc2m)*Ca*Fs* G3 -ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3); 在(2)和(1)中的(3)替换之后,然后在(1)中的(2)替换之后,我得到(1)如下: Ua = (
(1) Ua = (Un*Ga -ia -(U2 -Ug2)*G3)/Ga;
(2) U2 = (Ug2*G3 -(Uc2m - Ua)*Ca*Fs)/(Ca*Fs + G3);
(3) Ug2 = ((Ua -Uc2m)*Ca*Fs* G3 -ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3);
在(2)和(1)中的(3)替换之后,然后在(1)中的(2)替换之后,我得到(1)如下:
Ua = (Un*Ga -ia -((((Ua -Uc2m)*Ca*Fs* G3 -ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3)*G3 -(Uc2m - Ua)*Ca*Fs)/(Ca*Fs + G3) -((Ua -Uc2m)*Ca*Fs* G3 -ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3))*G3)/Ga;
Ua
同时出现在左侧和右侧构件上。是否有方法(使用Matlab或任何其他工具)来:
Ua
的表达式直观地说,我会说只做
solve(expr1,expr2,expr3,'Ua')
,但这似乎不起作用(至少在R2010a上是这样)
所以我被黑客攻击了。现在,我不是一个象征性的工具箱工人,所以很可能有一个“更好”的方法来做到这一点。然而,以下函数回答了您的两个问题:
function solution = solveFor(exprs, var)
%// Split the equations up into the RHS and LHS
C = regexp(expr, '\s*=\s*', 'split');
C = cat(1, C{:});
%// The equation we're solving for
kk = find(strcmp(C(:,1), var));
%// Substitute every expression into every other expression
for ii = 1:size(C,1)
if ii==kk, continue; end
for jj = 1:size(C,1)
if jj==ii, continue; end
C{jj,2} = regexprep(C{jj,2}, C{ii,1}, C{ii,2});
end
end
%// Solve for the requested variable & simplify
solution = simplify(solve([C{kk,1} '=' C{kk,2}], C{kk,1}));
end
这样使用:
>> expr{1} = 'Ua = (Un*Ga -ia -(U2 -Ug2)*G3)/Ga';
>> expr{2} = 'U2 = (Ug2*G3 -(Uc2m - Ua)*Ca*Fs)/(Ca*Fs + G3)';
>> expr{3} = 'Ug2 = ((Ua -Uc2m)*Ca*Fs*G3 - ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3)';
>> Ua = solveFor(expr, 'Ua')
Ua =
-(G3*Gg2*ia - G3*Ga*Gg2*Un + Ca*Fs*G3*ia + Ca*Fs*G3*ig2 + Ca*Fs*Gg2*ia - Ca*Fs*G3*Gg2*Uc2m - Ca*Fs*G3*Ga*Un - Ca*Fs*Ga*Gg2*Un)/(G3*Ga*Gg2 + Ca*Fs*G3*Ga + Ca*Fs*G3*Gg2 + Ca*Fs*Ga*Gg2)
明显的局限性:
- 所有方程式必须采用上述格式,例如,
“单变量=表达式”
- 方程式必须以字符串形式给出,因此不能是其他smybolic运算的结果(尽管使用
顶部会取消该限制)expr=cellfun(@char,expr,'UniformOutput',false);
solve
的调用具有以下语法:
S = solve(expr{:}, 'Ua,U2,Ug2');
因此,要使流程自动化,您可以将上述函数修改为以下更简单的形式:
function solution = solveFor(exprs, var)
%// Syms or strings?
if ~iscellstr(exprs) && all(cellfun('isclass', exprs, 'sym'))
exprs = cellfun(@char, expr, 'UniformOutput', false);
else
error(...);
end
%// Split the equations up into the RHS and LHS
C = regexp(expr, '\s*=\s*', 'split');
C = cat(1, C{:});
%// Solve for the requested variables
vars = cellfun(@(x)[x ','], C(:,1), 'UniformOutput', false);
vars = [vars{:}];
solution = solve(expr{:}, vars(1:end-1));
%// Extract desired solution
solution = simplify(solution.(var));
end
直观地说,我会说只做
solve(expr1,expr2,expr3,'Ua')
,但这似乎不起作用(至少在R2010a上是这样)
所以我被黑客攻击了。现在,我不是一个象征性的工具箱工人,所以很可能有一个“更好”的方法来做到这一点。然而,以下函数回答了您的两个问题:
function solution = solveFor(exprs, var)
%// Split the equations up into the RHS and LHS
C = regexp(expr, '\s*=\s*', 'split');
C = cat(1, C{:});
%// The equation we're solving for
kk = find(strcmp(C(:,1), var));
%// Substitute every expression into every other expression
for ii = 1:size(C,1)
if ii==kk, continue; end
for jj = 1:size(C,1)
if jj==ii, continue; end
C{jj,2} = regexprep(C{jj,2}, C{ii,1}, C{ii,2});
end
end
%// Solve for the requested variable & simplify
solution = simplify(solve([C{kk,1} '=' C{kk,2}], C{kk,1}));
end
这样使用:
>> expr{1} = 'Ua = (Un*Ga -ia -(U2 -Ug2)*G3)/Ga';
>> expr{2} = 'U2 = (Ug2*G3 -(Uc2m - Ua)*Ca*Fs)/(Ca*Fs + G3)';
>> expr{3} = 'Ug2 = ((Ua -Uc2m)*Ca*Fs*G3 - ig2*(Ca*Fs + G3)) / ((G3 + Gg2)*(Ca*Fs + G3) - G3*G3)';
>> Ua = solveFor(expr, 'Ua')
Ua =
-(G3*Gg2*ia - G3*Ga*Gg2*Un + Ca*Fs*G3*ia + Ca*Fs*G3*ig2 + Ca*Fs*Gg2*ia - Ca*Fs*G3*Gg2*Uc2m - Ca*Fs*G3*Ga*Un - Ca*Fs*Ga*Gg2*Un)/(G3*Ga*Gg2 + Ca*Fs*G3*Ga + Ca*Fs*G3*Gg2 + Ca*Fs*Ga*Gg2)
明显的局限性:
- 所有方程式必须采用上述格式,例如,
“单变量=表达式”
- 方程式必须以字符串形式给出,因此不能是其他smybolic运算的结果(尽管使用
顶部会取消该限制)expr=cellfun(@char,expr,'UniformOutput',false);
solve
的调用具有以下语法:
S = solve(expr{:}, 'Ua,U2,Ug2');
因此,要使流程自动化,您可以将上述函数修改为以下更简单的形式:
function solution = solveFor(exprs, var)
%// Syms or strings?
if ~iscellstr(exprs) && all(cellfun('isclass', exprs, 'sym'))
exprs = cellfun(@char, expr, 'UniformOutput', false);
else
error(...);
end
%// Split the equations up into the RHS and LHS
C = regexp(expr, '\s*=\s*', 'split');
C = cat(1, C{:});
%// Solve for the requested variables
vars = cellfun(@(x)[x ','], C(:,1), 'UniformOutput', false);
vars = [vars{:}];
solution = solve(expr{:}, vars(1:end-1));
%// Extract desired solution
solution = simplify(solution.(var));
end
我不确定在这种情况下@RodyOldenhuis的所有努力都是必要的。只需正确使用
solve
。当您提供N个方程式时,通常最好要求它为您自己选择的N个变量求解(不指定任何变量名称):
然后s.Ua
返回
-(G3*Gg2*ia - G3*Ga*Gg2*Un + Ca*Fs*G3*ia + Ca*Fs*G3*ig2 + Ca*Fs*Gg2*ia - Ca*Fs*G3*Gg2*Uc2m - Ca*Fs*G3*Ga*Un - Ca*Fs*Ga*Gg2*Un)/(G3*Ga*Gg2 + Ca*Fs*G3*Ga + Ca*Fs*G3*Gg2 + Ca*Fs*Ga*Gg2)
不要错误地将Ua
、U2
和Ug2
作为向量传递到solve
(我相信,除非您使用的是R2015a+)
这也可以使用旧的基于字符串的技术(如果需要,可以用单个字符串输入替换单元格数组):
这适用于R2013a和R2015a。我不知道旧版本是否能处理这个问题。我不确定@RodyOldenhuis在这种情况下需要付出所有的努力。只需正确使用
solve
。当您提供N个方程式时,通常最好要求它为您自己选择的N个变量求解(不指定任何变量名称):
然后s.Ua
返回
-(G3*Gg2*ia - G3*Ga*Gg2*Un + Ca*Fs*G3*ia + Ca*Fs*G3*ig2 + Ca*Fs*Gg2*ia - Ca*Fs*G3*Gg2*Uc2m - Ca*Fs*G3*Ga*Un - Ca*Fs*Ga*Gg2*Un)/(G3*Ga*Gg2 + Ca*Fs*G3*Ga + Ca*Fs*G3*Gg2 + Ca*Fs*Ga*Gg2)
不要错误地将Ua
、U2
和Ug2
作为向量传递到solve
(我相信,除非您使用的是R2015a+)
这也可以使用旧的基于字符串的技术(如果需要,可以用单个字符串输入替换单元格数组):
这适用于R2013a和R2015a。我不知道旧版本是否可以处理此问题。谢谢您的建议。我做了替换,得到了长(1')表达式,现在我想简化(1'),这样右边就没有Ua,只有参数。不确定这是否有用,但您是否检查了
doc simplify
?你能在没有matlab的情况下得到你喜欢的结果吗?谢谢,simplify非常有用,但它给了我另一个扩展表达式,与我的表达式类似,当然更紧凑,但它是另一个f(Ua)。我想找的是一种方法,取一个类似“ax+(b+cx)/(d+e)”的表达式,得到“x=f(a,b,c,d)”。如果不使用matlab,可以手动求解长而简单的方程,但我需要使用不同的长表达式多次重复该过程,因此自动化将非常有用,并可以防止最终的黑板错误。您能展示您的代码,包括求解调用吗?您是否考虑过增加迭代次数并指出方程需要求解的变量?谢谢您的建议。我做了替换,得到了长(1')表达式,现在我想简化(1'),这样右边就没有Ua,只有参数。不确定这是否有用,但您是否检查了doc simplify
?你能在没有matlab的情况下得到你喜欢的结果吗?谢谢,simplify非常有用,但它给了我另一个扩展表达式,与我的表达式类似,当然更紧凑,但它是另一个f(Ua)。我想找的是一种方法,取一个类似“ax+(b+cx)/(d+e)”的表达式,得到“x=f(a,b,c,d)”。如果不使用matlab,可以手动求解长而简单的方程,但我需要使用不同的长表达式多次重复该过程,因此自动化将非常有用,并可以防止最终的黑板错误。您能展示您的代码,包括求解调用吗?你有没有想过增加迭代次数,并指出方程需要求解哪个变量?太棒了!这正是我所做的,洛基