Simplifying simple signed expression ( such as $-x(x-1) \to x(1-x)$ ) based on assumptions
You can use ComplexityFunction
option to "penalize" the number of terms with a negative sign:
cf = (LeafCount[#] + 100 Count[#, _?Internal`SyntacticNegativeQ, ∞] &);
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[#, _?Internal`SyntacticNegativeQ, ∞]/ 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.
Second Answer
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[Internal`SyntacticNegativeQ[#], 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]
]
Original Answer
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[Internal`SyntacticNegativeQ[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 ->
(Simplify`SimplifyCount[#] + 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 ->
(Simplify`SimplifyCount[#] + 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 ->
(Simplify`SimplifyCount[#] + 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.