7
votes

Suppose I have a column vector of formulae like this

N =

 4*k2 + 5*k3 + k1*x
 7*k2 + 8*k3 + k1*y

and a column vector of symbolic variables like this

k =

 k1
 k2
 k3

The formulae are linear with respect to k. I'd like to find a matrix M such that M*k equals N.

I can do this with N/k. However, that gives

[ (4*k2 + 5*k3 + k1*x)/k1, 0, 0]
[ (7*k2 + 8*k3 + k1*y)/k1, 0, 0]

which is correct, but not what I want. What I want is the matrix

 x     4     5
 y     7     8

which seems to me the simplest answer in that it involves no variables from k.

How do I convince Matlab to factor out the specified variables from a formula or a vector of formulae?

2
Here's a solution from Matlab Answers mathworks.com/matlabcentral/answers/…Theodore Norvell

2 Answers

7
votes

You can use coeffs, specifically the form

C = coeffs(p,vars) returns coefficients of the multivariate polynomial p with respect to the variables vars.

Since the first input needs to be a polynomial, you need to pass each component of N:

coeffs(N(1), k)
coeffs(N(2), k)

Or use a loop and store all results in a symbolic array:

result = sym('result', [numel(N) numel(k)]); % create symbolic array
for m = 1:numel(N)
    result(m,:) = coeffs(N(m), k);
end

In your example, this gives

result =
[ 5, 4, x]
[ 8, 7, y]
1
votes

Based on @LuisMendo's answer, I used coeffs. But there are a couple of problems with coeffs. The first is that its result doesn't include any coefficients that are 0. The second is that it doesn't seem to guarantee that the coefficients are ordered the same way as the variables in its second argument. I came up with the following function to replace coeffs.

Luckily coeffs returns a second result that lists the variables associated with each item in the first result. (It's more complicated if the formula is not linear.)

function m = factorFormula(f, v )
    % Pre: f is a 1x1 sym representing a
    %      linear function of the variables in v.
    % Pre: v is a column vector of variables
    % Post: m is a row vector such that m*v equals f
    %       and the formulas in m do not contain the 
    %       variables in v
    [cx,tx] = coeffs(f,v)
    n = size(v,1)
    m = sym(zeros(1,n))
    for i = 1:n
        j = find(tx==v(i))
        if size(j,2) == 1
            m(i) = cx(j)
        end
    end
end

This only works for one formula, but it can be extended to a vector using the loop in @LuisMendo's answer or this equivalent expression in @Sanchises comment there.

cell2sym(arrayfun( @(f)factorFormula(f,k),N,'UniformOutput',false ) )

I hope there is a better answer than this.