# Reducing exponential inequalities fails

I am quite stumped by this problem :

Reduce[ N^(x-y) <1 && N > 0 , x, Reals]


gives the expected result

(N>1 && x<y) || (N<1 && x>y)


but

Reduce[ N^(x-y) <1 && N > 1 , x, Reals]
Reduce::nsmet This system cannot be solved by the methods available to Reduce


and more importantly

Reduce[ N^x < N^y && N > 0 , x, Reals]
Reduce::nsmet This system cannot be solved by the methods available to Reduce


Now this would not be a problem but I am trying to apply Reduce automatically to large quantities of inequalities, and I would rather avoid having to rewrite each and every one by hand. Especially considering that some will be multiple inequalities like

N^x < N^y < N^z


Do you have any idea why Reduce fails and how to go around this ? Thanks in advance.

• How about taking the Log of both sides? – bill s May 15 '13 at 5:13
• Ah yes that might be reasonably done automatically, with a Map and applying a log on both sides of any equation that contains N. Thanks, I'll try it that way ! – Fgsft May 15 '13 at 5:17
• Be very careful about using N as a variable name as it's a Function in Mathematica already. – Jonathan Shock May 15 '13 at 5:21
• Haha good call, using any other variable name I get the first bug to disappear, but not the second (and alas more important) one. – Fgsft May 15 '13 at 5:24
• In version 9 I only get a message with the third Reduce. The first Reduce also gets a better solution of (N > 1 && x < y) || (0 < N < 1 && x > y). – Sjoerd C. de Vries May 15 '13 at 8:06

Edit: I must precise that I am using Mathematica 8

Okay one month later I've faced this problem at a far large scale, and so I resolved to create my own batch of rules. I must have done it in the least elegant way possible, but for the sake of whoever may face the same sort of problems, here is my batch of functions putting this sort of equations under a form agreeable to Reduce. I have tested them on my own equations but cannot guarantee the absence of a bug, however hopefully the general idea is clear enough for anyone to build their own version.

Only the last function needs to be used explicitly, applied to the expression before Reduce, and right now it is explicitly geared toward Real solutions with no coefficient equal to zero.

First some tools (I swear I did not find convincing alternatives in the doc, but I might be utterly blind):

Logical[exp_] := !
FreeQ[{Greater, Less, Or, And, Not, Equal, Unequal, LessEqual,
(*determines whether an expression is logical, obviously*)

MapList[func_, exp_] := Reap[Scan[Sow[func[#]] &, exp]][[2, 1]]
(*returns a list of the elements of an expression (not a list) with func applied to them*)

TrueCoefficient[poly_, var_, x_] :=
Coefficient[ Coefficient[poly, var, x], var, 0]
(* avoids a strange bug in Coefficient*)

TruerCoefficient[poly_, var_, x_] :=
With[{normal = TrueCoefficient[poly, var, x]},
If[normal === 0, TrueCoefficient[Simplify[poly], var, Simplify[x]],
normal]]
(*avoids problem of coefficients associated with exponents formally equal but written differently*)

FullTerm[exp_, var_, x_] :=
var^ex TruerCoefficient[exp, var, x]
(*returns the real term in expression exp where var appears with power x*)


Then the meat :

SymbPower[exp_, pow_] :=
FullSimplify[
Map[SymbPower[#, pow] &, exp], Power[exp, pow]],
Assumptions -> {x_ \[Element] Reals}]
(*Distributes power pow over expression exp to avoid conundrums like (a y^x)^(1/x) not being simplified in y and blocking Reduce*)

RemPower[exp_, var_] :=
PiecewiseExpand[
With[{side =
If[MapList[Count[#, var, Infinity] &, exp] === {1, 0}, 1, 2]},
With[{x = TrueExponent[exp[[side]], var]},
If[x === 0 || x === 1, exp,
With[{result = Map[SymbPower[#, 1/x] &, exp]},
If[x > 0, result,
result /. {Less -> Greater, Greater -> Less,
LessEqual -> GreaterEqual, GreaterEqual -> LessEqual} ] ]]]]]
(*Carelessly takes the root when a formal power is involved and Reduce refuses to do anything. Caution should be applied before use.*)

TwoToOne[exp_, var_] :=
With[{cnt = MapList[Count[#, var, Infinity] &, exp]},
Which[cnt === {1, 1}, Map[#/exp[] &, exp], cnt === {0, 2},
If[exp[] === 0, TwoToOne[Map[# - exp[[2, 2]] &, exp], var],
exp], cnt == {2, 0}, TwoToOne[Head[exp][exp[], exp[]], var],
True, exp]]
(*from y^a - C y^b = 0 to y^(a-b)=C *)

VariableOnHS[exp_, var_] :=
With[{cnt = MapList[Count[#, var, Infinity] &, exp]},
With[{side = If[cnt === {1, 0}, 1, 2]},
Which[Length[TermList[exp[[side]], var ]] == 1, exp,
Plus @@ cnt === 1,
With[{si = FullTerm[exp[[side]], var, 0]}, Map[# - (si) &, exp]],
True, exp]]]
(*puts the variable alone on one hand-side of the equation*)

CanonicalForm[exp_, var_] :=
With[{cnt = MapList[Count[#, var, Infinity] &, exp]},
Which[Plus @@ cnt === 0, exp, Plus @@ cnt === 1,
RemPower[VariableOnHS[exp, var], var], Plus @@ cnt === 2,
With[{simp = TwoToOne[exp, var]},
If[Count[simp, var, Infinity] === 1, CanonicalForm[simp, var],
exp]], FreeQ[MapList[Logical, exp], True], exp, True,
Map[CanonicalForm[#, var] &, exp]]]
(*everything put together, ready to use in Reduce*)


Apologies for the mammoth post. Any more elegant alternative will be embraced and rewarded with eternal gratitude.

Taking the Log makes a lot of sense, though to do the simplification it's necessary to be explicit about the domain of the variables: x and y need to be real-valued and n needs to be larger than 1

eqn = n^x < n^y;
FullSimplify[Log /@ eqn, n > 1 && x ∈ Reals && y ∈ Reals]
x < y


If n isn't larger than 1:

FullSimplify[Log /@ eqn, 0 < n < 1 && x ∈ Reals && y ∈ Reals]
y < x


and of course if n<0 it is no longer a real-valued problem.