These all work:
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> 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