Log of products to sum of logs
I don't think there is any in-built way of doing this with Mathematica using FullSimplify etc, other than as you have suggested. These issues arise quite often when solving symbolic maximum likelihood estimator problems, so we added this functionality years ago into the mathStatica add-on for Mathematica, which is done by activating SuperLog, which enhances Mathematica's Log function to make such conversions automatically. Since your example is a bit more unusual than the norm, I thought I'd just try it out ... Here's the syntax:
A more typical problem would be something like:
Here is a concise way to do the transformation :
(* your expression : *)
exp00 = Log[Product[
g[a[i, i]] Product[
f[a[i, k]],
{k, 1, i}
],
{i, 1, n}]
];
(* your rules expressed as functions : *)
transformationFunction1 = (# /. Log[Product[expr_,range_]] :> Sum[Log[expr],range]) &;
transformationFunction2 = PowerExpand;
(* the transformation : *)
FixedPoint[(# // transformationFunction1 // transformationFunction2) &, exp00];
It gives :
$$
\sum _{i=1}^n \left(\text{Log}[g[a[i,i]]]+\sum _{k=1}^i \text{Log}[f[a[i,k]]]\right)
$$
With Simplify, the solution is :
Simplify[
exp00,
TransformationFunctions -> {
Automatic,
transformationFunction1,
transformationFunction2
},
ComplexityFunction -> (200 Count[#, _Product, Infinity] +
20 Count[#, _Times, Infinity] + LeafCount[#] &)
]
Simplify[]
is hmm... complicated and useless in this case.
When not to use Simplify[]
?. Here is my rule of thumb : In a Simplify[]
, if the transformationFunctions can be applied everywhere in the expression and the transformation goes in the right direction (ie no backtrack on a earlier goal in the future) or does nothing, get rid of Simplify[]
and use FixedPoint[(# //TransformationFunction1 //TransformationFunction2 ...)&,exp]
Moreover :
- Simplify[] can stop on a local minimum of a ComplexityFunction
- Here the term 20 Count[#, _Times, Infinity]
in the ComplexityFunction limits strongly the generality of the transformation.
Beyond this point, for those interested : How to waste time with Simplify[]
I have detailed the trial and error path that leads to the code. Hope my explanations could simplify the path for others.
We want to automatically transform :
$$ \text{exp00}=\text{Log}\left[\prod _{i=1}^n \left(g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right)\right] $$
(equivalent to :
exp00 = Log[
Product[g[a[i, i]] Product[f[a[i, k]], {k, 1, i}], {i, 1, n}]]
)
in : $$ \sum _{i=1}^n \left(\text{Log}[g[a[i,i]]]+\sum _{k=1}^i \text{Log}[f[a[i,k]]]\right) $$
First, one must know (unfortunately) that Mathematica doesn't simplify $\text{Log}\left[\prod _{k=1}^i x[i]\right]$. So one tries the rule : Log[Product[expr_, range_]] :> Sum[Log[expr], range]
and obtains :
$$
\sum _{i=1}^n \text{Log}\left[g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right]
$$
which goes in the right direction.
Then comes to the mind the idea that this rule should always be used, so that one get rid of the second Product, or maybe every product for this kind of problem. The point is that the rule transforms a expression into a expression which is equal (in the meaning of the user, depending of the context : Real, Complex etc...), so it can be applied everywhere (because we don't know yet how will be the expression when the rule will be applied)
To apply semi-automatically such rules which conserves a expression, there is Simplify[exp, TransformationFunctions -> {# /. conservativeRule1 &,# /. conservativeRule1 & ...} ]
.
Simplify[]
has built-in conservative rules (which are unknown). To use them, add Automatic
at the beginning of the list of TransformationFunctions
.
So we try :
Simplify[
exp00,
TransformationFunctions -> {
Automatic,
# /. Log[Product[expr_, range_]] :> Sum[Log[expr], range] &
}
]
and we see that it gives : $$ \sum _{i=1}^n \text{Log}\left[g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right] $$
It's not better than applying the Rule directly, but we have hope to resolve the second Product later. Here the problem is apparently that Mathematica doesn't transform Log[a b]
in Log[a]+ Log[b]
. Once again one must (unfortunately) know that PowerExpand is the (hard to find) solution :
Log[a b] // PowerExpand
(* Log[a] + Log[b] *)
So one add PowerExpand to the TransformationFunctions
:
Simplify[
exp00,
TransformationFunctions -> {
Automatic,
# /. Log[Product[expr_, range_]] :> Sum[Log[expr], range] &,
PowerExpand
}
]
This gives : $$ \sum _{i=1}^n \text{Log}\left[g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right] $$
It doesn't work !
We expected something like : $$ \sum _{i=1}^n \text{Log}[g[a[i,i]]]+\text{Log}\left[ \prod _{k=1}^i f[a[i,k]]\right] $$
The reason is that Mathematica doesn't consider that what we expected is simpler than the input expression."simpler" is a very subjective notion. The option that determine the criterion "simple" is : ComplexityFunction-> {LeafCount}
(Default).
Here we want to get rid of Times
(because $\text{FullForm}\left[g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right]$ is Times[g[a[i, i]], Product[f[a[i, k]], List[k, 1, i]]]
)
So we add the option : ComplexityFunction -> (20 Count[#, _Times, Infinity] + LeafCount[#] &)
. The coefficient 20 is strong to get rid of all Times
in the expression. Here,there is only one. Very dangerous if other expression (1).
It gives : $$ \text{Log}\left[\prod _{i=1}^n g[a[i,i]] \prod _{k=1}^i f[a[i,k]]\right] $$
It doesn't work. We are back to the first expression !! Simplify
doesn't want to eliminate Product
. As we know that it can do it, we must complete the ComplexityFunction List by specifiying that we do not want any Product
at all (coefficient 200) :
Simplify[
exp00,
TransformationFunctions -> {
Automatic,
# /. Log[Product[expr_, range_]] :> Sum[Log[expr], range] &,
PowerExpand
},
ComplexityFunction ->
(200 Count[#, _Product, Infinity] +
20 Count[#, _Times, Infinity] +
LeafCount[#] &
)
]
It gives : $$ \sum _{i=1}^n \left(\text{Log}[g[a[i,i]]]+\sum _{k=1}^i \text{Log}[f[a[i,k]]]\right) $$
This is what we want.
Nicely, the second Product
has vanished.