Symbolics to Float64

I have the output from symbolics_solve

What am I to do with this? Can someone tell me how to access this information in a usable form as in I want the maximum value for this output ?

The answer should be
π*2 + π var"##320"

I think the answer given is incorrect?

Cheers, Paul

1 Like

The solution to cos(x)=0 would be π/2 + πn. acos(0)=π/2, so that part at least is right, if weirdly unsimplified. Not sure why there’s a π*2n there.

symbolics_to_float

I am not aware of this function? Would you please indicate how to use it and let me know if it is in the Symbolics library? I do not find it there.

2 Likes

It’s not apparent how this helps for an expression that isn’t equal to an exact number

julia> foo
acos(0) + π*2var"##225"

julia> Symbolics.symbolic_to_float(foo)
ERROR: UndefVarError: `_x` not defined

Not that there is a maximum for a linear function. The more pressing issue is that the solution seems wrong, unless I’ve sorely misunderstood what symbolics_solve is solving:

julia> [(x->(x,cos(x)))(substitute(acos(0)+pi*2x, Dict(x=>z))) for z in -2:2]
5-element Vector{Tuple{Num, Num}}:
 (-10.995574287564276, -4.286263797015736e-16)
 (-4.71238898038469, -1.8369701987210297e-16)
 (1.5707963267948966, 6.123233995736766e-17)
 (7.853981633974483, 3.061616997868383e-16)
 (14.137166941154069, 5.51091059616309e-16)

julia> (x->(x,cos(x))).([-5pi/2, -3pi/2, -pi/2, pi/2, 3pi/2, 5pi/2]) # zeros of cos(x)
6-element Vector{Tuple{Float64, Float64}}:
 (-7.853981633974483, 3.061616997868383e-16)
 (-4.71238898038469, -1.8369701987210297e-16)
 (-1.5707963267948966, 6.123233995736766e-17)
 (1.5707963267948966, 6.123233995736766e-17)
 (4.71238898038469, -1.8369701987210297e-16)
 (7.853981633974483, 3.061616997868383e-16)

I think the answer given is correct, however, just in a very awkward form. I have no idea how you would use it, say to give an explicit solution to the problem, or as I intended, to find the maximum value of a third derivative of a function.

The zeroes of cosine are π apart, the output’s elements are 2π apart, which I evaluated earlier to check. Maybe the author @Yassin_ElBedwihy can help explain, I’m not an experienced user of Symbolics and can’t find an explanation in the documentation.

If you were trying to find a maximum value of a function by checking where its derivative is zero, there isn’t always one unique place for its maximum. Sine peaks at 1 periodically, and it coincides with only “half” its derivative cosine’s zeroes.

You are correct. I would like to ask however, which would you prefer? @Benny @Paul_Warburton

symbolic_solve(cos(x), x)
-> pi/2 + pi*N

or
image
similarly:

symbolic_solve(sin(x), x)
-> pi*N

or
image

