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,可以手动求解长而简单的方程,但我需要使用不同的长表达式多次重复该过程,因此自动化将非常有用,并可以防止最终的黑板错误。您能展示您的代码,包括求解调用吗?你有没有想过增加迭代次数,并指出方程需要求解哪个变量?太棒了!这正是我所做的,洛基