Hi,
I am currently trying to write some custom simplification rules throughout different stages of a symbolic manipulation process.
One thing I noticed is that no matter how I try, I can’t come up with a rule that cancels literal rationals of the form n//1
where n is a literal int. Later in the simplification process, the presence of this rational causes some breaking bugs (integer overflows during trying to apply some of the base rewrite rules), so I unfortunately need ot deal with this issue.
From reading the src
files, it seems that this could be solved via using is_literal_number()
and the ::()
match predicate in @rules as in the docs.
I have however failed to write a function like this. The bellow example illustrates my attempt.
A minimal reproducible example is:
using Symbolics
using SymbolicUtils: Chain, is_literal_number
@syms x
examp = x//1 + 3//1 + 2*x//1
sim_examp = simplify(examp)
#(3//1) + 3x
#sanity check, via custom rule. We don't expect this to work...
rw = @rule ~x//1 => ~x
sim_examp2 = simplify(examp, rewriter = Chain([rw]))
#(3//1) + 3x
rw_literal = @rule ~x::(λ -> (is_literal_number(λ) && isa(λ,Rational) && (denominator(λ) == 1))) => numerator(~x)
sim_examp3 = simplify(examp, rewriter = Symbolics.Postwalk(rw_literal))
#(3//1) + 3x
#yet....
sim_examp4 = rw_literal(3//1)
# 3 (!!!!!)
#sanity check...
cprint(x) = println(x," : ", is_literal_number(x), " : ", isa(x,Rational) && denominator(x) == 1)
trick = SymbolicUtils.Postwalk(cprint) #this walks the expression and prints the predicate
trick(examp)
#=
3//1 : true : true - ?
3 : true : false
x : false : false
3x : false : false
(3//1) + 3x : false : false
=#
I am especially confused why the rewrites fails to match into the literal (despite the subexpression meeting the predicate, as seen in the above Postwalk() debug).
Any help is greatly appreciated - I am new to SymbolicUtils.jl and CAS in general .