0
$\begingroup$

I often run into the problem that Mathematica refuses to simplify divergent subexpressions as part of a full expression that is manifestly finite. This only happens when a symbolic power is involved.

A minimal example is:

expr = x^(d - 4) (a x^2 + b (x + x^3 + c x^d));

Let's say this is an expression that I want to use for all d>=3. Then d=3 comes closest to diverging:

Series[expr/.d->3,{x,0,0}]

gives b, ofcourse.

But I want to be able to do this:

expr /. d->3 /.x->0

which in its current form will run into a division by zero.

Note that if we simplify the expression after setting d->3 it does work, but that is not what I'm after.

I have at various times made some ad hoc solution with a replacement rule for example, but I've run into this problem so often now that I'm looking for a definite general solution.

You may assume that the expression is rational in x, that the expression when properly expanded is finite and nonzero at x=x0 (in the example above x0=0), and that there is some definite lower bound for the symbolic power (d above).

I'm ideally looking for a simple and reasonably fast solution that works for any expression satisfying the above criteria.

EDIT: Something like Expand[expr] would work, but I want something more sensible, keeping the expression as much as possible in simplified form.

$\endgroup$
4
  • 1
    $\begingroup$ maybe Limit[expr, d -> 3 ] /. x->0? $\endgroup$
    – kglr
    Jul 25, 2018 at 14:57
  • $\begingroup$ What about Replace[expr, t_Times :> Distribute@t, All] /. d -> 3 /. x -> 0? $\endgroup$
    – Lukas Lang
    Jul 25, 2018 at 15:08
  • $\begingroup$ @kglr That does give the correct result, but I don't want to have to do any manipulations other than /. d->3 /. x->0, that is the point, it shouldn't be necessary. $\endgroup$
    – Jansen
    Jul 25, 2018 at 18:40
  • $\begingroup$ @LukasLang Sorry I should've mentioned that that's not what I'm looking for either. Of course it does work (just Expand should work too), but I want to keep the expression as close as possible to the simplified form, ideally just changing the already present powers of x appropriately to make it manifestly finite. $\endgroup$
    – Jansen
    Jul 25, 2018 at 18:44

2 Answers 2

2
$\begingroup$

Apart may be what you want. In the case of expr, it appropriately collects the powers of x so that they do not diverge at d->3.

Apart[expr]

b c x^(-4 + 2 d) + x^(-3+d) (b + a x + b x^2)

This does not increase the expression's complexity much, and gives the appropriate results after substitution:

Apart[expr] /. d -> 3

b + a x + b x^2 + b c x^2

Apart[expr] /. d -> 3 /. x -> 0

b

Apart is usually reasonably fast, and I'm not convinced there is a simpler way to manage the particular expression in Mathematica besides, conceptually, Limit. Its usual purpose is in rewriting rational expressions, such as these, to minimize (or in this case mostly eliminate) the denominators.

$\endgroup$
1
  • $\begingroup$ Thanks, that's a nice try. When used inside Collect it does decently, I have an expression with a LeafCount of 1454 and this takes it to 2000. However I also did this one by hand as a test, keeping the expression as is and only modifying the powers where necessary. This actually brought the LeafCount down by 4. There should be some replacement rule that automates this. $\endgroup$
    – Jansen
    Jul 26, 2018 at 15:36
0
$\begingroup$

I found one way to automate what you would do yourself, ending up with an expression very close to the original:

You apply this function:

regulateExpression[expr,x,d->3]

where the function is this:

regulateExpression[expr_, x_, repl_] := expr /. x^p_ factor_ /; (p < 0/. repl) :> 
decreasePower[factor, x, -p, repl]

This finds the problematic powers (those that can become negative), removes them and applies decreasePower to the expression that multiplies that power.

The function that does the work is decreasePower. It's rather lengthy, but it basically just encodes the mathematical identities regarding powers.

The first argument is the expression it's applied to, the second the variable, the third the power of that variable by which it should be divided, and the fourth the replacement rule that sets the minimum value of the parameter occurring in the powers (d in the question).

decreasePower[(a_ : 1) x_^(q_ : 1), x_, n_, repl_] /; (q >= n /. repl) := a x^(q - n)
decreasePower[a_, x_, 0, repl_] := a
decreasePower[a_ + b_, params__] := decreasePower[a, params] + decreasePower[b, params]
decreasePower[a_^p_, x_, n_, repl_] := decreasePower[a, x, n/p, repl]^p
decreasePower[a_*b_, x_, n_, repl_] /; FreeQ[a, x] := a decreasePower[b, x, n, repl]
decreasePower[a_*b_, x_, n_, repl_] /; (0 == a /. repl /. x -> 0) := decreasePower[decreasePower[a, x, 1, repl] b, x, n - 1, repl]

This works for my current cases, I'm not sure how general it is beyond that, but I'll update if I have any improvements.

$\endgroup$

Your Answer

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

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