Skip to content

Commit

Permalink
Merge pull request #272 from JuliaRobotics/master
Browse files Browse the repository at this point in the history
release v0.8.4-rc1
  • Loading branch information
dehann committed Jan 21, 2024
2 parents 2c16396 + 11f4dc9 commit ce8c995
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 108 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Expand Up @@ -15,8 +15,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.9'
- '~1.10.0-0'
- '1.10'
- 'nightly'
os:
- ubuntu-latest
Expand Down
7 changes: 4 additions & 3 deletions Project.toml
@@ -1,7 +1,7 @@
name = "ApproxManifoldProducts"
uuid = "9bbbb610-88a1-53cd-9763-118ce10c1f89"
keywords = ["MM-iSAMv2", "SLAM", "inference", "sum-product", "belief-propagation", "nonparametric", "manifolds", "functional"]
version = "0.8.3"
version = "0.8.4"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Expand Down Expand Up @@ -46,7 +46,7 @@ Manifolds = "0.9"
ManifoldsBase = "0.14, 0.15"
NLsolve = "3, 4"
Optim = "1"
RecursiveArrayTools = "2"
RecursiveArrayTools = "2, 3.3"
Reexport = "0.2, 1.0"
Requires = "0.5, 1"
Rotations = "1"
Expand All @@ -61,12 +61,13 @@ ApproxManiProdGadflyExt = "Gadfly"
[extras]
BSON = "fbb218c0-5317-5bc6-957e-2ee96dd4b1f0"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
Rotations = "6038ab10-8711-5258-84ad-4b1120ba62dc"
TensorCast = "02d47bb6-7ce6-556a-be16-bb1710789e2b"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["BSON", "DataFrames", "Rotations", "TensorCast", "Test"]
test = ["BSON", "DataFrames", "JSON3", "Rotations", "TensorCast", "Test"]

[weakdeps]
Gadfly = "c91e804a-d5a3-530f-b6f0-dfbca275c004"
2 changes: 1 addition & 1 deletion ext/ApproxManiProdGadflyExt.jl
Expand Up @@ -5,7 +5,7 @@ using Colors
using Manifolds
using ApproxManifoldProducts: BallTreeDensity, ManifoldKernelDensity

import ApproxManifoldProducts: plotCircBeliefs, plotKDECircular, plotMKD
import ApproxManifoldProducts: plotCircBeliefs, plotKDECircular, plotMKD, addtheta, difftheta


include("CircularPlotting.jl")
Expand Down
9 changes: 5 additions & 4 deletions src/ApproxManifoldProducts.jl
Expand Up @@ -8,7 +8,7 @@ import TransformUtils as TUs
import Rotations as _Rot

import ManifoldsBase
import ManifoldsBase: AbstractManifold
import ManifoldsBase: AbstractManifold, distance
using RecursiveArrayTools: ArrayPartition
export ArrayPartition

Expand All @@ -29,10 +29,10 @@ using Distributions

import Random: rand

import Base: *, isapprox, convert, show
import LinearAlgebra: rotate!
import Base: *, isapprox, convert, show, eltype
import LinearAlgebra: rotate!, det
import Statistics: mean, std, cov, var
import KernelDensityEstimate: getPoints, getBW
import KernelDensityEstimate: getPoints, getBW, evalAvgLogL, entropy

const MB = ManifoldsBase
const CTs = CoordinateTransformations
Expand Down Expand Up @@ -72,6 +72,7 @@ include("API.jl")
include("Deprecated.jl")

# experimental
include("entities/ManellicTree.jl")
include("services/ManellicTree.jl")

# weak dependencies
Expand Down
9 changes: 5 additions & 4 deletions src/CommonUtils.jl
Expand Up @@ -2,10 +2,11 @@


function resid2DLinear(μ, mus, Lambdas; diffop::Function=-) # '-' exploits EuclideanManifold commutativity a-b = b-a
= broadcast(diffop, μ, mus) # mus .- μ ## μ .\ mus
# dμ = broadcast(diffop, μ, mus) # mus .- μ ## μ .\ mus
# @show round.(dμ, digits=4)
ret = sum( Lambdas.*dμ )
return ret
# ret = sum( Lambdas.*dμ )
r = map((mu, lam) -> diffop(μ[], mu) * lam, mus, Lambdas)
return sum(r)
end

