【问题标题】:How to write a `lhs()` or `rhs()` function for symbolic expressions on Matlab如何在 Matlab 上为符号表达式编写 `lhs()` 或 `rhs()` 函数
【发布时间】:2013-01-22 15:36:17
【问题描述】:

我在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

【问题讨论】:

  • +1:这是个好问题。
  • 我很惊讶我只有一个答案。

标签: matlab symbolic-math mupad


【解决方案1】:

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

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

【讨论】:

  • 您的 Symbolic Math Toolbox 愿望清单上还有其他内容吗? :) 每个版本都添加了功能。请参阅release notes
  • 谢谢。我喜欢实时工作表,但我很生气我不能为变量输入希腊符号或 unicode 以显示漂亮。如果您可以直接输入'\gamma' = 1 或更好的γ = 1 之类的内容,请提供图像。在 mupad 中,您可以为此输入 'γ'=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,[x y])S.x = 5/7S.y = 3/7 一起使用。这是您的预期吗?
【解决方案2】:
expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
lr = children(expr);
lr{1}

ans =

[ 1 - x^2, 2*y]

请注意,这比 EitanT 的字符串操作更强大,原因很简单:您的左侧和右侧可能包含等号本身。

【讨论】:

  • 也许但我得到??? Undefined function or method 'children' for input arguments of type 'sym'.
  • sym/children 被引入时,我必须搜索。可能在 2012 年左右或类似的时间?
  • 感谢您的提示。我会在工作中检查并奖励问题是否有效。
  • 我当然可以争论我的解决方案的稳健性,但您的解决方案绝对值得 +1。
  • @EitanT:我的意思不是不尊重您或您的代码——只是一些符号表达式在其输出中包含= 符号,这意味着破坏文本表示需要大量工作,您正确地没有包括在内。此外,根据我的经验,当表达式变大时,通过 MATLAB 字符串往返会带来性能问题。
【解决方案3】:

我正在考虑正则表达式,所以这是我的尝试。

假设您有一个符号表达式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) 转换,因为它添加了matrix([[...]]) 语法)。

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

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

然后将元素串联回一个字符串,并将其转换为符号表达式:

str = sprintf('%s,', C{:})
result = reshape(sym(str(1:end - 1)), size(expr))

瞧。


这里是复制粘贴友好的 lhsrhs 函数:

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));

请注意,lhsrhs 之间的唯一区别是 regexprep 中的替换标记。
使用$1 提取左侧,使用$2 提取右侧。

【讨论】:

  • 该函数确实具有expr 的范围,因此size(expr) 无效。我将其替换为size(x),但出现错误。 Dimensions must be real nonnegative.
  • 抱歉,输入错误。那当然应该是x。我觉得很奇怪你收到size(x) 的错误...你在为x 传递什么?
  • x=[ xp_2 == xp_1 + qp_2*(rx*cos(th_1) - ry*sin(th_1)) - thp_1*(cos(th_1)*(n_2_y + q_2*ry) + 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 == 0] 并尝试rhs(x)
  • 哦,显然正则表达式有错误,所以偶尔会失败。现在应该已经修复了,请尝试一下。
  • 如果我输入一个我需要的向量,我会得到一个错误:Error using mupadmex Error in MuPAD command: Dimensions must be real nonnegative integers. Error in sym/reshape (line 35) ySym = mupadmex('symobj::reshape',x.s,args{:}); Error in lhs2 (line 8) r = reshape(sym(str(1:end - 1)), size(x));
猜你喜欢
  • 1970-01-01
  • 2023-02-09
  • 2015-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多