Search code examples
matlabsymbolic-math

matlab: creating a symbolic vector


I am trying to create a function using the symbolic toolbox in matlab. I have been having trouble creating a symbolic vector (not a vector of symbolic variables). Do you guys know a way to do this without creating and editing a text-like matlab function file in your path?

  • *After creating the symbolic variables and all I use 'matlabFunction' to create and save the function.

Example:

Function:

function f=test1(x,a) {
   f=x(1)/a(1)+x(2)/a(2);
}

Code:

a = sym('a', [1 2]);
x = sym('x', [1 2]);
% f(x, a) = sym('f(x, a)');
r=x(1)/a(1)+x(2)/a(2);
% f(x,a)=r;
% handle=matlabFunction(f(x,a),'file','test1');
handle=matlabFunction(r,'file','test1');
  • The problem is that the code seen above creates a function with the set of input arguments (x1, x2, a1, a2) instead of (x,a) and I can't change the form of input arguments, it must be uniform.
  • In reality I am trying to write a function that will create a polynomial of specified degree and save it to the path so I could use 'eval' with it (which doesn't support polyval), but it will probably be useful for more.

Solution

  • Try:

    >> x = sym('x',[1 2])
    x =
    [ x1, x2]
    
    >> x(1)
    ans =
    x1
    
    >> x(2)
    ans =
    x2
    
    >> whos x
      Name      Size            Bytes  Class    Attributes
    
      x         1x2               112  sym      
    

    This is similar to writing:

    >> syms a1 a2
    >> a = [a1 a2]
    

    EDIT:

    First we build an expression from the symbolic variables:

    a = sym('a', [1 2]);
    x = sym('x', [1 2]);
    expr = x(1)/a(1)+x(2)/a(2);
    

    Next we convert it to a regular MATLAB function:

    fh = matlabFunction(expr, 'file','test1', 'vars',{a,x});
    

    The generated function is:

    function expr = test1(in1,in2)
        a1 = in1(:,1);
        a2 = in1(:,2);
        x1 = in2(:,1);
        x2 = in2(:,2);
        expr = x1./a1+x2./a2;
    end
    

    Initially I was thinking of using regular expressions to fix the function handle generated. This is a much dirtier hack, so I recommend using the previous approach instead:

    % convert to a function handle as string
    fh = matlabFunction(expr);
    str = char(fh);
    
    % separate the header from the body of the function handle
    T = regexp(char(fh), '@\((.*)\)(.*)', 'tokens', 'once');
    [args,body] = deal(T{:});
    
    % extract the name of the unique arguments (without the index number)
    args = regexp(args, '(\w+)\d+', 'tokens');
    args = unique([args{:}], 'stable');
    
    % convert arguments from: x1 into x(1)
    r = sprintf('%s|', args{:}); r = r(1:end-1);
    body = regexprep(body, ['(' r ')(\d+)'], '$1($2)');
    
    % build the arguments list of the new function: @(a,b,c)
    head = sprintf('%s,', args{:}); head = head(1:end-1);
    
    % put things back together to form a function handle
    f = str2func(['@(' head ') ' body])
    

    The resulting function handle:

    >> f
    f = 
        @(a,x)x(1)./a(1)+x(2)./a(2)