function solveresid2DLinear!(res, x, mus, Lambdas; diffop::Function=-)::Nothing
Expand Down Expand Up @@ -71,7 +72,7 @@ function _getManifoldFullOrPart(mkd::ManifoldKernelDensity, aspartial::Bool=true
end

function Statistics.mean(mkd::ManifoldKernelDensity, aspartial::Bool=true; kwargs...)
return mean(_getManifoldFullOrPart(mkd,aspartial), getPoints(mkd, aspartial); kwargs...)
return mean(_getManifoldFullOrPart(mkd,aspartial), getPoints(mkd, aspartial), GeodesicInterpolation(); kwargs...)
end
"""
$SIGNATURES
Expand Down
3 changes: 2 additions & 1 deletion src/KernelHilbertEmbeddings.jl
Expand Up @@ -11,7 +11,8 @@ function gramLoops(MF::AbstractManifold, a::AbstractVector, b::AbstractVector, b
# a_ = a[i]
val_ = view(val, i)
@inbounds for j in eachindex(b)
val_ .+= ker(MF, a[i], b[j], bw)
ret = ker(MF, a[i], b[j], bw)
val_ .+= ret
end

return nothing
Expand Down
31 changes: 31 additions & 0 deletions src/entities/ManellicTree.jl
@@ -0,0 +1,31 @@



# """
# $TYPEDEF

# Elliptical structure for use in a (Manellic) Ball Tree.
# """
# struct HyperEllipse{P <:AbstractArray,D,DD}
# """ manifold point at which this ellipse is based """
# point::P
# """ Covariance of coords at either TBD this point or some other reference point? """
# coord_cov::SMatrix{D,D,Float64,DD}
# end

# ManellicTree

# Short for Manifold Ellipse Metric Tree
# starting as a balanced tree, relax to unbalanced in future.
struct ManellicTree{M,D<:AbstractVector,N,HL,HT}
manifold::M
data::D
weights::MVector{N,<:Real}
permute::MVector{N,Int}
# kernels::ArrayPartition{<:Number,KT}
leaf_kernels::SizedVector{N,HL}
tree_kernels::SizedVector{N,HT}
left_idx::MVector{N,Int}
right_idx::MVector{N,Int}
end

67 changes: 46 additions & 21 deletions src/services/KernelEval.jl
@@ -1,57 +1,82 @@

# also makes static
function projectSymPosDef(c::AbstractMatrix)
s = size(c)
# pretty fast to make or remake isbitstype form matrix
_c = SMatrix{s...}(c)
issymmetric(_c) ? _c : project(SymmetricPositiveDefinite(s[1]),_c,_c)
end


abstract type AbstractKernel end

@kwdef struct MvNormalKernel{T,M} <: AbstractKernel
@kwdef struct MvNormalKernel{T,M,iM} <: AbstractKernel
p::MvNormal{T,M}
sqrt_iΣ::M = sqrt(inv(p.Σ))
# TDB might already be covered in p.Σ.chol but having issues with SymPD (not particular to this AMP repo)
sqrt_iΣ::iM = sqrt(inv(p.Σ))
end

Base.eltype(mt::MvNormalKernel) = eltype(mt.p)

function MvNormalKernel(m::AbstractVector,c::AbstractArray)
_c = projectSymPosDef(c)
p=MvNormal(m,_c)
# NOTE, TBD, why not sqrt(inv(p.Σ)), this had an issue seemingly internal to PDMat.chol which breaks an already forced SymPD matrix to again be not SymPD???
sqrt_iΣ = sqrt(inv(_c))
MvNormalKernel(;p, sqrt_iΣ)
end

Statistics.mean(m::MvNormalKernel) = m.p.μ
Statistics.cov(m::MvNormalKernel) = m.p.Σ # note also about m.sqrt_iΣ


function distanceMalahanobisCoordinates(
M::AbstractManifold,
K::AbstractKernel,
q,
basis=DefaultOrthonormalBasis()
basis=DefaultOrthogonalBasis()
)
p = mean(K)
i_p = inv(M,p)
pq = Manifolds.compose(M, i_p, q)
X = log(M, p, pq)
Xc = get_coordinates(M, p, X, basis)
ϵ = identity_element(M,q)
X = log(M, ϵ, pq)
Xc = get_coordinates(M, ϵ, X, basis)
return K.sqrt_iΣ*Xc
end

function distanceMalahanobisSq(
M::AbstractManifold,
K::AbstractKernel,
q,
basis=DefaultOrthonormalBasis()
basis=DefaultOrthogonalBasis()
)
δc = distanceMalahanobisCoordinates(M,K,q,basis)
p = mean(K)
# ϵ = identity_element(M, q)
X = get_vector(M, p, δc, basis)
ϵ = identity_element(M, q)
X = get_vector(M, ϵ, δc, basis)
return inner(M, p, X, X)
end

# function distance(
# M::AbstractManifold,
# p::AbstractVector,
# q::AbstractVector,
# kernel=(_p) -> MvNormalKernel(
# p=MvNormal(_p,SVector(ones(manifold_dimension(M))...))
# ),
# distFnc::Function=distanceMalahanobisSq
# )
# distFnc(M, kernel(p), q)
# end

function _distance(
M::AbstractManifold,
p::AbstractVector,
q::AbstractVector,
kernel = (_p) -> MvNormalKernel(
p=MvNormal(_p,SVector(ntuple((s)->1,manifold_dimension(M))...))
),
distFnc::Function=distanceMalahanobisSq,
# distFnc::Function=distanceMalahanobisSq,
)
distFnc(M, kernel(p), q)
end


"""
$SIGNATURES
$SIGNATURES
Normal kernel used for Hilbert space embeddings.
"""
ker(M::AbstractManifold, p, q, sigma::Real=0.001) = exp( -sigma*(distance(M, p, q)^2) )
ker(M::AbstractManifold, p, q, sigma::Real=0.001, distFnc=(_M,_p,_q)->distance(_M,_p,_q)^2) = exp( -sigma*distFnc(M, p, q) ) # _distance(M,p,q) #

0 comments on commit ce8c995

Please sign in to comment.