使用MuPAD查找非线性方程组的所有解

时间:2013-12-30 15:43:29

标签: matlab symbolic-math mupad

我的问题是,是否有一种在Matlab脚本中使用MuPAD函数的好方法。背景是我有一个问题,我需要找到一组非线性方程的所有解。之前的解决方案是在Matlab中使用solve,它适用于我的一些模拟(即一些输入T),但并非总是如此。所以我用以下方式使用MuPAD:

function ut1 = testMupadSolver(T)
% # Input T should be a vector of 15 elements

mupadCommand = ['numeric::polysysroots({' eq1(T) ' = 0,' ...
    eq2(T) '= 0},[u, v])'];
allSolutions = evalin(symengine, mupadCommand);
ut1 = allSolutions;

end

function strEq = eq1(T)
sT = @(x) ['(' num2str(T(x)) ')'];

strEq = [ '-' sT(13) '*u^4 + (4*' sT(15) '-2*' sT(10) '-' sT(11) '*v)*u^3 + (3*' ...
    sT(13) '-3*' sT(6) '+v*(3*' sT(14) '-2*' sT(7) ')-' sT(8) '*v^2)*u^2 + (2*' ...
    sT(10) '-4*' sT(1) '+v*(2*' sT(11) '-3*' sT(2) ')+v^2*(2*' sT(12) ' - 2*' ...
    sT(3) ')-' sT(4) '*v^3)*u + v*(' sT(7) '+' sT(8) '*v+' sT(9) '*v^2)+' sT(6)];

end

function strEq = eq2(T)
sT = @(x) ['(' num2str(T(x)) ')'];
strEq = ['(' sT(14) '-' sT(13) '*v)*u^3 + u^2*' '(' sT(11) '+(2*' sT(12) '-2*' sT(10) ...
    ')*v-' sT(11) '*v^2) + u*(' sT(7) '+v*(2*' sT(8) '-3*' sT(6) ')+v^2*(3*' sT(9) ...
    '-2*' sT(7) ') - ' sT(8) '*v^3) + v*(2*' sT(3) '-4*' sT(1) '+v*(3*' sT(4) ...
    '-3*' sT(2) ')+v^2*(4*' sT(5) ' - 2*' sT(3) ')-' sT(4) '*v^3)+' sT(2)];

end

我有两个问题:

1)为了使用MuPAD,我需要将方程式系统的两个方程重写为字符串,如上所示。有没有更好的方法来做到这一点,最好没有字符串步骤?

2)关于格式输出;当

T = [0 0 0 0 0 0 0 0 0 0 1 0 1 0 1];

输出是:

testMupadSolver(T)

ans =

matrix([[u], [v]]) in {matrix([[4.4780323328249527319374854327354], [0.21316518769990291263811232040432]]), matrix([[- 0.31088044854742790561428736573347 - 0.67937835289645431373983117422178*i], [1.1103383836576028262792542770062 + 0.39498445715599777249947213893789*i]]), matrix([[- 0.31088044854742790561428736573347 + 0.67937835289645431373983117422178*i], [1.1103383836576028262792542770062 - 0.39498445715599777249947213893789*i]]), matrix([[0.47897094942962218512261248590261], [-1.26776233072168360314707025141]]), matrix([[-0.83524238515971910583152318717102], [-0.66607962429342496204955062300669]])} union solvelib::VectorImageSet(matrix([[0], [z]]), z, C_)

MuPAD可以将解决方案作为一组向量或类似方式提供吗?为了使用上面的答案,我需要从该字符串集解决方案中挑选出解决方案。有一个聪明的方法来做到这一点?到目前为止,我的解决方案是找到我知道将在解决方案中出现的标志,例如'([['并选择下面的数字,这真的很难看,如果解决方案出于某种原因看起来有点不同于我所涵盖的案例不起作用。

修改

当我使用@horchler在下面的答案中建议的解决方案时,我得到与之前实现相同的解决方案。但对于某些情况(并非所有情况),需要更长的时间。例如。对于下面的T,下面建议的解决方案需要一分多钟,而使用evalin(我之前的实现)需要一秒钟。

