Symbolics.jl problem trying to use solve_for

I’m learning how to use Symbolcs.jl.

My current work involves lines and vectors in three dimensional space.

At the suggestion of, I think Shash, at a CAJUN about a month ago, since the Symbolics variables as introduced by @variables are scalars, I’ve defined

"""
    symbolic_vector(name::Symbol, n::Integer)

Define `n` Symbolics variables hose names are based on `name` and
return a vector of those variables.
"""
function symbolic_vector(name::Symbol, n::Integer)
    eltname(name, i) = Symbol("($name)_$i")
    map(variable, map(i -> eltname(name, i), 1:n))
end

to define “vector variables”, and

"""
    vsubs(v::Vector{Symbolics.Num}, values...)

Return a list of `Pair`s suitable for constructing a `Dict` which is
suitable for passing to `Symbolics.substitute`, which
substitues each of `values` with the corresponding variable in `v`.
"""
function vsubs(v::Vector{Symbolics.Num}, values...)
	Pair.(v, values)
end

to swubstitute values for them.

I also provide qa cnvenience function for creating the parameteric formula for a line:

"""
    line(p1, p2, param)

Return the parametric formula for a point on a line which passes through points `p1` and `p2`, and has `param`.
"""
function line(p1, p2, param)
    p1 + param * (p2 - p1)
end

As a simple example, I’m trying to find the point at which two copla\nar lines intersect:

P1 = symbolic_vector(:P1, 3)
P2 = symbolic_vector(:P2, 3)
P3 = symbolic_vector(:P3, 3)
P4 = symbolic_vector(:P4, 3)
@variables r, s
L1 = line(P1, P2, r)
L2 = line(P3, P4, s)
# L1 and L2 intersect at the point where their formulas are equal:
e1 = Equation(L1, L2)

substitutions = OrderedDict(
    # expect r = s = 0.5.
    vsubs(P1, 0, -1, 0)...,
    vsubs(P2, 2, 1, 0)...,
    vsubs(P3, 0, 0, 0)...,
    vsubs(P4, 2, 0, 0)...)

eq1s = substitute(e1, substitutions)

from which I can solve in my head to r = s = 0.5.

How do I get solve_for to tell me that though?

solved = solve_for(eq1s, r)

but solved[1] is

(1//0)*(2r - 2s)

and solved[2]

(1//0)*(-1 + 2r)

show division by zero.

What am I doing wrong?

How do I get solve_for to give me solutions?

Should I be doing something else instead?

1 Like

What is variable in

function symbolic_vector(name::Symbol, n::Integer)
    eltname(name, i) = Symbol("($name)_$i")
    map(variable, map(i -> eltname(name, i), 1:n))
end

Symbolics.variable. I must have forgot to include the "using"s. I’ll check for any more later when I’m at my computer.

Here’s a file that I’ve tested and is complete:

using DataStructures
using Symbolics
using Symbolics: variable, solve_for, substitute


"""
    symbolic_vector(name::Symbol, n::Integer)

Define `n` Symbolics variables hose names are based on `name` and
return a vector of those variables.
"""
function symbolic_vector(name::Symbol, n::Integer)
    eltname(name, i) = Symbol("($name)_$i")
    map(variable, map(i -> eltname(name, i), 1:n))
end


"""
    vsubs(v::Vector{Symbolics.Num}, values...)

Return a list of `Pair`s suitable for constructing a `Dict` which is
suitable for passing to `Symbolics.substitute`, which
substitues each of `values` with the corresponding variable in `v`.
"""
function vsubs(v::Vector{Symbolics.Num}, values...)
	Pair.(v, values)
end


"""
    line(p1, p2, param)

Return the parametric formula for a point on a line which passes through points `p1` and `p2`, and has `param`.
"""
function line(p1, p2, param)
    p1 + param * (p2 - p1)
end


P1 = symbolic_vector(:P1, 3)
P2 = symbolic_vector(:P2, 3)
P3 = symbolic_vector(:P3, 3)
P4 = symbolic_vector(:P4, 3)
@variables r, s
L1 = line(P1, P2, r)
L2 = line(P3, P4, s)
# L1 and L2 intersect at the point where their formulas are equal:
e1 = Equation(L1, L2)

substitutions = OrderedDict(
    # expect r = s = 0.5.
    vsubs(P1, 0, -1, 0)...,
    vsubs(P2, 2, 1, 0)...,
    vsubs(P3, 0, 0, 0)...,
    vsubs(P4, 2, 0, 0)...)

eq1s = substitute(e1, substitutions)

solved = solve_for(eq1s, r)

println(solved)

If I define

function vector_solve_for(e::Equation, var)
	if e.lhs isa Vector && e.rhs isa Vector
		result = []
		for lr in zip(e.lhs, e.rhs)
			push!(result,
				solve_for(Equation(lr...), var))
		end
		result
	else
		solve_for(e, var)
	end
end

I can use it to get a value for r:

vector_solve_for(eq1s, r)
3-element Vector{Any}:
   s
   0.5
 NaN

but this doesn’t get me to automated solutions for both r and s.