# Simplifying simple signed expression ( such as $-x(x-1) \to x(1-x)$ ) based on assumptions

Context

I would like to simplify expression involving, say, (x-1) or (x^2-1) when I know that |x|<1 so that the global sign appears more clearly.

I apologise in advance if it turns out to be trivial.

Attempt

I have tried e.g.

Simplify[(-2*x^2*(-1 + x^2))/135,Assumptions->x<1&&x>0]


but I would like to have instead

I guess I want to put a penalty on having a negative sign in front at the rendering stage?

The motivation for this is to be able to typeset the result into a publication.

## Update

While the answers this question have received address successfully my original question, I think it would be of wide interest to scientists in general who typeset equations extracted from mathematica to be able to improve simplification when assumptions on the sign of certain variables are made.

For example,

  (Sqrt[1 - x] - 3*(-1 + x)*ArcTan[3*Sqrt[1 -x]])/(4*Pi)


Can be simplified if $$0.

I realise it is probably not a trivial task to produce such simplification generically, but no one would typeset this equation as

$$\frac{\sqrt{1-x}-3 (x-1) \tan ^{-1}\left(3 \sqrt{1-x}\right)}{4 \pi }$$

• But your answer is the same as what you requested, just rendered slightly differently (the canonical order in Mathematica, with increasing powers of $x$. What's the true problem? Nov 27, 2018 at 2:02
• As you rightly notice, its only a rendering issue. Basically when I publish the result, the second form is preferable to the first one, since the reader will understand more easily that the quantity is positive since he knows that |x|<1. In other words, can I wrap a rendering option to formulas so it respect my convention, not mathematica's? Nov 27, 2018 at 2:04
• What's the desired outcome of Simplify[(2*x^2*(-1 + x^2))/135,Assumptions->x<1&&x>0]? @kglr's gives no minus sign, mine gives a minus sign. Nov 27, 2018 at 4:19
• @MichaelE2 your expression is preferred. The drawback of your function is that it is less easily encapsulated as it involves both ComplexityFunction and TransformationFunctions. I wish I could grant both of you the solved badge! Nov 27, 2018 at 4:21

You can use ComplexityFunction option to "penalize" the number of terms with a negative sign:

cf = (LeafCount[#] + 100 Count[#, _?InternalSyntacticNegativeQ, ∞] &);

Simplify[(-2*x^2*(-1 + x^2))/135, ComplexityFunction -> cf]


2/135 x^2 (1 - x^2)

As chris noted in comments, this gives an unsatisfactory result for the following example:

Simplify[(Sqrt[1 - x] - 3*(-1 + x)*ArcTan[3*Sqrt[1 - x]])/(4*Pi),
ComplexityFunction -> cf]


(Sqrt[1 - x] + (3 - 3 x) ArcTan[3 Sqrt[1 - x]])/(4 π)

since it expands - 3*(-1 + x) to (3-3x).

A simple modification of cf to cf2 normalizing the second term by the LeafCount of input expression:

cf2 = LeafCount[#] + 100 Count[#, _?InternalSyntacticNegativeQ, ∞]/ LeafCount[#] &;


gives the desired result for both examples:

Simplify[(-2*x^2*(-1 + x^2))/135, ComplexityFunction -> cf2]


2/135 x^2 (1 - x^2)

Simplify[(Sqrt[1 - x] - 3*(-1 + x)*ArcTan[3*Sqrt[1 - x]])/(4*Pi),
ComplexityFunction -> cf2]


(Sqrt[1 - x] + 3 (1 - x) ArcTan[3 Sqrt[1 - x]])/(4 π)

Needless to say, I am sure there will be examples where both will fail to give the desired result.

• Thanks! Do you think this question is worth keeping on the site or is it too trivial? Nov 27, 2018 at 2:13
• @chris, it is not trivial at all.
– kglr
Nov 27, 2018 at 2:21
• The result on (Sqrt[1 - x] - 3*(-1 + x)*ArcTan[3*Sqrt[1 - x]])/(4*Pi) is a bit disappointing since it expands the 3. Any suggestion? Jun 5, 2019 at 12:32
• @chris, ComplexityFunction -> (LeafCount[#] + 100 Count[#, _?InternalSyntacticNegativeQ, \[Infinity]]/ LeafCount[#] &) gives the desired result for your example. I am sure there will be cases the trick will fail.
– kglr
Jun 5, 2019 at 23:42
• Fair enough! Thanks for your help. Jun 6, 2019 at 6:43

Sticking with the problem of having a product's syntactic sign agree with the sign of its real value under \$Assumptions, assuming it's real-valued (and not the problem of just supressing an initial minus sign regardless of the sign of the expression)...

The idea of syntacticallyCorrectSignForm is to convert any negative factors to positive factors and and keep track of the sign changes:

syntacticallyCorrectSignForm[e_Times] := Module[{sign = 1, res},
res = If[
TrueQ@Simplify[# < 0],
sign = -sign
; If[InternalSyntacticNegativeQ[#], Defer[#], #] &@Simplify[-#],
#] & /@ e;
sign*res]


OP's example (from comment below):

Assuming[x < 1 && x > 0 && b > 0,
syntacticallyCorrectSignForm[b (-2*x^2*(-1 + x^2))/135]
]


Powers of negative expressions are difficult, since (-y)^3 automatically evaluates to -(y^3). The use of Defer in syntacticallyCorrectSignForm allows the output expression to be copied as input.

Assuming[x < 1 && x > 0 && b > 0 && y < 0,
syntacticallyCorrectSignForm[b (-2*x^2*y^3*(-1 + x^2))/135]
]


Here's what I came up with, understanding the question to say that we want a negative sign when the expression is negative:

cf[e_Times] :=
Boole[InternalSyntacticNegativeQ[e] =!=
TrueQ@Simplify[
Reduce[$$Assumptions \[Implies] e < 0],$$Assumptions]];
cf[e_Plus] := cf /@ e;
cf[e_] := 0;
xf = # /. e_Plus /; Simplify[
Reduce[$$Assumptions \[Implies] e < 0],$$Assumptions
] :> -\[FormalX][-e] /. \[FormalX] -> Expand &;


OP's example:

Assuming[x < 1 && x > 0,
Simplify[(-2*x^2*(-1 + x^2))/135,
ComplexityFunction ->
(SimplifySimplifyCount[#] + 10 cf[#] - 5 Boole[Head[#] === Times] &),
TransformationFunctions -> {Automatic, xf}
]
];
(*  2/135 x^2 (1 - x^2)  : This expression is positive under the assumptions *)


The negative of the OP's example:

Assuming[x < 1 && x > 0,
Simplify[(2*x^2*(-1 + x^2))/135,
ComplexityFunction ->
(SimplifySimplifyCount[#] + 10 cf[#] - 5 Boole[Head[#] === Times] &),
TransformationFunctions -> {Automatic, xf}
]
]
(*  -(2/135) x^2 (1 - x^2)  : This expression is negative under the assumptions *)


Another example from a comment:

Assuming[x < 1 && x > 0 && b > 0,
Simplify[b (2*x^2*(-1 + x^2))/135,
ComplexityFunction ->
(SimplifySimplifyCount[#] + 10 cf[#] - 5 Boole[Head[#] === Times] &),
TransformationFunctions -> {Automatic, xf}
]
]
(*  -(2/135) b x^2 (1 - x^2)  *)


Note that there's nothing that can be done about expressions like -(1-x^2), which evaluates automatically to x^2 - 1, AFAICT.

• Thanks. I does not seem to be able to cope with b (2*x^2*(-1 + x^2))/135 even if I specify that b >0. ? Nov 27, 2018 at 4:30
• @chris This may not be worth investigating further, but I tweaked it to work with your example. Nov 27, 2018 at 4:50
• Whaow! The second answer is exactly what is needed I think. For people like me this should be super useful. Thanks a lot! Nov 27, 2018 at 23:56

Try this:

expr = (-2*x^2*(-1 + x^2))/135;
exprA = -Last[expr]
exprB = -expr[[1 ;; 2]]

(*  1 - x^2

(2 x^2)/135   *)


Now:

exprA*exprB

(*  2/135 x^2 (1 - x^2)  *)


as you wished.

One can also make sure that Mma will never change this if you make a slight change in the code. It is as follows

MapAt[HoldForm, exprA*exprB, {3}]


There exists a special function for such things in the package "Presentations" of David Park that can be used.

As much as I understood from the explanations, you need it for the purposes of demonstration or publishing. You did not, however, specify, what kind of document (or demonstration) are you creating. For example, it is not clear, why do not you simply type this function in a cell of the "Display Formula" type? Probably you have your reasons. Depending on this, however, one may use other more simple and efficient ways.

Have fun!

• Thank you for your work. I meant to say I will export the formula into a paper via TexForm. I typically do this by hand but it is nice to be able to teach mathematica to write things the way I want. Nov 27, 2018 at 15:09

One way to do this to check each subexpression with the head Plus under given assumptions, and replace it with its negative version depending on the sign. One then does the simplification again but leaves these terms untouched using ExcludedForms option of Simplify.

For example, OP's case:

simplify[(-2*x^2*(-1+x^2))/135]
(* 2/135 x^2 (1-x^2) *)


in contrast to

Simplify[(-2*x^2*(-1+x^2))/135]
(* -(2/135) x^2 (-1+x^2) *)


The code is as follows:

ClearAll[assumptions];
assumptions = {1 > x > 0};

ClearAll[simplify];
simplify = Function[
Module[{m, transform},
transform = Function[# /. a_Plus /; Simplify[a < 0, Assumptions -> assumptions] :> m Plus[-a]];
Simplify[transform[#], ExcludedForms -> a_Plus /; Simplify[a > 0, Assumptions -> assumptions],
TransformationFunctions -> {Automatic, transform}
] /. m -> -1
]];


As there are many pattern matching going on, this function is best to be used at the very end. However, it is quite generic.

Another example:

assumptions={1>x>0,y<5};
Sin[(x-1)(6-y)]//simplify
(* -Sin[(1-x) (6-y)] *)

• Thanks for your function ! Dec 1, 2018 at 5:12