Solve can not solve nonlinear symbolic equations

It seems like symbolic_solve doesn’t symbolically solve nonlinear equations yet. Is this a feature that will be added in the future, so that I for example could do the following? Or is there some alternative way to do this?

using Symbolics, LinearAlgebra, Nemo

@variables e_x[1:3]
heading = 0.01

eqs = [
    atan(-e_x[2]/-e_x[1]) ~ heading
    norm(e_x) ~ 1.0
    e_x[2] ~ 1.0
]

eqs = Symbolics.scalarize.(reduce(vcat, Symbolics.scalarize.(eqs)))
println("Equations: ", eqs)
println("Solution of e_x[1]: ", symbolic_solve(eqs, e_x[1]))
println("Solution of e_x: ", symbolic_solve(eqs, e_x))
println("Solution of e_x[2] in equation $(eqs[1]): ", symbolic_solve(eqs[1], e_x[2]))
println("Solution of e_x[2] in equation $(eqs[2]): ", symbolic_solve(eqs[2], e_x[2]))
println("Solution of e_x[2] in equation $(eqs[3]): ", symbolic_solve(eqs[3], e_x[2]))

output:

Equations: Equation[atan(e_x[2] / e_x[1]) ~ 0.01, sqrt(abs2(e_x[3]) + abs2(e_x[1]) + abs2(e_x[2])) ~ 1.0, e_x[2] ~ e_x[1]]
┌ Warning: Solve can not solve this input currently
└ @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:169
Solution of e_x[1]: nothing
┌ Warning: Solve can not solve this input currently
└ @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/main.jl:169
Solution of e_x: nothing
┌ Warning: Var not present in given expression
└ @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/ia_main.jl:275
Solution of e_x[2] in equation atan(e_x[2] / e_x[1]) ~ 0.01: Any[]
┌ Warning: Var not present in given expression
└ @ Symbolics ~/.julia/packages/Symbolics/GYV9b/src/solver/ia_main.jl:275
Solution of e_x[2] in equation sqrt(abs2(e_x[3]) + abs2(e_x[1]) + abs2(e_x[2])) ~ 1.0: Any[]
Solution of e_x[2] in equation e_x[2] ~ e_x[1]: SymbolicUtils.BasicSymbolic{Real}[e_x[1]]

Note that there is no generic algorithm for solving nonlinear systems. Some special cases are handled by each CAS, but it is very easy to run into systems that don’t have a closed-form solution, or the CAS cannot obtain it.

3 Likes

We could implement this in Symbolics. It is definitely worth opening an issue.

For future reference, Maple seems to produce a sensible answer

solve([
    arctan((-e_x[2])/(-e_x[1])) = 0.01,
    Norm(Vector(3,symbol=e_x)) = 1,
    e_x[2] = 1
]);

{e_x[1] = 99.99666664, e_x[2] = 1., e_x[3] = 99.99666664*I}, {e_x[1] = 99.99666664, e_x[2] = 1., e_x[3] = -99.99666664*I}
1 Like