# Applying rules to expressions [closed]

I'm trying to write a rule that acts on any number, lists, expression and so on to turn any negative numbers positive.

The simple r = n_ -> Abs[n] works perfectly well for numbers, lists and nested lists, but does not work expressions, such as Exp[-5], which is unaffected by my rule. I can't use the replace function, because I also require my rule to work for other Mathematica inputs, like numbers, lists and nested lists.

Can someone suggest why this does not work? Is it due to the rule not penetrating the expression? An edit to my rule would also be much appreciated.

-

## closed as unclear what you're asking by Daniel Lichtblau, Louis, MarcoB, m_goldberg, marchJan 30 at 18:11

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question.If this question can be reworded to fit the rules in the help center, please edit the question.

Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Take the tour! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! – Michael E2 Jan 29 at 13:24
I think it is working, but it's working on Exp[-5]. Trace shows you the sequence of evaluation steps: Trace[Exp[-5] /. r]. Perhaps Exp[-5] /. n_?NumberQ :> Abs[n] is what you're after? – Michael E2 Jan 29 at 13:27
@MichaelE2, using your method, why can we get (-E)^(-5) to return E^5, but we can't get (-2)^(-5) to return 2^5? Changing the -2 to -2.0 doesn't change it either. – JasonB Jan 29 at 13:44
@JasonB Perhaps Trace and the observation that NumberQ[E] is False leads to an explanation. E.g., (-2)^(-5) evaluates to -1/32 before any rules are applied. See if you can figure out HoldForm[(-2)^(-5)] /. n_?NumberQ :> Abs[n] // Trace -- it stumped me at first. Inactivate[(-2)^(-5)] /. n_?NumberQ :> Abs[n] is the only way I figured out to do what you want. – Michael E2 Jan 29 at 14:02
This question needs a good size set of example inputs with desired outputs. Too many people are needing too many guesses to sort out what actually is wanted, and that amounts to wasted time. – Daniel Lichtblau Jan 29 at 18:34

A few more examples provided at suggestion of OP.

Replace[Unevaluated[{Exp[-5], -7, (-2)^(-5), BesselJ[-2, -3],
Cos[-5], {-Pi, -E}, Exp[-5 Exp[-5]]}], n_ -> Abs[n], {0, Infinity}]

(* {E^5, 7, 32, BesselJ[2, 3], Cos[5], {π, E}, E^(5 E^5)} *)


may be what you want. (Note:. Unevaluated needed to handle (-2)^(-5).)

This can be written as a function by

f = Function[x, Replace[Unevaluated[x], n_ -> Abs[n], {0, Infinity}], HoldAll]


Then,

f@{Exp[-5], -7, (-2)^(-5), BesselJ[-2, -3], Cos[-5], {-Pi, -E}, Exp[-5 Exp[-5]]}
(* {E^5, 7, 32, BesselJ[2, 3], Cos[5], {π, E}, E^(5 E^5)} *)


as before.

-
Thank you for your help, but I should have made my question clearer (I have just edited it). I require this rule to work for all kinds of mathematica inputs, such as numbers, lists of numbers, Cos[-5] and so on. Therefore, Replace won't work since it is far too specific. – Pablo Jan 29 at 13:34
@Pablo Works for those too. See addition to list of examples. The third argument, Infinity, causes Replace to reach inside functions. The suggestion by MichaelE2 works well too, of course. – bbgodfrey Jan 29 at 13:39
@bbgodfrey I believe Reduce[ expr, n_?NumberQ -> Abs[n], Infinity] might work and be more precise? (Oh, I see that is what MichaelE2 has suggested above) – gwr Jan 29 at 13:40
@gwr Certainly, your suggestion works too, but I am not sure what you mean by "more precise". – bbgodfrey Jan 29 at 13:42
@bbgodfrey While testing ?NumberQ takes time, we will not need to have nested Abs[ ] in a nested expression, but that is what we will get without the filtering. – gwr Jan 29 at 13:50

Exp[-5] is not unaffected by your rule at all; on the contrary,

