18
$\begingroup$

I can't believe this hasn't been asked before but I can't find anything.

Is there a way to convince Simplify or FullSimplify to extract common factors from matrices as it does from sums?

  • Exhibit A:

    {a/(2 c), b/(2 c), d/(2 c), e/(2 c)} // FullSimplify // FullSimplify
    

    gives

    {a/(2 c), b/(2 c), d/(2 c), e/(2 c)}
    

    In reality, I have a 2x2 matrix, but the result is effectively the same. A solution to my problem should ideally not depend on the dimensions/layout of the (potentially nested) list.

  • Exhibit B:

    a/(2 c) + b/(2 c) + d/(2 c) + e/(2 c) // FullSimplify
    

    gives

    (a + b + d + e)/(2 c)
    

I did see this related question, but I'm just asking about rearranging, I don't actually need access to the polynomial GDC in a separate variable or anything, so I was wondering if this was possible with Simplify or FullSimplify somehow.

$\endgroup$
9
  • $\begingroup$ {a,b,c} x is not a "stable form", it would immediately evaluate to {a x, b x, c x}. The question is interesting, I'm just mentioning that it's not possible to keep the expression in this form. You'd have to store {a,b,c} and x separately. $\endgroup$
    – Szabolcs
    Commented Jan 4, 2015 at 17:48
  • $\begingroup$ @Szabolcs Could you link me to some background reading about "stable forms"? $\endgroup$ Commented Jan 4, 2015 at 17:49
  • $\begingroup$ I just made that term up, you won't find much by searching for it. All I meant to say is that it evaluates further immediately. A similar example would be x+x, which evaluates immediately to 2x, or Sin[Pi] which evaluates to 0. $\endgroup$
    – Szabolcs
    Commented Jan 4, 2015 at 17:51
  • $\begingroup$ @Szabolcs I see. I'd still be interested, what's going on under the hood. But I guess that means my only option is indeed to flatten the input and feed it to PolynomialGDC. Feel free to close as duplicate. $\endgroup$ Commented Jan 4, 2015 at 17:52
  • $\begingroup$ You can actually keep it in that form using Hold[{a, b} x] or HoldForm[{a,b} x], but held expressions aren't very suitable for algebraic manipulation. HoldForm is useful though for just displaying the expression in certain form that is easier for us humans to parse. $\endgroup$
    – Szabolcs
    Commented Jan 4, 2015 at 17:55

3 Answers 3

8
$\begingroup$

A toy approach is as follows:

 FactorizeCommonFactor[tensor_?TensorQ] := 
  Block[{GCDListv, cfactor, tenfact, tenfactmf, facten},
   cfactor := PolynomialGCD @@ Flatten@tensor;
   tenfact := (1/cfactor)*tensor;
   tenfactmf := MatrixForm[tenfact];
   Piecewise[{{Return[{"Common Factor" -> cfactor, tenfact, 
        Inactivate[cfactor*tenfactmf]}], 
      cfactor =!= 1}, {Print[
       "The tensor cannot be expressed as a multiple of another
tensor"], cfactor === 1}}];
   ];

Test:

enter image description here

$\endgroup$
6
$\begingroup$

I am not seriously proposing this as a solution but it was fun to play with.

Block[{Plus},
  Simplify[
    Plus @@ {a/(2 c), b/(2 c), d/(2 c), e/(2 c)}
  ] /. Plus -> Defer@*List
]
{a, b, d, e}/Sqrt[2]

I do not recommend this in practice as Plus is a very low level operator and it is not clear what Block actually accomplishes.

  1. As noted elsewhere(1)(2) heads like Plus and Equal have rules that fire on numbers and packed arrays even while Blocked. One cannot be sure that Simplify does not also have specific handling of Plus that Block does not affect therefore this seem unreliable.

  2. Plus is such a basic function that it is probably used in a lot of internal code that we do not wish to affect, and Block is an indiscriminate tool.

$\endgroup$
2
  • $\begingroup$ @Martin Sorry, I am increasingly forgetful, and recently I've been busy, so I do this a lot I'm afraid. :-/ $\endgroup$
    – Mr.Wizard
    Commented Apr 14, 2017 at 6:35
  • $\begingroup$ This post is from many years ago, is there something more about the extraction of common factors in vectors or matrices? $\endgroup$ Commented Dec 3, 2021 at 3:26
4
$\begingroup$

arrayFactorList[array] factors an array à la FactorList, which can then be put in the form Inactive[Times][scalarCommonFactor, array] (see examples):

arrayFactorList[array_?ArrayQ] :=
 FactorList@Total[
    MapIndexed[# \[FormalCapitalA][#2] &, array, {ArrayDepth[array]}],
     ArrayDepth[array]] /. \[FormalCapitalA][i_] :> 
   SparseArray[{i -> 1}, Dimensions[array]]

Example 1:

arrayFactorList[{a/(2 c), b/(2 c), d/(2 c), e/(2 c)}]
GroupBy[Power @@@ %, Head[#] === SparseArray &] //
   Map@Apply@Times //
  Apply@Inactive@Times //
 Normal

Mathematica graphics

Example 2:

arrayFactorList[{{1/Sqrt[2]}, {0}, {0}, {1/Sqrt[2]}}]
GroupBy[Power @@@ %, Head[#] === SparseArray &] //
   Map@Apply@Times //
  Apply@Inactive@Times //
 Normal

Mathematica graphics

$\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.