Changes from Legacy (v0.0)¶
Note
It should not be necessary to make changes to any CMakeLists.txt. Newly added files should be automatically detected. Contact main developers if you find limitations in this.
Set paths to dependencies in the CMakeUserPresets.txt, and not directly in the CMakeLists.txt. An exception happens when adding a new executable to the src/examples directory.
The current version of the DynaPlex library uses a similar API to the legacy version. However, several changes have been made:
StateCategory: - In Legacy DynaPlex, the flow of the program could be determined by the functions
bool AwaitsAction(const State& state),bool IsFinal(const State& state), and for the case of multiple task types, alsoint TaskType(State& state). This was effective but a bit cumbersome, and the new version instead supports all functionality inDynaPlex::StateCategory GetStateCategory(const state& state). StateCategory can be eitherIsAwaitEvent();,IsAwaitAction();, orIsFinal();. Moreover, apart from having these three possible values, it also supports an index:auto cat = StateCategory::AwaitAction(int64_t index);Index may be useful when you have a range of actions that must be performed sequentially after a single event, e.g. actions for various entities in your model. Indices will also support task types.
It is recommended to simply have
StateCategoryas a member variable toState, so that it can be kept up-to-date easily and returned fromGetStateCategory.
Action Type: Actions transitioned from
size_t(unsigned) toint64_t(signed). This change was made for several reasons: - Improved compatibility with Torch, which usesint64_t. -int64_tensures consistency across platforms, streamlining interoperability. - The library can support negative actions in future DynaPlex versions. - Usingint64_tfor both input actions and internal logic simplifies implementation as an action can be subtracted from a number without casting.Static Info Communication: Attributes like the number of allowed actions, number of features, and
alpha(nowdiscount_factor) no longer come from member functions likeNumFeatures()orNumValidActions()or from thealphamember variable. Instead, this information is packaged and provided whenGetStaticInfo()is called, offering future flexibility and other benefits.Namespaces: Strict requirements for namespaces facilitate copying and pasting an MDP, changing identifiers, and adding new MDPs, as discussed extensively above.
Data Types for Modeling: - State and MDP integer elements are preferably
int64_t. - For continuous variables, usedouble.Event Type: By default, events are
int64_t, but manual overrides remain possible.MDP Constructor: Every MDP should have a constructor accepting a
const VarGroup&. TheVarGroupbehaves similarly to a JSON file or nested dictionary, albeit with some restrictions (lists must be homogeneous and root must be object/dict). This consistent construction method: - Enables the uniform creation of MDPs and type erasure. This means any MDP can be retrieved with a single function, and there’s a singular typeDynaPlex::MDPthat can house every MDP. - Streamlines algorithm writing, compilation, and Python bindings. - Since the MDP is defined by these variables, a unique identifier can be generated from them, eliminating the need to manually implement and updateGetIdentifier. - Enables very flexible configuration of any MDP.VarGroup Usage: The
VarGroupis frequently used throughout the code. For its syntax, refer totests/other_unit_tests/t_model_provider.cppandt_initiateclasswithvargroup.cppin the same directory. Apart from providing a constructor of the MDP based onVarGroup, you’ll need to: - ConvertMDP::StatetoVarGroup, facilitating state console printing and conversion to native Python objects, as shown inlost_sales.cpp. - Provide a reverse conversion, as shown inlost_sales.cpp.