2024-02-10 19:50:50 +00:00
|
|
|
module Numerical
|
|
|
|
|
2024-02-10 22:39:26 +00:00
|
|
|
using LinearAlgebra
|
2024-02-10 19:50:50 +00:00
|
|
|
using AbstractAlgebra
|
2024-02-13 01:34:12 +00:00
|
|
|
using HomotopyContinuation:
|
|
|
|
Variable, Expression, AbstractSystem, System, LinearSubspace,
|
|
|
|
nvariables, isreal, witness_set, results
|
|
|
|
import GLMakie
|
2024-02-10 19:50:50 +00:00
|
|
|
using ..Algebraic
|
|
|
|
|
|
|
|
# --- polynomial conversion ---
|
|
|
|
|
|
|
|
# hat tip Sascha Timme
|
|
|
|
# https://github.com/JuliaHomotopyContinuation/HomotopyContinuation.jl/issues/520#issuecomment-1317681521
|
|
|
|
function Base.convert(::Type{Expression}, f::MPolyRingElem)
|
|
|
|
variables = Variable.(symbols(parent(f)))
|
2024-02-13 01:34:12 +00:00
|
|
|
f_data = zip(coefficients(f), exponent_vectors(f))
|
2024-02-10 19:50:50 +00:00
|
|
|
sum(cf * prod(variables .^ exp_vec) for (cf, exp_vec) in f_data)
|
|
|
|
end
|
|
|
|
|
|
|
|
# create a ModelKit.System from an ideal in a multivariate polynomial ring. the
|
|
|
|
# variable ordering is taken from the polynomial ring
|
|
|
|
function System(I::Generic.Ideal)
|
|
|
|
eqns = Expression.(gens(I))
|
|
|
|
variables = Variable.(symbols(base_ring(I)))
|
|
|
|
System(eqns, variables = variables)
|
|
|
|
end
|
|
|
|
|
2024-02-10 22:39:26 +00:00
|
|
|
# --- sampling ---
|
|
|
|
|
|
|
|
function real_samples(F::AbstractSystem, dim)
|
|
|
|
# choose a random real hyperplane of codimension `dim` by intersecting
|
|
|
|
# hyperplanes whose normal vectors are uniformly distributed over the unit
|
|
|
|
# sphere
|
|
|
|
# [to do] guard against the unlikely event that one of the normals is zero
|
|
|
|
normals = transpose(hcat(
|
|
|
|
(normalize(randn(nvariables(F))) for _ in 1:dim)...
|
|
|
|
))
|
|
|
|
cut = LinearSubspace(normals, fill(0., dim))
|
|
|
|
filter(isreal, results(witness_set(F, cut)))
|
|
|
|
end
|
|
|
|
|
2024-02-13 01:34:12 +00:00
|
|
|
AbstractAlgebra.evaluate(pt::Point, vals::Vector{<:RingElement}) =
|
|
|
|
GLMakie.Point3f([evaluate(u, vals) for u in pt.coords])
|
|
|
|
|
|
|
|
function AbstractAlgebra.evaluate(sph::Sphere, vals::Vector{<:RingElement})
|
|
|
|
radius = 1 / evaluate(sph.coords[1], vals)
|
|
|
|
center = radius * [evaluate(u, vals) for u in sph.coords[3:end]]
|
|
|
|
GLMakie.Sphere(GLMakie.Point3f(center), radius)
|
|
|
|
end
|
|
|
|
|
2024-02-10 19:50:50 +00:00
|
|
|
end
|