From the Wolfram functions web site it is known that

$$\log(z_1)+\log(z_2)=\log(z_1z_2),\text{ for $z_1+z_2>0$}$$

In an answer to this question Alexei Boulbitch wrote a useful function collectLog. However, this function does not impose conditions on the Log-arguments.

Therefore, my question is, how should collectLog look like, so that it can be used in

FullSimplify[Log[a] + Log[b], 
 TransformationFunctions -> {Automatic, collectLog}, 
 Assumptions -> a + b > 0]

providing the desired simplification only when the condition is met.


In trying to create a minimal example I simplify the problem too much. In fact, the main motivation is to combine two Log-functions together when it can be inferred from the given that the sum of arguments is positive. In many cases the solution of Carl Woll already works fine. For instance here

(* Log[Cos[a]^2] *)

The product of 1-Sin[a] and 1+Sin[a] is equal to Cos[a]^2, which is positive for $x\in\mathbb{R}$, thus, endorsing the simplification. However, there are many exceptions that I would like to be addressed too. Below are two simple examples where the LogContract fails.

  • Identity 1

$$\log(\mathrm{sign}\,x)+\log(x)=\log(x\,\mathrm{sign}\,x)=\log{\!|x|},\text{ for $x\in\mathbb{R}$.}$$

(* Log[a]+Log[Sign[a]] *)

The expected result is Log[Abs[a]].

  • Identity 2

$$\log(1-\cos2x)-\log(1+\cos2x)=\log\!\left(\frac{1-\cos2x}{1+\cos2x}\right)=\log\!\left(\tan^2\!x\right),\text{ for $x\in\mathbb{R}$.}$$

Assuming[a∈Reals,FullSimplify[Log[1-Cos[2 x]]-Log[1+Cos[2 x]],

The expected result is Log[Tan[x]^2].


Many expressions of this kind result from the and not artificially constructed just to make the function fail. At the moment it is a rather laborious process to bring the expressions to a human-readable form.


2 Answers 2


One idea is to make use of PowerExpand with its Assumptions option. For example, consider:

PowerExpand[Log[a b], Assumptions->a+b>0]

Log[a] + Log[b]

Of course, PowerExpand is going the wrong direction! However, we can go in the right direction by using something like:

Log[a] + Log[b] /. Log[x_] + Log[y_] :> Log[x y] + 
    PowerExpand[Log[x] + Log[y] - Log[x y], Assumptions->x+y>0]

Log[a b]

The function LogContract, defined below, does this more generally, accounting for sums that are not pure sums of Log expressions (e.g., Log[x] + 3 Log[y] + 4):

Options[LogContract] = {Assumptions :> $Assumptions};

LogContract[e_, OptionsPattern[]] := Block[{$Assumptions = OptionValue[Assumptions]},
    e /. {l_Log :> l, Plus->iplus}

iplus[a__]:=Module[{logArgs, nonlogs, sum, product},
    {logArgs, nonlogs} = Transpose @ Replace[{a},
        z_. Log[v_] :> {v^z, Simplify @ PowerExpand[z Log[v]-Log[v^z], Assumptions->True]},
        o_ :> {1, o}
    sum = Total[Log[logArgs]];
    product = Log[Times @@ logArgs];
        product + PowerExpand[sum - product, Assumptions->$Assumptions] + Total[nonlogs]

Your example:

LogContract[Log[a] + Log[b], Assumptions -> a + b > 0]

Log[a b]

A slightly more complicated example:

LogContract[Log[x] + 3 Log[y] + 4, Assumptions -> x>0 && y<0]

4 + 2 I π + Log[x y^3]

Check that the above transformation is correct for a random example:

rules = Thread @ Rule[{x, y}, {RandomReal[1], -RandomReal[1]}];

Log[x] + 3 Log[y] + 4 /. rules
4 + 2 I π + Log[x y^3] /. rules

-2.785 + 9.42478 I

-2.785 + 9.42478 I


If you want to make use of LogContract with assumptions inside of FullSimplify, you will need to use Assuming instead of giving FullSimplify the Assumptions option. This is because FullSimplify does not change $Assumptions while performing simplifications. So:

    a + b > 0,
    FullSimplify[Log[a] + Log[b], TransformationFunctions -> {Automatic, LogContract}]

Log[a b]

Update on OP comments (after 2 1/2 years!)

Identity 1 is only true for positive real parts, for example:

Log[-1] + Log[-2]

2 I Pi + Log[2]

is a counter example. So, you need a better assumption:

LogContract[Log[Sign[x]] + Log[x], Assumptions -> Re[x]>0]

Log[x Sign[x]]

Identity 2 manifested a bug in my code, which I just fixed (by avoiding messing up the insides of Log objects):

LogContract[Log[1 - Cos[2 x]] - Log[1 + Cos[2 x]], Assumptions -> x ∈ Reals]


  • 1
    $\begingroup$ Nice solution! Indeed it works in many cases, but also fails sometimes. I've amended my post after realizing that I oversimplified the original problem in trying to construct a minimal example. Could you please have a look at the two examples that still make a problem. Thanks a lot! $\endgroup$
    – yarchik
    Oct 9, 2019 at 11:18

For positive values I just use a simple rule:

logsimp := {n_ Log[x_] -> Log[x^n], Log[x_] - Log[y_] -> Log[x/y], 
  Log[x_] + Log[y_] -> Log[x y], Log[1/x_] -> -Log[x]}

Log[x] + 3 Log[y] //. logsimp
(*Log[x y^3]*)

Log[x] - Log[y]/3 //. logsimp

You can wrap this rule about any part of your expression if you don't want to simplify all of it.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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