2
$\begingroup$

The following code

$Assumptions = {0 < x < 1, 0 < y < 1, z > 1};
myexpr = Expand[(1 - x) (1 - y) (z - 1)];
TraditionalForm[Simplify[myexpr]]

outputs

(x-1)(y-1)(z-1)

but I want to output

(1-x)(1-y)(z-1)

i.e., I want every block in my expression to be a positive number. If the expression itself is negative, that should be shown by a minus in front of it. (The $Assumptions guarantee that Mathematica knows what it needs to know to make sure every block is positive).

Is it possible?

I found this answer but it doesn't quite cut it because (a) it's way too cumbersome and (b) in my case the expression to be reformatted comes out of a solver and I have no control over it.

$\endgroup$
2
  • $\begingroup$ -# & /@ Simplify[myexpr] $\endgroup$
    – Bob Hanlon
    Sep 28, 2018 at 2:01
  • $\begingroup$ Thank you @BobHanlon but I want to reformat the expression without changing its value, so that all blocks have positive value, except perhaps a minus in front. Your code simply multiplies all blocks by -1. If the expression has an odd number of blocks, it will change the value of the expression. If the expression already contains positive blocks, they will become negative. I have edited my question to clarify. Your code does not work with the new example. $\endgroup$
    – Mattia
    Sep 29, 2018 at 3:22

2 Answers 2

1
$\begingroup$

Here is one idea. Create a function that converts products into the desired form. This function will test each multiplicand to see if it is definitely negative, and if so, negate it, keeping track of how many terms were negated. I also added support for integer powers:

Options[positiveMultiplicands] = {Assumptions->$Assumptions};

positiveMultiplicands[a_Times, OptionsPattern[]] := Block[
    {$Assumptions = OptionValue[Assumptions]},

    Times @@ Replace[
        a,
        {
            Power[t_, e_Integer] :> If[Simplify[t>0], 
                {1, Power[t, e]},
                {(-1)^e, Power[-t, e]}, 
                {1, Power[t, e]}
            ],
            t_ :> If[Simplify[t>0], {1, t}, {-1, -t}, {1, t}]
        },
        {1}
    ]
]

Your example:

positiveMultiplicands[
    (x - 1) (y - 1) (z - 1),
    Assumptions -> x < 1 && y < 1 && z > 1
]

(1 - x) (1 - y) (-1 + z)

The example from the linked question:

positiveMultiplicands[(-2+a) y/(-1+a), Assumptions->a<1]

((2 - a) y)/(1 - a)

And finally, an example with powers:

positiveMultiplicands[(2-a)^3/(1-a)^2, Assumptions->a>2]

-((-2 + a)^3/(-1 + a)^2)

$\endgroup$
1
  • $\begingroup$ This is definitely more legible, even though the "-1 + z" bothers me to no end :) Moreover this function behaves well when it doesn't know the sign of a given block. I'll write back if one day I run into a counterexample. $\endgroup$
    – Mattia
    Oct 1, 2018 at 3:41
0
$\begingroup$
$Assumptions = {0 < x < 1, 0 < y < 1, z > 1};

Define a helper function to test whether an expression is negative assuming $Assumptions

negQ[expr_] := Simplify[expr < 0];

f[expr_] := Module[{expr2 = expr // Simplify},
  (-1)^Count[expr2, _?negQ] *(If[negQ[#], -#, #, #] & /@ expr2)]

EDIT: changed If statement in definition of f to handle undecided condition

myexpr = Expand[(1 - x) (1 - y) (z - 1)];

f[myexpr] // TraditionalForm

(* (1-x) (1-y) (z-1) *)

EDIT: With assumption z > 1 changed to z > 0

$Assumptions = {0 < x < 1, 0 < y < 1, z > 0};

f[myexpr] // TraditionalForm

(* (1-x) (1-y) (z-1) *)
$\endgroup$
1
  • $\begingroup$ Thanks, this is very elegant. However, if Mathematica cannot decide whether a given block is positive (e.g. if I assume z>0 instead of z>1), the output will contain an If[ ] block. I didn't say this in my question, but I prefer a function that fails gracefully when it doesn't know what to do. The code in the other answer seems to do that, so I'll accept it. $\endgroup$
    – Mattia
    Oct 1, 2018 at 3:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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