9

When I used an older version of Mathematica, CoefficientRules returned coefficients as entered, say x^2 +2x -4 y + 13., it returned {{2,0}->1,{1,0}->2,{0,1}->-4,{0,0}->13.} with all coefficients returned as integers except the last one.

I used this to identify non-valid (== non-integral) coefficients in my polynomial.

In version 13 of Mathematica, if I enter one coefficient as non-integral all other integer coefficients are returned as non-inetrgral as well.

I real want to have all coefficients in my polynomials returned as given.

Any suggestions?

Kent

kent
  • 139
  • 3
  • CoefficientRules[poly // Rationalize] – Bob Hanlon Jun 06 '22 at 18:42
  • @BobHanlon: I think the OP wants the coefficients to be returned as given, not all rationalized. In other words, the desired output is {2, 0} -> 1, {1, 0} -> 2, {0, 1} -> -4, {0, 0} -> 13.}. – Michael Seifert Jun 06 '22 at 19:01
  • @MichaelSeifert - Then ReplacePart[CoefficientRules[poly // Rationalize], -1 -> ({0, 0} -> (poly /. Thread[Variables[poly] -> 0]))] – Bob Hanlon Jun 06 '22 at 19:27
  • 1
    @BobHanlon: That doesn't look like it will work if any term other than the constant term is non-rational. But admittedly the OP only gave us the one use case. – Michael Seifert Jun 06 '22 at 19:29

3 Answers3

7

This seems to work, though the indexing is off by one compared to CoefficientRules:

expr = x^2 + 2 x - 4 y + 13.
result = Most[ArrayRules[CoefficientList[expr, {x, y}]]]
(* {{1, 1} -> 13., {1, 2} -> -4, {2, 1} -> 2, {3, 1} -> 1} *)

To regain the original indexing, you can apply the following command:

MapAt[# - 1 &, result, {All, 1}] 
(* {{0, 0} -> 13., {0, 1} -> -4, {1, 0} -> 2, {2, 0} -> 1} *)

The ordering of the results is also different; judicious application of SortBy can probably fix this if needed.

Michael Seifert
  • 15,208
  • 31
  • 68
4

Another way:

CoefficientRules[
  x^2 + 2 x - 4 y + 13. /. x_Real | x_Complex :> \[FormalA][x],
  {x, y}] /. \[FormalA][x_] :> x

(* {{2, 0} -> 1, {1, 0} -> 2, {0, 1} -> -4, {0, 0} -> 13.} *)

Michael E2
  • 235,386
  • 17
  • 334
  • 747
3

Here is a function which should reproduce your desired results for any polynomial.

coefficientRulesAlt[polynomial_] :=
 Module[{
   var, pows, lis,
   poly = polynomial},
  var = Variables[poly];
  pows = Table[{var[[i]], #[[i]]}, {i, Length[var]}] & /@ 
    Tuples[Table[ix, {ix, 0, #}] & /@ Exponent[poly, var]];
  lis = Table[
    Table[Last@pows[[j]][[i]], {i, Length[pows[[j]]]}] -> 
     Fold[Coefficient[#1, #2[[1]], #2[[2]]] &, poly, pows[[j]]], {j, 
     Length[pows]}];
  Reverse[If[Last[#] != 0, #, Nothing] & /@ lis]]

Input

coefficientRulesAlt[13. + 2 x + x^2 - 4 y]

Output

{{2, 0} -> 1, {1, 0} -> 2, {0, 1} -> -4, {0, 0} -> 13.}

Input

coefficientRulesAlt[126.357 + 2.1354 z + π*x^20*z^2 - 4 y]

Output

{{1, 0, 0} -> -4, {0, 2, 20} -> π, {0, 1, 0} -> 
  2.1354, {0, 0, 0} -> 126.357}
cphys
  • 161
  • 6
  • 1
    Great, this solves my problem for my coefficient check for my polynomials! – kent Jun 09 '22 at 11:01
  • It seems that the behaviour of CoeffcientRules changed sometime between version 10 and 13 of Mathematica. Why it was changed is unclear to me. Anybody? – kent Jun 09 '22 at 11:01