7

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?

Theodore Norvell
  • 15,366
  • 6
  • 31
  • 45

2 Answers2

7

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]
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

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.

Theodore Norvell
  • 15,366
  • 6
  • 31
  • 45
  • I asked the wrong question! It turns out that the the functions are *affine* with respect to `k`, not linear. It's easy to modify this answer to get the constant terms as well. Search for a 1 in the `tx` vector. If there is one, the corresponding item in `cx` is the constant term. If not, the constant term is zero. – Theodore Norvell Dec 18 '18 at 18:43
  • 1
    What about `diff(N,k1)`? – rahnema1 Dec 19 '18 at 04:42