MASA-Safe-RL 0.3.2__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4/MASA_Safe_RL.egg-info}/PKG-INFO +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MASA_Safe_RL.egg-info/SOURCES.txt +1 -0
- {masa_safe_rl-0.3.2/MASA_Safe_RL.egg-info → masa_safe_rl-0.3.4}/PKG-INFO +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/trpo.py +3 -3
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/recreg.py +7 -2
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/CPO.yaml +0 -5
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/PPOLag.yaml +0 -6
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/ProbShieldPPO.yaml +1 -6
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/RECREG_EXACT.yaml +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/RECREG_MODEL_BASED.yaml +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/recreg.yaml +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/__main__.py +5 -15
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/api.py +26 -3
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/config.py +58 -7
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/pipeline.py +7 -23
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/plot.py +117 -2
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/processing.py +139 -11
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/render.py +0 -4
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/run.py +5 -8
- masa_safe_rl-0.3.4/masa/plotting/source_registry.py +130 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/sources.py +42 -85
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/parameterized_ppo.py +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/pyproject.toml +1 -1
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/LICENSE +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MANIFEST.in +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MASA_Safe_RL.egg-info/dependency_links.txt +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MASA_Safe_RL.egg-info/entry_points.txt +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MASA_Safe_RL.egg-info/requires.txt +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/MASA_Safe_RL.egg-info/top_level.txt +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/README.md +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/a2c.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/abstract_classes.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/cpo.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/ppo.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/ppo_lag.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/prob_shield_ppo.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/on_policy/trpo_lag.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/lcrl.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/q_learning.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/q_learning_lambda.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/recovery_rl.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/recreg_exact.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/recreg_model_based.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/algorithms/tabular/sem.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/cli/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/cli/cli_app.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/base_class.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/buffers.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/configs.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/cmdp.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/ltl_safety.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/multi_agent/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/multi_agent/cmg.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/pctl.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/prob.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/constraints/reach_avoid.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/dummy.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/label_fn.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/labelled_env.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/labelled_pz_env.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/layers.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/ltl.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/metrics.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/notebook_play.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/on_policy_algorithm.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/pctl.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/pettingzoo_record_video.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/policies.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/registry.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/running_mean_std.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/schedule.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/utils.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/common/wrappers.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/QL.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/QL_LAMBDA.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/TRPO.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/TRPOLag.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/a2c.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/lcrl.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/ppo.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/recovery_rl.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/algorithms/sem.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/defaults.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/BridgeCrossing.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/BridgeCrossingV2.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ColourBombGridWorld.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ColourBombGridWorldV2.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ColourBombGridWorldV3.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ColourGridWorld.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ContinuousCartpole.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ContinuousMountainCar.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ConveyorBelt.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/DiscreteCartpole.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/DiscreteMountainCar.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/FrozenLake.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/IslandNavigation.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/MediaStreaming.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/MediaStreamingV2.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/MediaStreamingV3.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/MiniPacman.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/MiniPacmanWithCoins.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/Obstacle.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ObstacleV2.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ObstacleV3.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/ObstacleV4.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/PacmanWithCoins.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/Road1D.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/Road2D.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/pacman.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/configs/envs/sokoban.yaml +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/cartpole.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/mountain_car.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/obstacle.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/obstacle_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/obstacle_v3.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/obstacle_v4.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/cartpole.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/mountain_car.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/obstacle.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/road_1d.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/renderers/road_2d.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/road_1d.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/continuous/road_2d.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/cartpole.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/conveyor_belt.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/island_navigation.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/mini_pacman_with_coins.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/mountain_car.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/pacman_with_coins.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/renderers/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/renderers/pacman.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/discrete/sokoban.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/_label_utils.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/bertrand.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/chicken.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/congestion.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/dpgg.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/multiagent/matrix/inspection.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/bridge_crossing.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/bridge_crossing_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/colour_bomb_grid_world.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/colour_bomb_grid_world_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/colour_bomb_grid_world_v3.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/colour_grid_world.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/frozen_lake.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/media_streaming.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/media_streaming_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/media_streaming_v3.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/mini_pacman.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/pacman.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/bridge_crossing.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/colour_bomb_grid_world.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/colour_grid_world.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/media_streaming.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/renderers/pacman.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/envs/tabular/utils.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/colour_bomb_grid_world/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/colour_bomb_grid_world/property_1.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/colour_bomb_grid_world/property_2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/colour_bomb_grid_world/property_3.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/cpo_shield_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/norm_obs_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_cont_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_cont_ltl_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_frozen_lake_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_ltl_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_safety_abstraction_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/prob_shield_vec_ltl_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/record_video_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/reward_shaping_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/examples/wandb_example.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/io_utils.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/specs/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/specs/base.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/specs/margin.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/plotting/specs/performance.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/__init__.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/cpo_shield.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/eventual_discounted_vi.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/helpers.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/interval_bound_vi.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/parameterized_policy.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/parameterized_policy_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/parameterized_ppo_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/prob_shield_wrapper_v1.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/masa/prob_shield/prob_shield_wrapper_v2.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/setup.cfg +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_cmg.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_frozen_lake_shield.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_notebook_play.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_reach_avoid.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_record_video.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_sample.py +0 -0
- {masa_safe_rl-0.3.2 → masa_safe_rl-0.3.4}/tests/test_tutorial_notebooks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MASA-Safe-RL
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: A safe reinforcement library for providing a common interface for different constraints and environments
|
|
5
5
|
Project-URL: Homepage, https://github.com/sacktock/MASA-Safe-RL
|
|
6
6
|
Project-URL: Repository, https://github.com/sacktock/MASA-Safe-RL
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: MASA-Safe-RL
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: A safe reinforcement library for providing a common interface for different constraints and environments
|
|
5
5
|
Project-URL: Homepage, https://github.com/sacktock/MASA-Safe-RL
|
|
6
6
|
Project-URL: Repository, https://github.com/sacktock/MASA-Safe-RL
|
|
@@ -30,10 +30,10 @@ class TRPO(OnPolicyAlgorithm):
|
|
|
30
30
|
vf_coef: float = 1.0,
|
|
31
31
|
max_grad_norm: float = 0.5,
|
|
32
32
|
target_kl: float = 0.01,
|
|
33
|
-
cg_iters: int =
|
|
33
|
+
cg_iters: int = 15,
|
|
34
34
|
cg_damping: float = 0.1,
|
|
35
|
-
fvp_sample_freq: int =
|
|
36
|
-
line_search_steps: int =
|
|
35
|
+
fvp_sample_freq: int = 1,
|
|
36
|
+
line_search_steps: int = 15,
|
|
37
37
|
line_search_decay: float = 0.8,
|
|
38
38
|
policy_class: type[BaseJaxPolicy] = PPOPolicy,
|
|
39
39
|
policy_kwargs: Optional[dict[str, Any]] = None,
|
|
@@ -512,8 +512,13 @@ class RECREG(QL):
|
|
|
512
512
|
|
|
513
513
|
if override:
|
|
514
514
|
# Use boltzmann temperature=0.01 or epsilon=0.001 for backup policy
|
|
515
|
-
|
|
516
|
-
|
|
515
|
+
if self.exploration == "boltzmann":
|
|
516
|
+
safe_act = self._act(key3, obs, self.B, deterministic, 0.01, 0.001)
|
|
517
|
+
elif self.exploration == "epsilon_greedy":
|
|
518
|
+
safe_act = self._act(key3, obs, self.B, True, 0.01, 0.001)
|
|
519
|
+
else:
|
|
520
|
+
raise NotImplementedError(f"Unexpected exploration: {self.exploration}")
|
|
521
|
+
|
|
517
522
|
return self.prepare_act(safe_act), self.prepare_act(act), override
|
|
518
523
|
|
|
519
524
|
def act(self, key, obs, deterministic=False):
|
|
@@ -55,12 +55,6 @@ ColourBombGridWorldV2:
|
|
|
55
55
|
cost_gamma: 0.95
|
|
56
56
|
lagrangian_multiplier_init: 10.0
|
|
57
57
|
|
|
58
|
-
ColourBombGridWorldV2_Property1:
|
|
59
|
-
gamma: 0.95
|
|
60
|
-
cost_limit: 0.025
|
|
61
|
-
cost_gamma: 0.95
|
|
62
|
-
lagrangian_multiplier_init: 10.0
|
|
63
|
-
|
|
64
58
|
ColourBombGridWorldV2_Property2:
|
|
65
59
|
gamma: 0.95
|
|
66
60
|
cost_limit: 0.025
|
|
@@ -10,7 +10,7 @@ defaults:
|
|
|
10
10
|
ent_coef: 0.0
|
|
11
11
|
vf_coef: 1.0
|
|
12
12
|
max_grad_norm: 0.5
|
|
13
|
-
policy_kwargs: {net_arch: [64, 64], log_std_init: -1.0}
|
|
13
|
+
policy_kwargs: {net_arch: [64, 64], log_std_init: -1.0, conditional_beta_network: True}
|
|
14
14
|
init_safety_bound: 0.01
|
|
15
15
|
theta: 1e-15
|
|
16
16
|
max_vi_steps: 10000
|
|
@@ -39,11 +39,6 @@ ColourBombGridWorldV2:
|
|
|
39
39
|
gamma: 0.95
|
|
40
40
|
init_safety_bound: 0.025
|
|
41
41
|
|
|
42
|
-
ColourBombGridWorldV2_Property1:
|
|
43
|
-
gamma: 0.95
|
|
44
|
-
init_safety_bound: 0.025
|
|
45
|
-
policy_kwargs: {log_std_init: -2.0}
|
|
46
|
-
|
|
47
42
|
ColourBombGridWorldV2_Property2:
|
|
48
43
|
gamma: 0.95
|
|
49
44
|
init_safety_bound: 0.025
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
"""CLI
|
|
1
|
+
"""Benchmark pipeline CLI: load runs, aggregate quantiles, render PlotSpecs.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
python -m masa.plotting \\
|
|
6
|
-
--config masa/plotting/configs/example.yaml \\
|
|
7
|
-
--stages all
|
|
8
|
-
|
|
9
|
-
Example (load extra specs from another module before resolving):
|
|
10
|
-
|
|
11
|
-
python -m masa.plotting \\
|
|
12
|
-
--config <your-yaml> \\
|
|
13
|
-
--specs-from <your.spec.module> \\
|
|
14
|
-
--stages process,render
|
|
3
|
+
python -m masa.plotting --config configs/example_wandb.yaml --stages all
|
|
4
|
+
python -m masa.plotting --config <yaml> --specs-from <module> --specs my_plot
|
|
15
5
|
"""
|
|
16
6
|
|
|
17
7
|
from __future__ import annotations
|
|
@@ -55,10 +45,10 @@ def _preload_spec_modules(modules: Sequence[str]) -> None:
|
|
|
55
45
|
def parse_args(argv: Optional[Sequence[str]] = None) -> argparse.Namespace:
|
|
56
46
|
p = argparse.ArgumentParser(
|
|
57
47
|
prog="python -m masa.plotting",
|
|
58
|
-
description="
|
|
48
|
+
description="Load runs from W&B or TensorBoard, aggregate to quantiles, render figures from PlotSpecs.",
|
|
59
49
|
)
|
|
60
50
|
p.add_argument("--config", required=True, type=Path,
|
|
61
|
-
help="Path to a YAML config (see configs/
|
|
51
|
+
help="Path to a YAML config (see configs/example_wandb.yaml or example_tensorboard.yaml).")
|
|
62
52
|
p.add_argument("--stages", default="all",
|
|
63
53
|
help="Comma separated subset of {download,process,render}, or 'all'.")
|
|
64
54
|
p.add_argument("--specs", default=None,
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import os
|
|
5
6
|
from typing import Dict, List, Optional, Tuple
|
|
6
7
|
|
|
7
8
|
import matplotlib.pyplot as plt
|
|
8
9
|
|
|
9
|
-
from masa.plotting.plot import plot_metrics
|
|
10
|
+
from masa.plotting.plot import plot_metrics, plot_quantile_metrics
|
|
11
|
+
from masa.plotting.processing import build_long_form_from_tb, build_quantile_frame
|
|
10
12
|
from masa.plotting.sources import TensorBoardSource, WandBSource
|
|
11
13
|
|
|
12
14
|
|
|
@@ -17,7 +19,8 @@ def plot_run(
|
|
|
17
19
|
wandb_project: Optional[str] = None,
|
|
18
20
|
wandb_entity: Optional[str] = None,
|
|
19
21
|
wandb_filters: Optional[dict] = None,
|
|
20
|
-
run_filter: Optional[str] = None,
|
|
22
|
+
run_filter: Optional[str | List[str]] = None,
|
|
23
|
+
group_seeds: bool = False,
|
|
21
24
|
# What to plot
|
|
22
25
|
metrics: Optional[List[str]] = None,
|
|
23
26
|
# Plotting options
|
|
@@ -66,9 +69,29 @@ def plot_run(
|
|
|
66
69
|
if not tensorboard_logdir and not wandb_project:
|
|
67
70
|
raise ValueError("Provide either tensorboard_logdir or wandb_project.")
|
|
68
71
|
|
|
72
|
+
if group_seeds and not tensorboard_logdir:
|
|
73
|
+
raise ValueError("group_seeds is only supported for TensorBoard sources.")
|
|
74
|
+
|
|
69
75
|
if tensorboard_logdir:
|
|
70
76
|
source = TensorBoardSource(tensorboard_logdir)
|
|
71
|
-
|
|
77
|
+
raw_df = source.load(metrics=metrics, run_filter=run_filter)
|
|
78
|
+
if group_seeds:
|
|
79
|
+
env = os.path.basename(tensorboard_logdir.rstrip("/\\"))
|
|
80
|
+
long_df = build_long_form_from_tb(raw_df, env=env)
|
|
81
|
+
q_df = build_quantile_frame(long_df)
|
|
82
|
+
return plot_quantile_metrics(
|
|
83
|
+
q_df,
|
|
84
|
+
metrics=metrics,
|
|
85
|
+
smooth_weight=smooth_weight,
|
|
86
|
+
title=title,
|
|
87
|
+
output_path=output_path,
|
|
88
|
+
figsize=figsize,
|
|
89
|
+
show_legend=show_legend,
|
|
90
|
+
show_axes=show_axes,
|
|
91
|
+
dpi=dpi,
|
|
92
|
+
palette=palette,
|
|
93
|
+
)
|
|
94
|
+
df = raw_df
|
|
72
95
|
else:
|
|
73
96
|
source = WandBSource(wandb_project, entity=wandb_entity)
|
|
74
97
|
df = source.load(metrics=metrics, filters=wandb_filters, run_filter=run_filter)
|
|
@@ -7,6 +7,10 @@ from dataclasses import dataclass, field
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import Optional
|
|
9
9
|
|
|
10
|
+
# Default run-directory schema for TensorBoard sources: the leaf run dir is
|
|
11
|
+
# named ``{variant}_{seed}`` (env comes from the parent directory).
|
|
12
|
+
_TB_RUN_SCHEMA = r"^(?P<variant>.+)_(?P<seed>\d+)$"
|
|
13
|
+
|
|
10
14
|
|
|
11
15
|
@dataclass(frozen=True)
|
|
12
16
|
class VariantStyle:
|
|
@@ -28,17 +32,20 @@ class RunSchema:
|
|
|
28
32
|
|
|
29
33
|
@dataclass(frozen=True)
|
|
30
34
|
class Config:
|
|
31
|
-
wandb_entity: str
|
|
32
|
-
wandb_project: str
|
|
33
35
|
run_schema: RunSchema
|
|
34
36
|
variants: list[VariantStyle]
|
|
35
37
|
cache_dir: Path
|
|
36
38
|
output_dir: Path
|
|
39
|
+
source_kind: str = "wandb" # "wandb" or "tensorboard"
|
|
40
|
+
wandb_entity: Optional[str] = None
|
|
41
|
+
wandb_project: Optional[str] = None
|
|
42
|
+
tensorboard_logdir: Optional[Path] = None
|
|
37
43
|
metrics: Optional[list[str]] = None
|
|
38
44
|
envs: Optional[list[str]] = None
|
|
39
45
|
palette: str = "colorblind"
|
|
40
46
|
force_download: bool = False
|
|
41
47
|
seed_for_logged_quantiles: int = 1
|
|
48
|
+
max_step: Optional[int] = None
|
|
42
49
|
|
|
43
50
|
def variant_by_name(self) -> dict[str, VariantStyle]:
|
|
44
51
|
return {v.name: v for v in self.variants}
|
|
@@ -77,24 +84,68 @@ def load_config(path: str | Path) -> Config:
|
|
|
77
84
|
]
|
|
78
85
|
variants = _fill_palette(variants, raw.get("palette", "colorblind"))
|
|
79
86
|
|
|
87
|
+
source_kind, wandb_entity, wandb_project, tb_logdir = _resolve_source(path, raw, _resolve)
|
|
88
|
+
|
|
80
89
|
schema_raw = raw.get("run_schema") or {}
|
|
81
|
-
|
|
90
|
+
if "pattern" in schema_raw:
|
|
91
|
+
schema = RunSchema(pattern=schema_raw["pattern"])
|
|
92
|
+
elif source_kind == "tensorboard":
|
|
93
|
+
schema = RunSchema(pattern=_TB_RUN_SCHEMA)
|
|
94
|
+
else:
|
|
95
|
+
schema = RunSchema()
|
|
96
|
+
|
|
97
|
+
output_dir = _resolve(raw["output_dir"])
|
|
98
|
+
cache_raw = raw.get("cache_dir")
|
|
99
|
+
cache_dir = _resolve(cache_raw) if cache_raw else output_dir / "_cache"
|
|
82
100
|
|
|
83
101
|
return Config(
|
|
84
|
-
wandb_entity=raw["wandb_entity"],
|
|
85
|
-
wandb_project=raw["wandb_project"],
|
|
86
102
|
run_schema=schema,
|
|
87
103
|
variants=variants,
|
|
88
|
-
cache_dir=
|
|
89
|
-
output_dir=
|
|
104
|
+
cache_dir=cache_dir,
|
|
105
|
+
output_dir=output_dir,
|
|
106
|
+
source_kind=source_kind,
|
|
107
|
+
wandb_entity=wandb_entity,
|
|
108
|
+
wandb_project=wandb_project,
|
|
109
|
+
tensorboard_logdir=tb_logdir,
|
|
90
110
|
metrics=raw.get("metrics"),
|
|
91
111
|
envs=raw.get("envs"),
|
|
92
112
|
palette=raw.get("palette", "colorblind"),
|
|
93
113
|
force_download=raw.get("force_download", False),
|
|
94
114
|
seed_for_logged_quantiles=raw.get("seed_for_logged_quantiles", 1),
|
|
115
|
+
max_step=raw.get("max_step"),
|
|
95
116
|
)
|
|
96
117
|
|
|
97
118
|
|
|
119
|
+
def _resolve_source(
|
|
120
|
+
path: Path, raw: dict, resolve
|
|
121
|
+
) -> tuple[str, Optional[str], Optional[str], Optional[Path]]:
|
|
122
|
+
"""Return ``(source_kind, wandb_entity, wandb_project, tensorboard_logdir)``.
|
|
123
|
+
|
|
124
|
+
Accepts an explicit ``source:`` block, or falls back to legacy top-level
|
|
125
|
+
``wandb_entity`` / ``wandb_project`` keys (treated as a W&B source).
|
|
126
|
+
"""
|
|
127
|
+
src = raw.get("source")
|
|
128
|
+
if src:
|
|
129
|
+
kind = src.get("kind", "wandb")
|
|
130
|
+
if kind == "wandb":
|
|
131
|
+
project = src.get("project")
|
|
132
|
+
if not project:
|
|
133
|
+
raise ValueError(f"{path}: source.kind=wandb requires source.project.")
|
|
134
|
+
return "wandb", src.get("entity"), project, None
|
|
135
|
+
if kind == "tensorboard":
|
|
136
|
+
logdir = src.get("logdir")
|
|
137
|
+
if not logdir:
|
|
138
|
+
raise ValueError(f"{path}: source.kind=tensorboard requires source.logdir.")
|
|
139
|
+
return "tensorboard", None, None, resolve(logdir)
|
|
140
|
+
raise ValueError(
|
|
141
|
+
f"{path}: unknown source.kind={kind!r}; expected 'wandb' or 'tensorboard'."
|
|
142
|
+
)
|
|
143
|
+
project = raw.get("wandb_project")
|
|
144
|
+
if not project:
|
|
145
|
+
raise ValueError(f"{path}: provide a 'source:' block, or top-level 'wandb_project'.")
|
|
146
|
+
return "wandb", raw.get("wandb_entity"), project, None
|
|
147
|
+
|
|
148
|
+
|
|
98
149
|
def _fill_palette(variants: list[VariantStyle], palette_name: str) -> list[VariantStyle]:
|
|
99
150
|
"""Assign colours from a seaborn palette to any variant where colour is None."""
|
|
100
151
|
missing_idx = [i for i, v in enumerate(variants) if v.colour is None]
|
|
@@ -9,8 +9,7 @@ import pandas as pd
|
|
|
9
9
|
|
|
10
10
|
from .config import Config
|
|
11
11
|
from .io_utils import get_logger
|
|
12
|
-
from .
|
|
13
|
-
from .sources import CachedWandbSource
|
|
12
|
+
from .source_registry import get_source
|
|
14
13
|
from .specs import PlotSpec, all_specs
|
|
15
14
|
from .specs.base import RenderContext
|
|
16
15
|
|
|
@@ -21,19 +20,17 @@ class Pipeline:
|
|
|
21
20
|
def __init__(self, config: Config):
|
|
22
21
|
self.config = config
|
|
23
22
|
self.log = get_logger()
|
|
24
|
-
|
|
25
|
-
# -- individual stages ------------------------------------------------
|
|
23
|
+
self.source = get_source(config)
|
|
26
24
|
|
|
27
25
|
def download(self) -> list[Path]:
|
|
28
26
|
try:
|
|
29
|
-
|
|
30
|
-
return source.download()
|
|
27
|
+
return self.source.download()
|
|
31
28
|
except Exception as e:
|
|
32
29
|
self.log.error(f"download stage crashed: {e}")
|
|
33
30
|
return []
|
|
34
31
|
|
|
35
32
|
def process(self) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
36
|
-
return build_frames(
|
|
33
|
+
return self.source.build_frames()
|
|
37
34
|
|
|
38
35
|
def render(self,
|
|
39
36
|
long_df: pd.DataFrame,
|
|
@@ -68,8 +65,6 @@ class Pipeline:
|
|
|
68
65
|
outputs.append(path)
|
|
69
66
|
return outputs
|
|
70
67
|
|
|
71
|
-
# -- orchestration ----------------------------------------------------
|
|
72
|
-
|
|
73
68
|
def run(self,
|
|
74
69
|
specs: Optional[Sequence[PlotSpec]] = None,
|
|
75
70
|
stages: Sequence[str] = VALID_STAGES,
|
|
@@ -104,8 +99,6 @@ class Pipeline:
|
|
|
104
99
|
|
|
105
100
|
return []
|
|
106
101
|
|
|
107
|
-
# -- helpers ----------------------------------------------------------
|
|
108
|
-
|
|
109
102
|
def _select_envs(self, discovered: list[str]) -> list[str]:
|
|
110
103
|
"""Restrict to ``config.envs`` if set; otherwise return all discovered envs."""
|
|
111
104
|
if not self.config.envs:
|
|
@@ -128,23 +121,14 @@ class Pipeline:
|
|
|
128
121
|
def _dry_run(self, specs: Optional[Sequence[PlotSpec]]) -> None:
|
|
129
122
|
cfg = self.config
|
|
130
123
|
self.log.info("=== DRY RUN ===")
|
|
131
|
-
self.log.info(f"
|
|
132
|
-
self.log.info(f"cache_dir : {cfg.cache_dir}")
|
|
124
|
+
self.log.info(f"source : {self.source.describe()}")
|
|
133
125
|
self.log.info(f"output_dir : {cfg.output_dir}")
|
|
134
126
|
self.log.info(f"variants : {[v.name for v in cfg.variants]}")
|
|
135
127
|
self.log.info(f"palette : {cfg.palette}")
|
|
136
128
|
chosen = specs if specs is not None else all_specs()
|
|
137
129
|
self.log.info(f"specs : {[s.id for s in chosen]}")
|
|
138
|
-
envs
|
|
139
|
-
|
|
140
|
-
pat = cfg.run_schema.compile()
|
|
141
|
-
for p in sorted(cfg.cache_dir.glob("*.csv")):
|
|
142
|
-
m = pat.match(p.stem)
|
|
143
|
-
if m:
|
|
144
|
-
envs.append(m.group("env"))
|
|
145
|
-
envs = sorted(set(envs))
|
|
146
|
-
envs = self._select_envs(envs)
|
|
147
|
-
self.log.info(f"envs (cache) : {envs or '(none discovered yet)'}")
|
|
130
|
+
envs = self._select_envs(self.source.discover_envs())
|
|
131
|
+
self.log.info(f"envs : {envs or '(none discovered yet)'}")
|
|
148
132
|
for spec in chosen:
|
|
149
133
|
for env in envs or ["<env>"]:
|
|
150
134
|
target = cfg.output_dir / spec.out_subdir / f"{spec.id}_{env}.png"
|
|
@@ -58,7 +58,6 @@ def _thousands_formatter() -> ticker.FuncFormatter:
|
|
|
58
58
|
)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
# Core plotting
|
|
62
61
|
def plot_metrics(
|
|
63
62
|
df: pd.DataFrame,
|
|
64
63
|
metrics: Optional[List[str]] = None,
|
|
@@ -102,6 +101,45 @@ def plot_metrics(
|
|
|
102
101
|
)
|
|
103
102
|
|
|
104
103
|
|
|
104
|
+
def plot_quantile_metrics(
|
|
105
|
+
q_df: pd.DataFrame,
|
|
106
|
+
metrics: Optional[List[str]] = None,
|
|
107
|
+
smooth_weight: float = 0.6,
|
|
108
|
+
title: Optional[str] = None,
|
|
109
|
+
output_path: Optional[str] = None,
|
|
110
|
+
figsize: Tuple[int, int] = (7, 5),
|
|
111
|
+
show_legend: bool = True,
|
|
112
|
+
show_axes: bool = True,
|
|
113
|
+
dpi: int = 300,
|
|
114
|
+
palette: Optional[Dict[str, str]] = None,
|
|
115
|
+
) -> plt.Figure:
|
|
116
|
+
"""Plot q50 ± q25/q75 bands from a quantile DataFrame.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
q_df: DataFrame with columns ``[variant, step, metric, q25, q50, q75]``
|
|
120
|
+
as produced by :func:`~masa.plotting.processing.build_quantile_frame`.
|
|
121
|
+
metrics: Metric keys to plot. ``None`` plots all found in *q_df*.
|
|
122
|
+
smooth_weight: EMA weight applied per ``(variant, metric)`` group.
|
|
123
|
+
title: Per-panel title override. ``None`` uses the metric name.
|
|
124
|
+
output_path: Save path. ``None`` skips saving.
|
|
125
|
+
figsize: ``(width, height)`` per subplot panel.
|
|
126
|
+
show_legend: Render a shared legend below the panels.
|
|
127
|
+
show_axes: Label axes.
|
|
128
|
+
dpi: Resolution for saved figures.
|
|
129
|
+
palette: Colour mapping ``{variant: colour}``. ``None`` uses colorblind.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
The matplotlib :class:`~matplotlib.figure.Figure`.
|
|
133
|
+
"""
|
|
134
|
+
with plt.rc_context(_RC_PARAMS):
|
|
135
|
+
return _plot_quantile_inner(
|
|
136
|
+
q_df, metrics=metrics, smooth_weight=smooth_weight,
|
|
137
|
+
title=title, output_path=output_path, figsize=figsize,
|
|
138
|
+
show_legend=show_legend, show_axes=show_axes, dpi=dpi,
|
|
139
|
+
palette=palette,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
105
143
|
def _plot_metrics_inner(
|
|
106
144
|
df: pd.DataFrame,
|
|
107
145
|
*,
|
|
@@ -185,7 +223,84 @@ def _plot_metrics_inner(
|
|
|
185
223
|
return fig
|
|
186
224
|
|
|
187
225
|
|
|
188
|
-
|
|
226
|
+
def _plot_quantile_inner(
|
|
227
|
+
q_df: pd.DataFrame,
|
|
228
|
+
*,
|
|
229
|
+
metrics: Optional[List[str]],
|
|
230
|
+
smooth_weight: float,
|
|
231
|
+
title: Optional[str],
|
|
232
|
+
output_path: Optional[str],
|
|
233
|
+
figsize: Tuple[int, int],
|
|
234
|
+
show_legend: bool,
|
|
235
|
+
show_axes: bool,
|
|
236
|
+
dpi: int,
|
|
237
|
+
palette: Optional[Dict[str, str]],
|
|
238
|
+
) -> plt.Figure:
|
|
239
|
+
if metrics is None:
|
|
240
|
+
metrics = sorted(q_df["metric"].unique().tolist())
|
|
241
|
+
if not metrics:
|
|
242
|
+
raise ValueError("No metrics to plot.")
|
|
243
|
+
if q_df.empty:
|
|
244
|
+
raise ValueError("The provided DataFrame is empty.")
|
|
245
|
+
|
|
246
|
+
variants = sorted(q_df["variant"].unique().tolist())
|
|
247
|
+
if palette is None:
|
|
248
|
+
colours: Dict[str, str] = dict(zip(variants, sns.color_palette("colorblind", len(variants))))
|
|
249
|
+
else:
|
|
250
|
+
colours = {v: palette.get(v, "#888888") for v in variants}
|
|
251
|
+
|
|
252
|
+
n = len(metrics)
|
|
253
|
+
fig, axes = plt.subplots(1, n, figsize=(figsize[0] * n, figsize[1]))
|
|
254
|
+
if n == 1:
|
|
255
|
+
axes = [axes]
|
|
256
|
+
|
|
257
|
+
for k, metric in enumerate(metrics):
|
|
258
|
+
ax = axes[k]
|
|
259
|
+
sub = q_df[q_df["metric"] == metric]
|
|
260
|
+
if sub.empty:
|
|
261
|
+
ax.set_title(metric)
|
|
262
|
+
continue
|
|
263
|
+
for variant in variants:
|
|
264
|
+
vsub = sub[sub["variant"] == variant].sort_values("step")
|
|
265
|
+
if vsub.empty:
|
|
266
|
+
continue
|
|
267
|
+
colour = colours.get(variant)
|
|
268
|
+
steps = vsub["step"].values
|
|
269
|
+
q50 = smooth(vsub["q50"].values, smooth_weight)
|
|
270
|
+
q25 = smooth(vsub["q25"].values, smooth_weight)
|
|
271
|
+
q75 = smooth(vsub["q75"].values, smooth_weight)
|
|
272
|
+
ax.plot(steps, q50, color=colour, linewidth=2.0, label=variant)
|
|
273
|
+
ax.fill_between(steps, q25, q75, color=colour, alpha=0.25, linewidth=0)
|
|
274
|
+
|
|
275
|
+
ax.set_title(_pretty_name(metric) if title is None else title)
|
|
276
|
+
if show_axes:
|
|
277
|
+
ax.set_ylabel(_pretty_name(metric))
|
|
278
|
+
ax.set_xlabel("Training steps (in thousands)")
|
|
279
|
+
ax.xaxis.set_major_formatter(_thousands_formatter())
|
|
280
|
+
else:
|
|
281
|
+
ax.set_ylabel("")
|
|
282
|
+
ax.set_xlabel("")
|
|
283
|
+
ax.tick_params(axis="both", which="both", top=True, right=True)
|
|
284
|
+
|
|
285
|
+
if show_legend:
|
|
286
|
+
handles, labels = axes[0].get_legend_handles_labels()
|
|
287
|
+
if handles:
|
|
288
|
+
fig.legend(
|
|
289
|
+
handles, labels, loc="upper center",
|
|
290
|
+
bbox_to_anchor=(0.5, 0.02), ncol=min(len(handles), 6),
|
|
291
|
+
frameon=True, edgecolor="white", fancybox=False,
|
|
292
|
+
columnspacing=1.5, handlelength=2.0,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
fig.tight_layout(rect=[0, 0.08, 1, 1] if show_legend else [0, 0, 1, 1])
|
|
296
|
+
|
|
297
|
+
if output_path is not None:
|
|
298
|
+
os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
|
|
299
|
+
fig.savefig(output_path, bbox_inches="tight", pad_inches=0.15, dpi=dpi)
|
|
300
|
+
|
|
301
|
+
return fig
|
|
302
|
+
|
|
303
|
+
|
|
189
304
|
_PRETTY: Dict[str, str] = {
|
|
190
305
|
"ep_reward": "Reward",
|
|
191
306
|
"ep_length": "Episode Length",
|