Open zsunberg opened 4 years ago
My preferences are
@findmyway it looked like you had some ideas in #1 - if you're up for it, you could take a stab at implementing something and then we could discuss it.
My preferences:
MCTSPreferedStyle(env) -> StateBased/CopyEnvBased
, by default we stick with the one available (if both are provided, we can use either one by default and still tell the user that by defining MCTSPreferedStyle
one can choose a more efficient solution)hasmethod(clone, (env_type,)) || hasmethod(setstate!, (env_type, state_type)) || @warn
(if we decide to check method signatures in 1.))?@findmyway I like your idea for for (4)
generally should implement optional interfaces as much as possible
If these are "industrial-grade" environment writers, like people wrapping gym or something, then I agree, but we should be careful - if it's someone in environmental engineering who has a cool model of a water system, we should not accidentally make them think they need to implement state
or setstate!
if they don't need it for the solver they want to use :)
most can be defined by default implementations
Make sure to weigh in on #6 :)
Ok. Given that we agree on (2), I think this package should contain:
requirements_met(list) # returns a boolean
show_requirements(list; show_method_candidates=true) # prints a nice list with check marks
where list
is an iterable that contains either (function, arg, arg)
, (function, Tuple{argtype, argtype})
or some kind of Or
item that we create to deal with "or" cases. We could also try to make it handle just functions.
Anyone want to take a crack at it?
Given the importance that provided
will have, I think we should include checks for it, e.g. in requirements_met
. It may be too easy for an environment author to forget to put an @provided
in front of an optional interface function.
Maybe it's just me, but I am getting confused here.
Given the importance that provided will have, I think we should include checks for it, e.g. in requirements_met.
I think we should be more clear about who this check tool is intended for. Are we agreed on the role of the environment writer here? I agree with @findmyway that environments should be written w/o knowledge of algorithms/solvers. I was under the impression the requirements check was for algorithm writers:
In #1, several people talked about a way for algorithm writers to specify requirements.
@zsunberg the functions you listed in your last comment don't take algorithms into account in any way? Don't we need some information from the algorithm writer to say whether requirements are met? Or are you describing some kind of interface for algorithm writers?
EDIT: Sorry, I think I found the source of my confusion. Is list
provided by the algorithm writer?
@darsnack Thanks for bringing this up - I think it is useful to talk about.
Yes, you are right - list
would be provided by the algorithm writer (maybe one day we can do some fancy analysis that automatically generates it).
There are really three roles and 2 contexts that we should be thinking about for this package:
environments should be written w/o knowledge of algorithms/solvers
environment developers should certainly do this, but environment tinkerers who only want to start out with one algorithm should probably start out only implementing the optional functions that are needed to use the algorithm that they want to.
I see provided
as a mechanism for these communication flows:
Requirements is a mechanism for these communication flows:
In other words, I don't think algorithm tinkerers will ever specify requirements and I don't think environment developers will ever look at them. They are mostly for communication from developers to tinkerers, whereas provided
will be used between developers and tinkerers.
the functions you listed in your last comment don't take algorithms into account in any way? Don't we need some information from the algorithm writer to say whether requirements are met? Or are you describing some kind of interface for algorithm writers?
Yeah, I'm not sure exactly what the usage would look like. I was imagining that a friendly algorithm writer might write something like this:
function learn(env::AbstractEnv)
# construct requirements list
# ...
if !requirements_met(list)
@warn("There were missing requirements for <algorithm name>")
show_requirements(list)
end
# run the algorithm
end
and/or, they might write a function called determine_requirements
put in their documentation:
to see if your environment meets the requirements for the algorithm, run
CommonRLInterface.show_requirements(determine_requirements(env))
I'm not sure if we can do anything more than that because we haven't specified how an algorithm should look (and shouldn't) in this package.
Maybe the requirements functionality should go in another package, e.g. RLEnvironmentLinter.jl?
Okay that clears a lot up. Based on that description, I think we need args + types as part of requirements for the requirements_met
check to be reliable. If these functions were purely tools (e.g. for linting only), then we could get away with checking only function names and printing what function we detected as matching. But to be usable within developed code, we need types.
Maybe it's just me, but I am getting confused here.
Given the importance that provided will have, I think we should include checks for it, e.g. in requirements_met.
Sorry, I wasn't clear. I imagined the situation, where a student or researcher, unfamiliar with the RL ecosystem in julia, has a custom environment and wants to run some algorithms on that environment. The researcher figured out that step!
, reset!
, actions
and the optional clone
should be implemented for the custom environment, but forgets to decorate clone
with @provided
. An algorithm that checks for clone
with the provided
-mechanism will complain in this case that the environment doesn't meet the requirements, and potentially leave the researcher pretty confused ("But I did implement clone
!?", "Yes, but you did not decorate it with @provided
".)
I like the idea of RLEnvironmentLinter.jl
. This could also help the environment authors to follow the maxime
generally [you] should implement optional interfaces as much as possible.
In #1, several people talked about a way for algorithm writers to specify requirements. This seems like a good idea, but designing it will be challenging. Here are a few important questions we need to answer:
clone
) or method signatures (i.e. with the argument types, e.g.clone(::YourCommonEnv)
? There are several sub-issues with this:interact!(env, a)
, to check the requirement we would have to infer (or ask the user to supply) the type ofa
. It might be possible to doBase.return_types(env->eltype(actions(env)), Tuple{typeof(env)}))
or something.clone
orsetstate!
Base.show_method_candidates
to make a report like aMethodError
, or just wait until it is erroneously called?Please weigh in!