To me, the first ones seem obviously better for showing the periodicity cos(x)=0 (wolframalpha.com). Turns out Wolfram Alpha could do something like the second shifted ones for more complex equations, I tried the example in the symbolic_solve announcement sin(x^2 +1)^2 + sin(x^2 + 1) + 3=0 (wolframalpha.com) and clicking “more roots” and “exact forms” gives 8 roots but half of them are shifted (incidentally they also simplify away the leading 1//2 and 4 coefficients by multiplying). I’m not positive but it looks like those could also be collapsed into 4, which would also deviate from the symbolic_solve output.

I also think the first form is easier to use, however, it does not explicitly tell you what N is, this would need to be defined somehow.

In Mathematica you can access this information if required but I don’t remember how. I think it is using the substitution command (/.)

With the first format, is N automatically made into a variable? What will happen if there is more than 1 coefficient in the answer?

Somehow it would be most useful to be able to solve this equation then, say, plot the first 10 results for example.

I think that was just an easier shorthand for the generated var"##__", there’s no good way to generate simpler symbols that could easily collide with the user’s current or likely upcoming symbols.

There’s no “first” results for a periodic function, so we have to specify the inputs ourselves. I haven’t figured out how to reference a generated variable for substitute, but that can evaluate expressions with user-defined variables to a numerical Num, which I showed earlier. Symbolics.value(::Num) unwraps to the underlying Number subtype, could be Int, Float64, Rational{Int},etc.

The user could provide the symbols to use

That’s an idea, but we can’t possibly do it in advance when we don’t know how many generated variables would be needed. Maybe a way to do it afterward, like counting the number of generated variables and a method to replace them with a vector of enough of our own variables. Maybe there’s already a way to do that for any variables now already, I just never learned.

@Paul_Warburton @Benny , The variable information is given in the Info in blue when calling symbolic_solve.

julia> root = symbolic_solve(cos(x), x)[1]
[ Info: var"##233" ϵ Ζ
π / 2 + π*var"##233"

Afterwards, you can use Symbolics.get_variables in order to get the only variable in some printed out root and subtitute it for whatever value you want, here is 0 for example:

julia> root
π / 2 + π*var"##233"

julia> Symbolics.substitute(root, Dict(Symbolics.get_variables(root)[1]=>0))
1.5707963267948966

if you dont want it to fold, I advise using Symbolics.ssubs instead of Symbolics.substitute

julia> Symbolics.ssubs(root, Dict(Symbolics.get_variables(root)[1]=>0))
(1//2)*π

but this may break if complex nums are present in the equation

1 Like

Also, @Benny , the example sin(x^2 +1)^2 + sin(x^2 + 1) + 3=0 , this is what we currently output:

julia> symbolic_solve(sin(x^2 + 1)^2 + sin(x^2 + 1) + 3, x)
[ Info: var"##268" ϵ Ζ
[ Info: var"##271" ϵ Ζ
4-element Vector{SymbolicUtils.BasicSymbolic{Complex{Real}}}:
 (1//2)*√(-4(1 - asin((1//2)*(-1 + (0 + 1im)*√(11))) - (π*var"##268")))
 (-1//2)*√(-4(1 - asin((1//2)*(-1 + (0 + 1im)*√(11))) - (π*var"##268")))
 (1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*var"##271")))
 (-1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*var"##271")))

Which i think is correct given that we now are doing pi*N so that accounts for the 8 roots mathematica is showing, please correct me if im mistaken.

julia> root = symbolic_solve(sin(x^2 + 1)^2 + sin(x^2 + 1) + 3, x)[1]
[ Info: var"##286" ϵ Ζ
[ Info: var"##289" ϵ Ζ
(1//2)*√(-4(1 - asin((1//2)*(-1 + (0 + 1im)*√(11))) - (π*var"##286")))

julia> Symbolics.substitute(root, Dict(Symbolics.get_variables(root)[1]=>0))
0.5279984677890944883195449371158433523824004298838572993541435240980004752596828 + 1.238360873135359676020102047979975902000464573894570345327213453060598580248021im

which is one of the mathematica roots found:
image
and since matheamtica is looping over 2pi*N, our root equals this and some other shifted root they have.

1 Like

I’m assuming your result is on an updated version. For reference, this is the result on Julia v1.10.5, Symbolics v6.5.0, Nemo v0.46.2:

julia> symbolic_solve(sin(x^2 + 1)^2 + sin(x^2 + 1) + 3, x)
[ Info: var"##230" ϵ Ζ
[ Info: var"##233" ϵ Ζ
4-element Vector{SymbolicUtils.BasicSymbolic{Complex{Real}}}:
 (1//2)*√(-4(1 - asin((1//2)*(-1 + (0 + 1im)*√(11))) - (π*2var"##230")))
 (-1//2)*√(-4(1 - asin((1//2)*(-1 + (0 + 1im)*√(11))) - (π*2var"##230")))
 (1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*2var"##233")))
 (-1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*2var"##233")))

julia> symbolic_solve(sin(x^2 + 1)^2 + sin(x^2 + 1) + 3, x) # repeat shuffles the terms
[ Info: var"##240" ϵ Ζ
[ Info: var"##243" ϵ Ζ
4-element Vector{SymbolicUtils.BasicSymbolic{Complex{Real}}}:
 (1//2)*√(-4(1 - (π*2var"##240") - asin((1//2)*(-1 + (0 + 1im)*√(11)))))
 (-1//2)*√(-4(1 - (π*2var"##240") - asin((1//2)*(-1 + (0 + 1im)*√(11)))))
 (1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*2var"##243")))
 (-1//2)*√(-4(1 - asin((1//2)*(-1 - ((0 + 1im)*√(11)))) - (π*2var"##243")))

I’m really not qualified to correct any math, I’m just an occasional user (so those tips are very appreciated). I can at least note that the asin terms all have a coefficient of -1, which would simplify to +1 if we cancel out the 1/2 and -4 terms. However, Wolfram Alpha’s asin terms’ coefficients vary between +1 and -1, adding the extra π when it’s -1. I don’t know if there’s an asin identity that reconciles that and collapses the 8 roots into 4 closer spaced roots, so my earlier guess seems unfounded from my perspective, just happened to superficially resemble a simpler case we could verify.

Rather than manually tweaking expressions to compare to Wolfram Alpha results, which aren’t verified to be right either, could periodic or otherwise infinite sequence of roots be verified numerically, even within a finite range? Is there a CAS principle where solving simpler problems correctly (y^2+y+3=0, y=sin(z), z=x^2+1 would be simpler parts) would solve more complex problems correctly?

I think part of the issue here is that you are taking the arcsin of a complex number, which really means you need to use hyperbolic sin solutions.

The best way to resolve this will be to solve this problem by hand, explicitly and understand the process.

Yassin, does you code turn this into a quadratic first in sin(x^2+1), solve the quadratic then solve for x^2+1 = roots of the quadratic?

Yes, this is under development here

Well, our solver actually polynomializes this input expression and turns it into Y^2 + Y + 3 == 0. We then solve this expression and find the roots:

julia> symbolic_solve(Y^2 + Y + 3)
2-element Vector{SymbolicUtils.BasicSymbolic{Complex{Real}}}:
 (-1//2 + 0//1*im) + (0//1 + 1//2*im)*√(11)
 (-1//2 + 0//1*im) + (0//1 - 1//2*im)*√(11)

this array is then used to solve for x inside Y. so essentially we’re solving sin(x^2 + 1) == Y

@Paul_Warburton Had this comment written out yesterday and forgot to post it, hope this helps.

Computing this isnt our problem, as long as the roots are correct we dont care how the asin function carries out the computation.