7
$\begingroup$

Test cases:

SeedRandom[0]
rand = RandomInteger[{-5, 5}, {5, 6}]
poly = rand.{x^2, x y, y^2, x, y, 1}

res1 = MonomialList[#, {x, y}, "DegreeLexicographic"] /. x | y -> 1 & /@ poly

res2 = CoefficientRules[#, {x, y}, "DegreeLexicographic"][[All, 2]] & /@ poly

res1 == rand
res2 == rand

{{5, 2, -5, 3, -3, -4}, {0, 3, -5, 1, 2, 5}, {-3, -4, -5, 1, -4, -3}, {5, 5, 3, 5, 1, 5}, {0, 0, 3, -1, 0, 4}}

{-4 + 3 x + 5 x^2 - 3 y + 2 x y - 5 y^2, 5 + x + 2 y + 3 x y - 5 y^2, -3 + x - 3 x^2 - 4 y - 4 x y - 5 y^2, 5 + 5 x + 5 x^2 + y + 5 x y + 3 y^2, 4 - x + 3 y^2}

{{5, 2, -5, 3, -3, -4}, {3, -5, 1, 2, 5}, {-3, -4, -5, 1, -4, -3}, {5, 5, 3, 5, 1, 5}, {3, -1, 4}}

{{5, 2, -5, 3, -3, -4}, {3, -5, 1, 2, 5}, {-3, -4, -5, 1, -4, -3}, {5, 5, 3, 5, 1, 5}, {3, -1, 4}}

False

False

When one of the coefficients is zero, I want to get 0, not a missing entry.

$\endgroup$
2
  • 1
    $\begingroup$ Are you only interested in quadratic polynomials? $\endgroup$
    – Carl Woll
    Jun 4, 2018 at 13:06
  • $\begingroup$ @CarlWoll If it can be generalized would be better. $\endgroup$
    – matrix42
    Jun 5, 2018 at 3:49

4 Answers 4

5
$\begingroup$

CoefficientArrays come to mind, but it needs some tweaking. The below solutions work for polynomials of order $2$.

Demonstration

{m0, m1, m2} = CoefficientArrays[poly[[1]], {x, y}] // Normal

{-4, {3, -3}, {{5, 2}, {0, -5}}}

We want upper-right triangular elements of m2:

Flatten@Table[m2[[i, i ;;]], {i, 1, Length@m2}]

{5, 2, -5}

Make it a function:

RU[m_] := Flatten@Table[m[[i, i ;;]], {i, 1, Length@m}]

and Join it with m1 and m0:

RU[m2]~Join~m1~Join~{m0}

{5, 2, -5, 3, -3, -4}

Function

Clear@RU

coeff[pol_] := 
 Block[{ca = CoefficientArrays[pol, {x, y}] // Normal // Reverse, RU},
   RU[m_] := Flatten@Table[m[[i, i ;;]], {i, 1, Length@m}]; 
  RU[First@ca]~Join~Flatten@Rest@ca]

(coeff /@ poly) == rand

True

The function coeff gives the coefficients in the exact same order as the OP requested.

Three variables

However, a re-arrangement of the terms will make the computations easier:

SeedRandom[0]
rand3 = RandomInteger[{-5, 5}, {3, 10}]
poly3 = rand3.{x^2, y^2, z^2, x y, y z, x z, x, y, z, 1};

{{5, 2, -5, 3, -3, -4, 0, 3, -5, 1}, {2, 5, -3, -4, -5, 1, -4, -3, 5, 5}, {3, 5, 1, 5, 0, 0, 3, -1, 0, 4}}

So here squares come first, then mixed terms, first order terms, and the free term.

{m0, m1, m2} = CoefficientArrays[poly3[[1]], {x, y, z}] // Normal

{1, {0, 3, -5}, {{5, 3, -4}, {0, 2, -3}, {0, 0, -5}}}

Then

Flatten[Table[Diagonal[m2, k], {k, 0, 2}]]~Join~m1~Join~{m0}

{5, 2, -5, 3, -3, -4, 0, 3, -5, 1}

and

% == rand3[[1]]

True

The same line of reasoning should apply to any number of variables, hence

N variables

coeffN = Module[{ca = CoefficientArrays[#, Variables@#] // Normal},
   Flatten[Table[Diagonal[ca[[3]], k], {k, 0, 2}]]~Join~ca[[2]]~Join~{ca[[1]]}
    ] &;

E.g.

(coeffN /@ poly3) == rand3

True

$\endgroup$
0
5
$\begingroup$

You can also use CoefficientList as follows:

Flatten[Table[Diagonal[#, -i], {i , 0, Length[#[[1]]] - 1}]] & /@ 
  PadLeft[Reverse /@ CoefficientList[poly, {x, y}]]

{{5, 2, -5, 3, -3, -4},
{0, 3, -5, 1, 2, 5},
{-3, -4, -5, 1, -4, -3},
{5, 5, 3, 5, 1, 5},
{0, 0, 3, -1, 0, 4}}

% == rand

True

For arbitrary polynomials in two variables, we can define a function

ClearAll[dlexCL]
dlexCL = Module[{cl = Reverse @ CoefficientList[#, Variables[#]]}, Flatten @ 
 Table[Diagonal[PadLeft[cl, {#, #}&@Length@cl[[1]]], -i], {i, 0, Length@cl[[1]] - 1}]]&;

dlexCL /@ poly == rand

True

dlexCL[1 + x^2 + 3 x^3 y + 2 y^4, {x, y}]

{0, 3, 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}

$\endgroup$
3
$\begingroup$

I do not understand your code, I am just answering the title of your post:

Given ax^2+bxy+cy^2+dx+ey+f, what is the best way to get {a,b,c,d,e,f}?

expr = a x^2 + b x y + c y^2 + d x + e y + f;
r = Flatten[CoefficientList[expr, {x, y}]]
DeleteCases[r, 0]

Mathematica graphics

$\endgroup$
0
$\begingroup$

I find a combination of Series and LogicalExpand useful for this sort of problem:

pattern = a x^2 + b x y + c y^2 + d x + e y + f;

vars = {a, b, c, d, e, f};

res = 
  vars /. Flatten[
      Solve[LogicalExpand[Series[pattern == #, {x, 0, 2}, {y, 0, 2}]],
        vars]] & /@ poly;

res == rand
(* True *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.