Skip to content

Commit

Permalink
multihypo fix #248
Browse files Browse the repository at this point in the history
  • Loading branch information
dehann committed Mar 27, 2020
1 parent 8b4845d commit 335ea49
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 18 deletions.
23 changes: 13 additions & 10 deletions src/ApproxConv.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,26 @@ function computeAcrossHypothesis!(ccwl::CommonConvWrapper{T},
count = 0
# TODO remove assert once all GenericWrapParam has been removed
# @assert norm(ccwl.certainhypo - certainidx) < 1e-6
for (mhidx, vars) in activehypo
for (hypoidx, vars) in activehypo
count += 1
if sfidx in certainidx || mhidx in certainidx || mhidx == sfidx
# hypo case mhidx, sfidx = $mhidx, $sfidx
if sfidx in certainidx || hypoidx in certainidx || hypoidx == sfidx
# hypo case hypoidx, sfidx = $hypoidx, $sfidx
for i in 1:Threads.nthreads() ccwl.cpt[i].activehypo = vars; end
approxConvOnElements!(ccwl, allelements[count])
# elseif mhidx == sfidx
# # multihypo, do conv case, mhidx == sfidx
# elseif hypoidx == sfidx
# # multihypo, do conv case, hypoidx == sfidx
# ah = sort(union([sfidx;], certainidx))
# @assert norm(ah - vars) < 1e-10
# for i in 1:Threads.nthreads() ccwl.cpt[i].activehypo = ah; end
# approxConvOnElements!(ccwl, allelements[count])
elseif mhidx != sfidx # sfidx in uncertnidx
elseif hypoidx != sfidx && hypoidx != 0 # sfidx in uncertnidx
# multihypo, take other value case
# sfidx=2, mhidx=3: 2 should take a value from 3
# sfidx=3, mhidx=2: 3 should take a value from 2
# DEBUG sfidx=2, mhidx=1 -- bad when do something like multihypo=[0.5;0.5] -- issue 424
ccwl.params[sfidx][:,allelements[count]] = view(ccwl.params[mhidx],:,allelements[count])
# sfidx=2, hypoidx=3: 2 should take a value from 3
# sfidx=3, hypoidx=2: 3 should take a value from 2
# DEBUG sfidx=2, hypoidx=1 -- bad when do something like multihypo=[0.5;0.5] -- issue 424
ccwl.params[sfidx][:,allelements[count]] = view(ccwl.params[hypoidx],:,allelements[count])
elseif hypoidx == 0
# basically do nothing since the factor is not active for these allelements[count]
else
error("computeAcrossHypothesis -- not dealing with multi-hypothesis case correctly")
end
Expand All @@ -154,6 +156,7 @@ function assembleNullHypothesis(ccwl::CommonConvWrapper{T},
maxlen::Int,
spreadfactor::Float64 ) where {T}
#
@warn "this assembleNullHypothesis method is obsolete, see e.g. `addFactor!(; nullhypo=0.1)` instead."
nhc = rand(ccwl.usrfnc!.nullhypothesis, maxlen) .- 1
val = ccwl.params[ccwl.varidx]
d = size(val,1)
Expand Down
6 changes: 4 additions & 2 deletions src/DispatchPackedConversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ function convert(
#
# TODO store threadmodel=MutliThreaded,SingleThreaded in persistence layer
usrfnc = convert(F, d.fnc)
mhcat = parseusermultihypo(d.multihypo)
# FIXME add proper nullhypo value
mhcat, nh = parseusermultihypo(d.multihypo, 0.0)

# TODO -- improve prepgenericconvolution for hypotheses and certainhypo field recovery when deserializing
# reconstitute from stored data
ccw = prepgenericconvolution(DFG.DFGVariable[], usrfnc, multihypo=mhcat)
# FIXME, add threadmodel=threadmodel
ccw = prepgenericconvolution(DFG.DFGVariable[], usrfnc, multihypo=mhcat, nullhypo=nh)
ccw.certainhypo = d.certainhypo

ret = FunctionNodeData{CommonConvWrapper{typeof(usrfnc)}}(d.fncargvID, d.eliminated, d.potentialused, d.edgeIDs, Symbol(d.frommodule), ccw, d.multihypo, d.certainhypo)
Expand Down
66 changes: 60 additions & 6 deletions src/ExplicitDiscreteMarginalizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,44 @@ end
"""
$(SIGNATURES)
This function explicitly encodes the marginalization of a discrete categorical selection variable for ambiguous data association situations. Improved implementations should implicitly induce the same behaviour through summation (integration) when marginalizing any number of discrete variables. This function populates `allelements` with particle indices associated with particular multihypothesis selection while `activehypo` simultaneously contains the hypothesis index and factor graph variables associated with that hypothesis selection. The return value `certainidx` are the hypotheses that are not in question.
This function explicitly encodes the marginalization of a discrete categorical selection variable for ambiguous data association situations. This function populates `allelements` with particle indices associated with particular multihypothesis selection while `activehypo` simultaneously contains the hypothesis index and factor graph variables associated with that hypothesis selection. The return value `certainidx` are the hypotheses that are not in question.
Output:
- certainidx: non fractional variables
- allelements: list of which particles go with which hypothesis selection
- activehypo: list of which hypotheses go with which certain + fractional variables
- mhidx: multihypothesis selection per particle idx
Example:
```julia
idx=(1,2,3)
multihypo=[1.0;0.5;0.5]
sfidx=2 # example specific
certainidx=
1-element Array{Int64,1}:
1
allelements=
3-element Array{Any,1}:
Int64[]
[1, 2, 11, ...]
[3, 4, 5, ...]
activehypo=
3-element Array{Any,1}:
(1, [1, 2])
(2, [1, 2])
(3, [2, 3])
mhidx=
100-element Array{Int64,1}:
2, 2, 3, 3, 3,...
```
Notes:
- Issue 427, race condition during initialization since n-ary variables not resolvable without other init.
DevNotes
- Improved implementations should implicitly induce the same behaviour through summation (integration) when marginalizing any number of discrete variables.
- TODO add nullhypo cases to returning result
```
# `allelements` example BearingRange [:x1, 0.5:l1a, 0.5:l1b]
# sfidx = (1=:x1,2=:l1a,3=:l1b)
Expand Down Expand Up @@ -86,6 +119,7 @@ function assembleHypothesesElements!(mh::Categorical,
# select only hypotheses that can be used (ie variables have been initialized)
@assert !(sum(isinit) == 0 && sfidx == certainidx) # cannot init from nothing for any hypothesis


mhh = if sum(isinit) < lenXi - 1
@assert isLeastOneHypoAvailable(sfidx, certainidx, uncertnidx, isinit)
@info "not all hypotheses initialized, but at least one available -- see #427"
Expand All @@ -99,12 +133,27 @@ function assembleHypothesesElements!(mh::Categorical,
mh
end

# prep mmultihypothesis selection values
mhidx = rand(mhh, maxlen) # selection of which hypothesis is correct
# prepend for the mhidx=0, bad-init-null-hypothesis case (if solving a fractional variable)
mhh = if sfidx in uncertnidx
nhw = 1.0/(length(uncertnidx)+1)
nmhw = [nhw; mhh.p]
nmhw ./= sum(nmhw) # renormalize
Categorical(nmhw)
else
mhh
end

# prep mmultihypothesis selection values
mhidx = rand(mhh, maxlen) # selection of which hypothesis is correct
pidx = 0
if sfidx in uncertnidx
# shift down to get mhidx=0 case
mhidx .-= 1
pidx = -1
end

sfincer = sfidx in certainidx
for pval in mh.p
for pval in mhh.p # mh.p
pidx += 1
pidxincer = pidx in certainidx # ??
# permutation vectors for later computation
Expand All @@ -123,15 +172,20 @@ function assembleHypothesesElements!(mh::Categorical,
iterah = Int[] # may be moot anyway, but double check first
elseif !pidxincer && !sfincer # pval >= 1e-15 && mh.p[sfidx] >= 1e-10
iterah = uncertnidx #allmhp[mh.p .> 1e-15]
elseif pidx == 0
# nullhypo for bad init case
iterah = [sfidx;]
else
error("Unknown hypothesis case, got sfidx=$(sfidx) with mh.p=$(mh.p), pidx=$(pidx)")
end
push!(allelements, iterarr)
push!(activehypo, (pidx,iterah))
end

# if mhidx == sfidx
# ah = sort(union([sfidx;], certainidx))
# # retroactively add nullhypo compensation for bad-init case (the 0 case)
# if sfidx in uncertnidx
# #
# end

return certainidx, allelements, activehypo, mhidx
end
Expand Down

0 comments on commit 335ea49

Please sign in to comment.