T = [2.4336 1.4309 0.5471 0.0934 9.5838 -0.1013 -0.2573 2.4830 ...
     36.5464 0.4898 -0.5383 61.5723 1.7637 36.0816 11.8262]

新功能:

function ut1 = testMupadSolver(T)
% # Input T should be a vector of 15 elements
allSolutions = feval(symengine,'numeric::polysysroots', ...
    [eq1(T),eq2(T)],'[u,v]');
end
function eq = eq1(T)
syms u v
eq = -T(13)*u^4 + (4*T(15) - 2*T(10) - T(11)*v)*u^3 + (3*T(13) - 3*T(6) ...
    + v*(3*T(14) -2*T(7)) - T(8)*v^2)*u^2 + (2*T(10) - 4*T(1) + v*(2*T(11) ...
    - 3*T(2)) + v^2*(2*T(12) - 2*T(3)) - T(4)*v^3)*u + v*(T(7) + T(8)*v ...
    + T(9)*v^2) + T(6);
end


function eq = eq2(T)
syms u v
eq = (T(14) - T(13)*v)*u^3 + u^2*(T(11) + (2*T(12) - 2*T(10))*v ...
    - T(11)*v^2) + u*(T(7) + v*(2*T(8) - 3*T(6) ) + v^2*(3*T(9) - 2*T(7)) ...
    - T(8)*v^3) + v*(2*T(3) - 4*T(1) + v*(3*T(4) - 3*T(2)) + v^2*(4*T(5) ...
    - 2*T(3)) - T(4)*v^3) + T(2);
end

有充分理由说明为什么需要这么长时间吗?

1 个答案:

答案 0 :(得分:2)

首先,Matlab通过字符串命令与MuPAD通信,因此最终无法绕过字符串的使用。因为它是本机格式,如果你将大量数据传递给MuPAD,最好的方法是快速有效地将所有内容转换为字符串(sprintf通常是最好的)。但是,在您的情况下,我认为您可以使用feval代替evalin,这允许您传入常规的Matlab数据类型(在sym/feval下进行字符串转换并调用{{ 1}})。此方法在此MathWorks article中讨论。可以使用以下代码:

evalin

最后一个参数仍然需要是一个字符串(或省略),并且将T = [0 0 0 0 0 0 0 0 0 0 1 0 1 0 1]; syms u v; eq1 = -T(13)*u^4 + (4*T(15) - 2*T(10) - T(11)*v)*u^3 + (3*T(13) - 3*T(6) ... + v*(3*T(14) -2*T(7)) - T(8)*v^2)*u^2 + (2*T(10) - 4*T(1) + v*(2*T(11) ... - 3*T(2)) + v^2*(2*T(12) - 2*T(3)) - T(4)*v^3)*u + v*(T(7) + T(8)*v ... + T(9)*v^2) + T(6); eq2 = (T(14) - T(13)*v)*u^3 + u^2*(T(11) + (2*T(12) - 2*T(10))*v ... - T(11)*v^2) + u*(T(7) + v*(2*T(8) - 3*T(6) ) + v^2*(3*T(9) - 2*T(7)) ... - T(8)*v^3) + v*(2*T(3) - 4*T(1) + v*(3*T(4) - 3*T(2)) + v^2*(4*T(5) ... - 2*T(3)) - T(4)*v^3) + T(2); allSolutions = feval(symengine, 'numeric::polysysroots',[eq1,eq2],'[u,v]'); 添加到方程式中也不起作用,但零是隐含的。

对于第二个问题,numeric::polysysroots返回的结果非常不方便且不易使用。它是一组(DOM_SET)矩阵。我尝试使用coerce将结果转换为其他内容无效。我认为最好将输出转换为字符串(使用==0)并解析结果。我这样做是为了更简单的输出格式。我不确定它是否有用,但请随意查看我的sym2float,它只使用一些优化来处理符号矩阵(char部分输出你的输出)。

最后一件事。您的助手功能是否包含多余的括号?这似乎足够了

'matrix([[ ... ]])'

sT = @(x)num2str(T(x),17);

请注意,sT = @(x)sprintf('%.17g',T(x)); 默认情况下仅转换为四位小数。如果num2str始终为整数,则应使用int2str(或%d