# Expression as single fraction in Symbolics.jl

**URL:** <https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816>\
**Category:** General Usage\
**Tags:** symbolics\
**Created:** [September 27, 2021, 3:29pm UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816 "2021-09-27T15:29:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [September 27, 2021, 3:29pm UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816/1 "2021-09-27T15:29:43Z")

</div>

I am using Symbolics.jl to automate some tedious mathematical operations in a large expression. I would like to express the result as a single fraction rather than the sum of several fractions. I tried to accomplish this with expand and simplify, but with no success. Is this possible? Here is a minimum working example:

```julia
using Symbolics

@variables a b c d e f g
x1 = (a+b) / (c + d) + (g+f) / (e + d)
expand(x1)

```

---

<div class="post-metadata">

**Author:** ![brianguenter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brianguenter/32/29519_2.png) [@brianguenter](https://discourse.julialang.org/u/brianguenter)\
**Post date:** [September 28, 2021, 12:13am UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816/2 "2021-09-28T00:13:51Z")

</div>

These all work:

```julia
simplify_fractions(a/(c+d) + b/(c+d))
(a + b) / (c + d)

julia> simplify_fractions((a+b)/(c+d) + b/(c+d))
(a + 2.0b) / (c + d)

julia> simplify_fractions((a+b)/(c+d) + (b+d)/(c+d))
(a + d + 2.0b) / (c + d)

julia> simplify_fractions((a+b)/(c+d) + (b+d)/(c+a))
(a^2 + a*b + a*c + b*d + c*d + d^2 + 2b*c) / ((a + c)*(c + d))

```

You can then call simplify on the result to do more simplification, if that is possible.

However, your example doesn’t work (see below). Maybe a bug? Or maybe simplify\_fractions is not meant to be part of the public facing api? It is exported though which normally means it is part of the public api.

```julia
julia> x1 = (a+b) / (c + d) + (g+f) / (e + d)
(a + b) / (c + d) + (f + g) / (d + e)

julia> simplify_fractions(x1)
ERROR: AssertionError: i1 == i2
Stacktrace:
  [1] deflated_gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:227
  [2] gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:123
  [3] _simplifier(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:408
  [4] (::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm})(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64})
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:436
  [5] (::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}})(acc::DynamicPolynomials.Polynomial{true, Int64}, x::DynamicPolynomials.Polynomial{true, Int64})
    @ Base ./reduce.jl:81
  [6] _foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, init::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:62
  [7] foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:48
  [8] mapfoldl_impl(f::typeof(identity), op::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:44
  [9] _mapreduce_dim(f::Function, op::Function, nt::DynamicPolynomials.Polynomial{true, Int64}, A::Vector{DynamicPolynomials.Polynomial{true, Int64}}, #unused#::Colon)
    @ Base ./reducedim.jl:315
 [10] #mapreduce#672
    @ ./reducedim.jl:310 [inlined]
 [11] #reduce#674
    @ ./reducedim.jl:359 [inlined]
 [12] content
    @ ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:435 [inlined]
 [13] deflated_gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:213
 [14] gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:123
 [15] deflated_gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:224
 [16] gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:123
 [17] _simplifier(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:408
 [18] (::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm})(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64})
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:436
 [19] (::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}})(acc::DynamicPolynomials.Polynomial{true, Int64}, x::DynamicPolynomials.Polynomial{true, Int64})
    @ Base ./reduce.jl:81
 [20] _foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, init::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:62
 [21] foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:48
 [22] mapfoldl_impl(f::typeof(identity), op::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:44
 [23] _mapreduce_dim(f::Function, op::Function, nt::DynamicPolynomials.Polynomial{true, Int64}, A::Vector{DynamicPolynomials.Polynomial{true, Int64}}, #unused#::Colon)
    @ Base ./reducedim.jl:315
 [24] #mapreduce#672
    @ ./reducedim.jl:310 [inlined]
 [25] #reduce#674
    @ ./reducedim.jl:359 [inlined]
 [26] content
    @ ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:435 [inlined]
 [27] deflated_gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:213
 [28] gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:123
 [29] _simplifier(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:408
 [30] (::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm})(a::DynamicPolynomials.Polynomial{true, Int64}, b::DynamicPolynomials.Polynomial{true, Int64})
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:436
 [31] (::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}})(acc::DynamicPolynomials.Polynomial{true, Int64}, x::DynamicPolynomials.Polynomial{true, Int64})
    @ Base ./reduce.jl:81
 [32] _foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, init::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:62
 [33] foldl_impl(op::Base.BottomRF{MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:48
 [34] mapfoldl_impl(f::typeof(identity), op::MultivariatePolynomials.var"#107#108"{MultivariatePolynomials.GeneralizedEuclideanAlgorithm}, nt::DynamicPolynomials.Polynomial{true, Int64}, itr::Vector{DynamicPolynomials.Polynomial{true, Int64}})
    @ Base ./reduce.jl:44
 [35] _mapreduce_dim(f::Function, op::Function, nt::DynamicPolynomials.Polynomial{true, Int64}, A::Vector{DynamicPolynomials.Polynomial{true, Int64}}, #unused#::Colon)
    @ Base ./reducedim.jl:315
 [36] #mapreduce#672
    @ ./reducedim.jl:310 [inlined]
 [37] #reduce#674
    @ ./reducedim.jl:359 [inlined]
 [38] content
    @ ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:435 [inlined]
 [39] deflated_gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:223
 [40] gcd(p1::DynamicPolynomials.Polynomial{true, Int64}, p2::DynamicPolynomials.Polynomial{true, Int64}, algo::MultivariatePolynomials.GeneralizedEuclideanAlgorithm)
    @ MultivariatePolynomials ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:123
 [41] gcd
    @ ~/.julia/packages/MultivariatePolynomials/vqcb5/src/gcd.jl:107 [inlined]
 [42] _gcd(x::DynamicPolynomials.Polynomial{true, Int64}, y::DynamicPolynomials.Polynomial{true, Int64})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:351
 [43] gcd(x::PolyForm{Real, Nothing}, y::PolyForm{Real, Nothing})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:89
 [44] _gcd(x::PolyForm{Real, Nothing}, y::PolyForm{Real, Nothing})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:351
 [45] rm_gcds(ns::Vector{PolyForm{Real, Nothing}}, ds::Vector{PolyForm{Real, Nothing}})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:464
 [46] simplify_div(d::SymbolicUtils.Div{Real, SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing}, SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}, Nothing})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:260
 [47] (::SymbolicUtils.var"#sdiv#129")(a::SymbolicUtils.Div{Real, SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing}, SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}, Nothing})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:287
 [48] (::ComposedFunction{SymbolicUtils.var"#sdiv#129", typeof(quick_cancel)})(x::SymbolicUtils.Div{Real, SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing}, SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}, Nothing})
    @ Base ./operators.jl:938
 [49] (::SymbolicUtils.Rewriters.Walk{:post, ComposedFunction{SymbolicUtils.var"#sdiv#129", typeof(quick_cancel)}, typeof(similarterm), false})(x::SymbolicUtils.Div{Real, SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing}, SymbolicUtils.Mul{Real, Int64, Dict{Any, Number}, Nothing}, Nothing})
    @ SymbolicUtils.Rewriters ~/.julia/packages/SymbolicUtils/vKBkE/src/rewriters.jl:164
 [50] simplify_fractions(x::SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing}; polyform::Bool)
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:289
 [51] simplify_fractions(x::SymbolicUtils.Add{Real, Int64, Dict{Any, Number}, Nothing})
    @ SymbolicUtils ~/.julia/packages/SymbolicUtils/vKBkE/src/polyform.jl:283
 [52] simplify_fractions(n::Num; kw::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Symbolics ~/.julia/packages/Symbolics/mFWWM/src/Symbolics.jl:127
 [53] simplify_fractions(n::Num)
    @ Symbolics ~/.julia/packages/Symbolics/mFWWM/src/Symbolics.jl:127

```

---

<div class="post-metadata">

**Author:** ![greatpet](https://avatars.discourse-cdn.com/v4/letter/g/e495f1/32.png) [@greatpet](https://discourse.julialang.org/u/greatpet)\
**Post date:** [September 28, 2021, 10:00am UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816/3 "2021-09-28T10:00:10Z")

</div>

I can reproduce the bug on my laptop with Julia 1.6.3. By the way, if you genuinely deal with only rational functions (no trig functions, square roots, etc.), a specialized package Nemo.jl can handle it:

```julia
julia> using Nemo

julia> R, (a,b,c,d,e,f,g) = PolynomialRing(QQ, ["a", "b", "c", "d", "e", "f", "g"]);

julia> x1 = (a+b) // (c + d) + (g+f) // (e + d)
(a*d + a*e + b*d + b*e + c*f + c*g + d*f + d*g)//(c*d + c*e + d^2 + d*e)

```

Floating point numbers cannot be used, as far as I know. Also, both the numerator and denominator are always in the expanded form in Nemo.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [September 28, 2021, 11:45am UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816/4 "2021-09-28T11:45:14Z")

</div>

Yeah open an issue. We need to collect these kinds of cases.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [September 28, 2021, 11:04pm UTC](https://discourse.julialang.org/t/expression-as-single-fraction-in-symbolics-jl/68816/5 "2021-09-28T23:04:32Z")

</div>

Thank you for your responses. I opened an [issue](https://github.com/JuliaSymbolics/Symbolics.jl/issues/398) and also noted that `simplify_fractions` is not in the documentation.