Trace[Exp[-5]/.n_->Abs[n]]


shows that Exp[-5] is replaced by Abs[Exp[-5]], which is equal to Exp[-5]. If you only want stuff that "looks like" numbers to get replaced, you can use

Replace[Exp[-5],n_->Abs[n]],-1]


which replaces anything that does not have a sub-part, i.e. it would give

e^5

But what about stuff like (-2)^(-5)? Do you want to replace both (-2) and (-5)?

-
Yes, I want to change every single thing that "looks like" a number from negative to positive before completing the operation. Thank you for your edit on the Exp[-5] example – Pablo Jan 29 at 13:25

In slight modification of @bbgodfrey's excellent answer, what you might use is this:

SetAttributes[ f, HoldAll ];
f[ expr_ ] := Replace[
HoldForm @ expr, (* prevent any evaluation before replacement *)
n_ -> Abs[n], (* ?NumberQ would not work then *)
Infinity
]//ReleaseHold;

f[ (-2)^(-5) ]


32

-
So you might use Replace[ HoldForm @ expr, n_?NumberQ -> Abs[n], Infinity]//ReleaseHold. – gwr Jan 29 at 14:09
There are subtle differences for HoldForm and Unevaluated which I have not pondered too far. With Unevaluated there is no need for a ReleaseHold. – gwr Jan 29 at 14:28

### The problem: "to turn any negative numbers positive"

Proposed solution: Depth-first, post-order traversal with Replace:

positivize[expr_] := MapAll[Replace[#, n_?Negative :> -n] &, expr]


Example:

-Exp[-5] // positivize
(*  E^5  *)


### Near misses

Depth-first, pre-order traversal:

-Exp[-5] /. n_?Negative :> -n
(*  1/E^5  *)


Repeated depth-first, pre-order almost works:

-Exp[-5] //. n_?Negative :> -n
(*  E^5   -- seems to work, but... *)

Zeta[-1/10] //. n_?Negative :> -n
(*  -Zeta[-(1/10)]  *)


### Caveat, re the solution

The solution has a potential trap, which is easily seen if doing the reverse, making positive numbers negative.

Example:

negativize[expr_] := MapAll[Replace[#, n_?Positive :> -n] &, expr];

Cos[5] // negativize
(*  -Cos[5]  *)


Explanation: After the 5 is changed to -5, Cos[-5] automatically reevaluates to Cos[5], according to an internal rule implementing the even-function property of Cos. This does not seem to affect positivize since the internal rule changes the argument to a positive number. However, there are so many functions, I cannot be sure that there isn't a built-in identity that would interfere with positivize. Personally, I think positive arguments tend to be preferred, so maybe it's ok.

### Why ReplacedRepeated and ReplaceAll fail?

Because both ReplacedRepeated (//.) and ReplaceAll (/.) do a pre-order traversal, the whole negative expression -Exp[-5] is matched first and replaced by the positive Exp[-5]. ReplaceAll then stops and the -5 is left unchanged. ReplaceRepeated will continue and replace the -5. But in the case of Zeta[-1/10], which is about -0.417228, it is first replaced by -Zeta[-1/10] or more explicitly Times[-1, Zeta[-1/10]]; on the next application of the rule, the -1 is replaced by 1 -- oops -- yielding Zeta[-1/10]; then the next replacement yields -Zeta[-1/10], at which point ReplaceRepeated exits the potential infinite loop.

Further caveat: Note that whether a minus sign or the numerical value is to be considered "negative" is not made explicitly clear. Negative tests the numerical value. There is InternalSyntacticNegativeQ for testing whether an expression "looks" negative (has a leading minus sign); it could perhaps be used in conjunction with NumericQ to test whether a numeric expression is written with a minus sign (see references below for example uses).

### References

How to ReplaceAll independent of depth?

How to perform a depth-first preorder traversal of an expression?

Merge Roots of Polynomial, Two ways to speed up slow Integrate[]s? (Can't do either) (SyntacticNegativeQ`)

-