如何在Matlab上编写符号表达式的`lhs()`或`rhs()`函数

如何在Matlab上编写符号表达式的`lhs()`或`rhs()`函数,matlab,symbolic-math,mupad,Matlab,Symbolic Math,Mupad,我在MATLAB中有一个符号表达式,带有=运算符,可以在solve()中使用。我想要的是将表达式的左侧和右侧分离为两个独立的符号表达式 例如: expr = sym('[1-x^2==2*y; 1+x^2==x+y]'); side1 = lhs(expr); % returns side1 = [1-x^2; 1+x^2]; 当然,我的表达式要复杂得多,它总是向量或矩阵形式 解决方案1 我可以使用MuPAD内置函数lhs(),但我想知道是否可以只使用MATLAB函数来实现这一点

我在
MATLAB
中有一个符号表达式,带有
=
运算符,可以在
solve()
中使用。我想要的是将表达式的左侧和右侧分离为两个独立的符号表达式

例如:

expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
side1 = lhs(expr);        % returns side1 = [1-x^2; 1+x^2];
当然,我的表达式要复杂得多,它总是向量或矩阵形式

解决方案1 我可以使用
MuPAD
内置函数
lhs()
,但我想知道是否可以只使用
MATLAB
函数来实现这一点,并且我想让它适用于表达式的向量,而不仅仅是一个值

这是我迄今为止所做的工作,正如预期的那样。也许结果填充可以通过使用
以某种方式进行矢量化,但我还没有设法让它工作

function [ r ] = lhs( expr )
%LHS Returns the left hand side an expression
%   LHS(sym('[1-x^2==2*y'; 1+x^2==x+y]')) = [1-x^2; 1+x^2]

  cmd = @(e)['lhs(',char(e),')'];
  [m,n] = size(expr);
  r = sym(zeros(m,n));
  for i=1:m
      for j=1:n
          r(i,j) = evalin(symengine, cmd(expr(i,j)));
      end
  end  
end

我在想正则表达式,这是我的尝试

假设您有一个符号表达式
expr
,例如:

expr = sym('[1-x^2==2*y; 1+x^2==x+y]')
由于不能假定它是标量表达式,因此第一步是将其拆分为子元素,并将每个子元素转换为字符串,如下所示:

C = arrayfun(@(n)char(expr(n)), 1:numel(expr), 'Uniform', false)
(我没有使用简单的
char(expr)
转换,因为它添加了
矩阵([…])
语法)

现在,我们使用正则表达式搜索和替换来提取LHS:

C = arrayfun(@(n)char(expr(n)), 1:numel(expr), 'Uniform', false)
C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$1')  %// $1 for lhs, $2 for rhs


以下是便于复制粘贴的
lhs
rhs
功能:

function y = lhs(x)
    C = arrayfun(@(n)char(x(n)), 1:numel(x), 'Uniform', false);
    C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$1');
    str = sprintf('%s,', C{:});
    y = reshape(sym(str(1:end - 1)), size(x));

function y = rhs(x)
    C = arrayfun(@(n)char(x(n)), 1:numel(x), 'Uniform', false);
    C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$2');
    str = sprintf('%s,', C{:});
    y = reshape(sym(str(1:end - 1)), size(x));
函数y=lhs(x)
C=arrayfun(@(n)char(x(n)),1:numel(x),“统一”,false);
C=regexprep(C,”([^>
请注意,这比EitanT的字符串操作更健壮,原因很简单:您的左手边和右手边本身可能包含等号。

从R2017a开始,使用“lhs”和“rhs”作为


+1:这是一个好问题。我很惊讶我只得到了这个问题的一个答案。该函数没有作用域到
expr
,因此
size(expr)
无效。我将其替换为
size(x)
我得到了一个错误。
维度必须是实非负的。
对不起,输入错误。那当然应该是
x
。我觉得奇怪的是,你在
大小(x)
上得到了一个错误。
x
你传递的是什么?
x=[xp_2==xp_1+qp_2*(rx*cos(th_1)-ry*sin(th_1))-thp_1*(cos(th_1)*+q_2)+sin(th_1)*(n_2_x+q_2*rx)),yp_2==yp_1+qp_2*(ry*cos(th_1)+rx*sin(th_1))+thp_1*(cos(th_1)*(n_2_x+q_2*rx)-sin(th_1)*(n_2_y+q_2*ry)),0=
并尝试
rhs(x)
噢,显然正则表达式中有一个错误,所以它偶尔会失败。现在应该已经修复了,请尝试一下。如果我像我需要的那样输入一个向量,我会得到一个错误:
error using mupadmex MuPAD命令中的error:Dimensions必须是实非负整数。sym/reformate(第35行)中的错误ySym=mupadmex('symobj::restrape',x.s,args{:});lhs2(第8行)中的错误r=restrape(sym(str(1:end-1)),大小(x))
也许吧,但我得到了
??未定义的函数或方法'children'作为'sym'类型的输入参数。
我必须在引入
sym/children
时进行搜索。大概是2012a左右吧?谢谢你的提示。我会在工作中检查并奖励问题,如果它有效的话。我当然可以就我的s的健壮性进行辩论解决方案,但你的绝对值得+1。@EitanT:我的意思不是不尊重你或你的代码——只是一些符号表达式的输出中包含
=
符号,这意味着打破文本表示需要大量工作,而你没有包括这些工作。此外,当表达式变大时,一个圆的tr根据我的经验,ip通过MATLAB字符串带来性能问题。符号数学工具箱愿望列表中还有其他内容吗?:)每个版本都添加了功能。请参阅。谢谢。我喜欢实时工作表,但我很恼火,我无法为变量输入希腊符号或unicode以显示漂亮的。如果您可以直接输入类似
'\gamma'=1
或更好的
γ=1
。在mupad中,您可以输入
'&gamma;=1
这一点你是对的。不幸的是,在MATLAB中,变量名不能有希腊字母。我看不到解决方法,但我会将你的反馈传递给你。拥有它肯定很好。很抱歉,这是一个合适的论坛,但MATLAB存在另一个问题(至少是早期版本)。如果我有一个存储在符号向量中的方程组(例如
expr=[2*x-y==1,x+3*y==2]
),并且我想求解它,我应该能够只键入
sol=solve(expr[x,y])
。我想现在我需要键入
sol=solve(expr(1),x,expr(2),y)
。也许它应该接受一个变量单元格,比如
subs
,但是具有快速形式
solve(expr,vars)
。命令
S=solve(expr,[xy])
可以与
S.x=5/7
S.y=3/7
一起工作。这是您所期望的吗?
function y = lhs(x)
    C = arrayfun(@(n)char(x(n)), 1:numel(x), 'Uniform', false);
    C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$1');
    str = sprintf('%s,', C{:});
    y = reshape(sym(str(1:end - 1)), size(x));

function y = rhs(x)
    C = arrayfun(@(n)char(x(n)), 1:numel(x), 'Uniform', false);
    C = regexprep(C, '([^><=]*)(?:[><=]*)(.*)', '$2');
    str = sprintf('%s,', C{:});
    y = reshape(sym(str(1:end - 1)), size(x));
expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
lr = children(expr);
lr{1}

ans =

[ 1 - x^2, 2*y]
syms x
expr = [1-x^2==2*y; 1+x^2==x+y];
lhsExpr = lhs(expr)
lhsExpr =
 1 - x^2
 x^2 + 1


rhsExpr = rhs(expr)
rhsExpr =
  2*y
 x + y