Search code examples
matlabsymbolic-math

Symbolic int results in deletion of main variable (MATLAB)


I am trying to do something like this:

syms x h4 t4 c13;
t = 0.6*sin(pi*x);
h1x = 0.5*(1 - t);
h0 = h1x;
h14x = -h4 -t4*(x - 0.5);
h24x = h4 + t4*(x - 0.5);
symvar(h14x)

which returns

ans =

[ h4, t4, x]

Then

u13x = (-4*int(h14x, x, 0, x) + c13)/h0
symvar(u13x)

returns

u13x =

-(c13 + 4*x*(h4 - t4/2) + 2*t4*x^2)/((3*sin(pi*x))/10 - 1/2)

ans =

[ c13, h4, t4, x]

and

p12x = -3*int(u13x, x, 0, x)
symvar(p12x)

which is

p12x =

-3*int(-(c13 + 4*x*(h4 - t4/2) + 2*t4*x^2)/((3*sin(pi*x))/10 - 1/2), x, 0, x)

ans =

[ c13, h4, t4 ]

As you can see from u13x where the variables were [h4, t4, c13, x], while integrating to p12x it got reduced to [h4, t4, c13] even though the integral limits are variable (in terms of x). Is it a bug? I can't seem to get by this weird behaviour. Is there a workaround?


Solution

  • Here are three possible workarounds (tested in R2015a).

    1. Use a symbolic function
    One option is to make the input that will be passed to sym/symvar a symfun in terms of x and then use the optional second argument to specify a finite number of variable to look for:

    syms x h4 t4 c13;
    t = 0.6*sin(pi*x);
    h1x = 0.5*(1 - t);
    h0 = h1x;
    h14x = -h4 -t4*(x - 0.5);
    u13x = (-4*int(h14x, x, 0, x) + c13)/h0
    p12x(x) = -3*int(u13x, x, 0, x) % Make symfun, function of x
    n = realmax;                    % 4 or greater to get all variables in this case
    symvar(p12x, n)                 % Second argument must be finite integer
    

    which returns the expected [ x, t4, h4, c13]. Just setting the second argument to a very large integer value seems to work.

    2. Convert expression to a string
    There are actually two versions of symvar. There is symvar for string inputs and sym/symvar, in the Symbolic Math toolbox, for symbolic expressions. The two forms apparently behave differently in this case. So, another workaround is to convert the equation with int to a character string with sym/char before passing it to symvar and then converting the output back to a vector of symbolic variables:

    syms x h4 t4 c13;
    t = 0.6*sin(pi*x);
    h1x = 0.5*(1 - t);
    h0 = h1x;
    h14x = -h4 -t4*(x - 0.5);
    u13x = (-4*int(h14x, x, 0, x) + c13)/h0
    p12x = -3*int(u13x, x, 0, x)
    sym(symvar(char(p12x))).'
    

    which also returns the expected [ c13, h4, t4, x] (note that order appears to be opposite of the first workaround above).

    3. Call MuPAD function from Matlab
    Lastly, you can call the MuPAD function indets that finds indeterminates in an expression.

    syms x h4 t4 c13;
    t = 0.6*sin(pi*x);
    h1x = 0.5*(1 - t);
    h0 = h1x;
    h14x = -h4 -t4*(x - 0.5);
    u13x = (-4*int(h14x, x, 0, x) + c13)/h0
    p12x = -3*int(u13x, x, 0, x)
    feval(symengine, 'x->indets(x) minus Type::ConstantIdents', p12x)
    

    which returns [ x, c13, h4, t4]. This will work if the input p12x is class sym or symfun. You can also use:

    evalin(symengine, ['indets(hold(' char(p12x) ')) minus Type::ConstantIdents'])
    

    The reason that sym/symvar doesn't work in your case is because it is based on freeIndets under the hood, which explicitly ignores free variables in functions like int.