7
$\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$
3
  • $\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
    Commented Feb 27, 2015 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$ Commented Feb 27, 2015 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
    Commented Jan 2, 2016 at 13:54

6 Answers 6

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$
6
  • $\begingroup$ very clever idea:) $\endgroup$ Commented Feb 26, 2015 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$ Commented Feb 26, 2015 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
    Commented Feb 26, 2015 at 23:00
  • $\begingroup$ @Jens +1 for reminder. I'd just use DeleteCases[..., x] instead of Select. $\endgroup$
    – Kuba
    Commented Feb 27, 2015 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
    Commented Feb 27, 2015 at 18:10
3
$\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$
1
$\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$
1
$\begingroup$
expr1 = 1/((x + a + b)  (c + d));

(*TransferOrbit's examples*)

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

Another way is to use CoefficientRules:

SimplifyDenominator[expr_] := 
Divide @@ (FromCoefficientRules[#, x] & /@ 
MapAt[Most, CoefficientRules[#, x] & /@ NumeratorDenominator[expr], {2}])

SimplifyDenominator /@ {expr1, expr2, expr3, expr4, expr5} //     
Column[#, Spacings -> 1.5, ItemStyle -> 16] &

enter image description here

$\endgroup$

Your Answer

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