Question

I have a symbolic expression in MATLAB with a == operator that I can use in solve(). What I want is to separate out the left hand side and the right hand side of the expression into two separate symbolic expressions.

For example:

expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
side1 = lhs(expr);        % returns side1 = [1-x^2; 1+x^2];

of course my expressions are far more complicated, and it is always vector or matrix form.

Workaround 1 I can use the MuPAD built-in function lhs() but I wanted to know if it possible to do this using only MATLAB functions and I want to make it work for vectors of expressions and not just one value.

This is what I have so far that works as expected. Maybe the result filling can be vectorized somehow by using : but I have not manage to get it working.

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
Was it helpful?

Solution

Starting R2017a, use "lhs" and "rhs" as

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

OTHER TIPS

expr = sym('[1-x^2==2*y; 1+x^2==x+y]');
lr = children(expr);
lr{1}

ans =

[ 1 - x^2, 2*y]

Note that this is more robust than EitanT's string manipulation for a simple reason: Your left- and right-hand sides may contain equals-signs themselves.

I'm thinking regular expressions, so here's my shot at this.

Let's say you have a symbolic expression expr, for instance:

expr = sym('[1-x^2==2*y; 1+x^2==x+y]')

Since it cannot be assumed to be a scalar expression, the first step would be splitting it into sub-elements, and converting each one to a string, like so:

C = arrayfun(@(n)char(expr(n)), 1:numel(expr), 'Uniform', false)

(I'm not using a simple char(expr) conversion because it adds the matrix([[...]]) syntax).

Now we use a regular expression search-and-replace to extract the LHS:

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

And then concatenate the elements back into a string and convert it into a symbolic expression:

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

Voila.


Here are copy-paste friendly lhs and rhs functions:

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

Note that the only difference between lhs and rhs are the replaced tokens in regexprep.
Using $1 extracts the left-hand side, and using $2 extracts the right-hand side.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top