6
$\begingroup$

I have a set of expressions that contains terms like $\frac{1}{(x + a + b)(c+d)}$. I would like to simplify the denominator so that products of $a,b,c,d$ are dropped, but $x c$ and $x d$ are kept. That is, the expression should be approximated as $\frac{1}{(c+d)x+a+b}$. One obvious way to do this is to use: 1/(Expand[Denominator[TheOriginalFraction]] /. {a*c -> 0, a*d -> 0, b*c -> 0, b*d -> 0}).

While this works, it's clunky and inconvenient for dealing with more complicated expressions. For example, a sum of several fractions of this form would require isolation of each fraction first, then pattern replacement, then reconstruction of the full expression.

Is there a more efficent and general method for this type of replacement/pattern matching?

$\endgroup$
  • $\begingroup$ There is a "typo" problem in your post : the approximated expression you give in your question does not correspond to what your code outputs. Also, according to your comment to an answer below, it is not clear what you precisely want. And, what do you exactly mean by "... fractions of this form ..." ? $\endgroup$ – SquareOne Feb 27 '15 at 13:55
  • $\begingroup$ Oops. You are correct. Thanks! I had simplified the problem I was actually solving and accidentally introduced errors! That's embarrassing. The answers below provide enough info to do what I need. $\endgroup$ – sm_physicist Feb 27 '15 at 15:08
  • $\begingroup$ How about you replace a->epsilon a, b->epsilon b, c->epsilon c, etc., then do a Series expansion in the denominator to first order in epsilon. Then Normal to turn it into a regular expression, and apply epsilon->1. $\endgroup$ – QuantumDot Jan 2 '16 at 13:54
7
$\begingroup$

Here is how I would do it:

expr = 1/((x + a + b) (c + d));

Limit[
  ϵ expr /. Thread[# -> ϵ #] &@Select[Variables[expr], # =!= x &],
 ϵ -> 0
]

(* ==> 1/(c x + d x) *)

I replaced all variables except x by ϵ times themselves and took the limit of ϵ times the original expression as ϵ goes to zero. This will leave only terms linear in the small variables in the denominator.

$\endgroup$
  • $\begingroup$ very clever idea:) $\endgroup$ – Algohi Feb 26 '15 at 22:00
  • $\begingroup$ This is a bit off the mark, as it explicitly eliminates a and b from the expression. It is a nice method of replacement, though. $\endgroup$ – sm_physicist Feb 26 '15 at 22:30
  • 1
    $\begingroup$ @sm_physicist But your desired replacement is mathematically inconsistent. I assumed you wanted correct math. If not, you have to do pattern matching, but then you should be very specific about the rules for each of your variables. $\endgroup$ – Jens Feb 26 '15 at 23:00
  • $\begingroup$ @Jens +1 for reminder. I'd just use DeleteCases[..., x] instead of Select. $\endgroup$ – Kuba Feb 27 '15 at 8:05
  • 1
    $\begingroup$ @Kuba Your'e right about DeleteCases. The Select just reflects my thought process... I want the variables to be happy that they got selected. $\endgroup$ – Jens Feb 27 '15 at 18:10
2
$\begingroup$
expr = 1/((x + a + b) (c + d));

Based on clipping by total degree. Let me make this answer more general.

ClearAll@expand
Options[expand] = {"SmallTerms" -> Automatic, "Order" -> 1, "Except" -> {}};

expand[expr_, OptionsPattern[]] := Module[{
   t,
   vars = Fold[
     DeleteCases,
     Flatten[{OptionValue["SmallTerms"]} /. Automatic -> Variables[expr] ], 
     Flatten[{OptionValue["Except"]}]]
   },
  Normal[Series[ expr /. Thread[vars -> t vars], {t, 0, OptionValue["Order"]}]
   ] /. t -> 1
  ]

You want to expand your denominator so:

Numerator[#] / expand[Denominator[#], "Except" -> {x}] & @ expr
1/(c x + d x)

usage examples:

expand[(1 + y) (X + X^2)]
expand[(1 + y) (X + X^2), "SmallTerms" -> X]
expand[(1 + y) (X + X^2), "Except" -> X]
expand[(1 + y) (X + X^2)^6 + y^2, "Order" -> 4, "Except" -> y]
X
X+X y
X+X^2+X y+X^2 y
y^2
$\endgroup$
2
$\begingroup$

I appreciate Jens's answer. However I want to answer literally

For example, a sum of several fractions of this form would require isolation of each fraction first, then pattern replacement, then reconstruction of the full expression.

Is there a more efficent and general method for this type of replacement/pattern matching?

Here are nice functions ExpandNumerator and ExpandDenominator. They didn't reconstruct sum of fractions

approx[expr_] := ExpandNumerator@ExpandDenominator@expr /. 
   Except[x, a_Symbol] Except[x, b_Symbol] :> 0

(a x + b)/((x + a + b) (c + d)) + (x^2 + 
     a) b/((x + a + b + f) (x + c + d) (x + g)) // approx

enter image description here

Of course, you can write more general patter. Note that ___ is unnecesary in Times since it orderless.

$\endgroup$
1
$\begingroup$
expr = 1/((x + a + b) (c + d));    

ExpandAll[expr] /. Times[v1_ /; v1 =!= x, v2_ /; v2 =!= x] :> 0

(*1/(c x + d x)*)
$\endgroup$
0
$\begingroup$

Given

expr = 1/((x + a + b) (c + d));
expr2 = 1/((x + a + b + f) (x + c + d));

While not the most elegant, this appears to do the trick

simpliFunc = Numerator[#] /
  Plus @@ Thread[
    Times[
      x^# & /@ Range[Length@Rest@CoefficientList[Expand@Denominator[#], {x}]],
      Rest@CoefficientList[ Expand@Denominator[#], {x}]
    ]
  ] &

simpliFunc@expr

enter image description here

Combined...

simpliFunc/@ (expr+expr2)

enter image description here

More complex examples:

expr4 = (a x + b)/((x + a + b) (c + d));
expr5 = (x^2 + x^b)/((x + a + b + f) (x + c + d));
expr6 = (b^x)/((x + a + b + f + g x^2) (x + c + d));

simpliFunc /@ (expr4 + expr5 + expr6)

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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