One could consider a home cooked simplify.
The purpose of the code below is to eliminate any guidance from the user. That is, there is no hard coding or any way to incorporate insight from the user.
The main idea is to find the terms that occur the most in multiplications and collect those.
Using simplify defined below:
expr // simplify
(G3 + G4 + G5 + G7 + G8) P2 + (G1 + G3 + G4 + G5 + G7 + G8) P5 + (G1 + G2 + G4 + G5 + G6 + G8) (P3 + P6)
In LaTeX :
$$(\text{P3}+\text{P6}) (\text{G1}+\text{G2}+\text{G4}+\text{G5}+\text{G6}+\text{G8})+\text{P5} (\text{G1}+\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8})+\text{P2} (\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8})$$
Code:
(code unpacked and mostly explained below)
Note: …=\[Ellipsis]
Clear[simplify];
simplify[expression_]:=
Module[{check,var,to…collect,
simplified,duplicated,x,renaming…rule,
renaming…rule…inversed,new…variables},
check= Head[expression]===Plus &&
(List@@expression//AllTrue[#,MatchQ[_Times]]&);
If[check===False,
Print["simplify is not adapted to this structure"];
Abort[]
];
var=(expression//Variables);
to…collect={Count[expression,#*_],#}&/@var
//MaximalBy[First]
//Map[Last];
simplified=Collect[expression, to…collect, Simplify];
(* Find subexpressions that occur
multiple times *)
duplicated=simplified
//Level[#,{2}]&
//Gather
//Select[Length@#>1&]
//Map[DeleteDuplicates]
//Flatten;
(*renaming duplicates*)
new…variables=x/@Range@Length@duplicated;
renaming…rule =
Thread[duplicated->new…variables];
renaming…rule…inversed=
Reverse/@renaming…rule;
Collect[simplified /.renaming…rule,
new…variables,
Simplify]/. renaming…rule…inversed
]
Explanation
- Step 1
Find the variables:
var = (expr // Variables);
- Step 2
Find which variables occur the most in the multiplications:
{Count[expr, #*_], #} & /@ var // Sort
{{2, G2}, {2, G3}, {2, G6}, {2, G7}, {3, G1}, {4, G4}, {4, G5}, {4, G8}, {5, P2}, {6, P3}, {6, P5}, {6, P6}}
(included transposition to reduce displayed height )
$$\left( \begin{array}{cccccccccccc} 2 & 2 & 2 & 2 & 3 & 4 & 4 & 4 & 5 & 6 & 6 & 6 \\ \text{G2} & \text{G3} & \text{G6} & \text{G7} & \text{G1} & \text{G4} & \text{G5} & \text{G8} & \text{P2} & \text{P3} & \text{P5} & \text{P6} \\ \end{array} \right)$$
- Step 3
Collect the variables that occur the most in multiplications:
simplified = Collect[expr, {P6, P5, P3}, Simplify]
(G3 + G4 + G5 + G7 + G8) P2 + (G1 + G2 + G4 + G5 + G6 + G8) P3 + (G1 + G3 + G4 + G5 + G7 + G8) P5 + (G1 + G2 + G4 + G5 + G6 + G8) P6
$$ \text{P3} (\text{G1}+\text{G2}+\text{G4}+\text{G5}+\text{G6}+\text{G8})+\text{P6} (\text{G1}+\text{G2}+\text{G4}+\text{G5}+\text{G6}+\text{G8})+\text{P5} (\text{G1}+\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8})+\text{P2} (\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8}) $$
- Step 4
collect sub expressions that occur more than once.
One could maybe use
Experimental`OptimizeExpression
(see for example Common subexpression from two expressions )
to find common sub expressions in the expression above but instead I consider a more simple approach for this kind of structure:
simplified // Level[#, {2}] & // Tally
{{G3 + G4 + G5 + G7 + G8, 1}, {P2, 1}, {G1 + G2 + G4 + G5 + G6 + G8, 2}, {P3, 1}, {G1 + G3 + G4 + G5 + G7 + G8, 1}, {P5, 1}, {P6, 1}}
$$\left( \begin{array}{cc} \text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8} & 1 \\ \text{P2} & 1 \\ \text{G1}+\text{G2}+\text{G4}+\text{G5}+\text{G6}+\text{G8} & 2 \\ \text{P3} & 1 \\ \text{G1}+\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8} & 1 \\ \text{P5} & 1 \\ \text{P6} & 1 \\ \end{array} \right)$$
G1 + G2 + G4 + G5 + G6 + G8 appears twice we can rename it then simplify then rename again:
Collect[simplified , G1 + G2 + G4 + G5 + G6 + G8]
$$(\text{P3}+\text{P6}) (\text{G1}+\text{G2}+\text{G4}+\text{G5}+\text{G6}+\text{G8})+\text{P5} (\text{G1}+\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8})+\text{P2} (\text{G3}+\text{G4}+\text{G5}+\text{G7}+\text{G8})$$