Hi all, I am trying to throw more helpful errors in POMDPs.jl. This package has two nested interfaces. The explicit interface deals with explicit probability distributions; the generative interface samples from distributions that are never explicitly defined. If the explicit interface is implemented for a problem, functions from the generative interface will call explicit functions and sample from the distributions using
The problem is that when parts of the interface are not implemented correctly, the
MethodErrors are very misleading. Users often think they need to implement the explicit interface, which is very difficult or impossible for many problems. The main issue is here: https://github.com/JuliaPOMDP/POMDPs.jl/issues/260
Below is a cartoon version of the problem.
gen is a simplified version of the generative interface, and
transition is a function from the explicit interface - it should return a distribution.
module POMDPs export POMDP, gen, transition, solve abstract type POMDP end function transition end gen(m, s, a) = rand(transition(m, s, a)) function solve(m::POMDP) # in reality this does something much more complex, but uses gen sp = gen(m, 1, 1) policy = nothing return policy end end using Main.POMDPs struct MyPOMDP <: POMDP end solve(MyPOMDP()) # this throws a MethodError for transition - very confusing!!
transitionis called from
transitionis not implemented, an error saying roughly “no state transition model was specified, you can implement it with
gen(MyPOMDP, s, a)or
transition(MyPOMDP, s, a)” should be thrown.
transitionis called outside of
MethodErrorshould be thrown for
- There can be no overhead when
transitionis implemented - these functions run in inner loops
My current best idea is to provide a default implementation for
transition that analyzes the stack trace to see if it was called from within
gen and then throws an error based on that.
This does not seem like a very good approach - does anyone have a better idea?