2

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.

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
Mattia
  • 175
  • 7
  • -# & /@ Simplify[myexpr] – Bob Hanlon Sep 28 '18 at 02:01
  • 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. – Mattia Sep 29 '18 at 03:22

2 Answers2

1

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)

Carl Woll
  • 130,679
  • 6
  • 243
  • 355
  • 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. – Mattia Oct 01 '18 at 03:41
0
$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) *)
Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198
  • 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. – Mattia Oct 01 '18 at 03:38