gr-libs 0.2.2__tar.gz → 0.2.6__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.
Files changed (87) hide show
  1. {gr_libs-0.2.2 → gr_libs-0.2.6}/PKG-INFO +31 -15
  2. {gr_libs-0.2.2 → gr_libs-0.2.6}/README.md +30 -14
  3. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/__init__.py +6 -1
  4. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/_version.py +2 -2
  5. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/all_experiments.py +73 -107
  6. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/environment/environment.py +126 -17
  7. gr_libs-0.2.6/gr_libs/evaluation/generate_experiments_results.py +100 -0
  8. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/consts.py +1 -0
  9. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/neural/deep_rl_learner.py +118 -34
  10. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/odgr_executor.py +27 -27
  11. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/problems/consts.py +568 -290
  12. gr_libs-0.2.6/gr_libs/recognizer/_utils/__init__.py +1 -0
  13. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/_utils/format.py +7 -1
  14. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/gr_as_rl/gr_as_rl_recognizer.py +158 -2
  15. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/graml/graml_recognizer.py +18 -10
  16. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/recognizer.py +4 -4
  17. gr_libs-0.2.6/gr_libs/tutorials/gcaura_panda_tutorial.py +168 -0
  18. gr_libs-0.2.6/gr_libs/tutorials/gcaura_parking_tutorial.py +167 -0
  19. gr_libs-0.2.6/gr_libs/tutorials/gcaura_point_maze_tutorial.py +169 -0
  20. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/gcdraco_panda_tutorial.py +6 -2
  21. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/gcdraco_parking_tutorial.py +3 -1
  22. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/graml_minigrid_tutorial.py +16 -12
  23. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/graml_panda_tutorial.py +6 -2
  24. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/graml_parking_tutorial.py +3 -1
  25. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/graml_point_maze_tutorial.py +15 -2
  26. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs.egg-info/PKG-INFO +31 -15
  27. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs.egg-info/SOURCES.txt +12 -6
  28. gr_libs-0.2.6/tests/test_gcaura.py +15 -0
  29. gr_libs-0.2.6/tests/test_odgr_executor_expertbasedgraml.py +14 -0
  30. gr_libs-0.2.6/tests/test_odgr_executor_gcaura.py +14 -0
  31. gr_libs-0.2.6/tests/test_odgr_executor_gcdraco.py +14 -0
  32. gr_libs-0.2.6/tests/test_odgr_executor_gcgraml.py +14 -0
  33. gr_libs-0.2.6/tests/test_odgr_executor_graql.py +14 -0
  34. gr_libs-0.2.2/gr_libs/_evaluation/_analyze_results_cross_alg_cross_domain.py +0 -260
  35. gr_libs-0.2.2/gr_libs/_evaluation/_generate_experiments_results.py +0 -141
  36. gr_libs-0.2.2/gr_libs/_evaluation/_generate_task_specific_statistics_plots.py +0 -497
  37. gr_libs-0.2.2/gr_libs/_evaluation/_get_plans_images.py +0 -61
  38. gr_libs-0.2.2/gr_libs/_evaluation/_increasing_and_decreasing_.py +0 -106
  39. /gr_libs-0.2.2/gr_libs/environment/_utils/__init__.py → /gr_libs-0.2.6/gr_libs/_evaluation/_generate_experiments_results.py +0 -0
  40. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/environment/__init__.py +0 -0
  41. {gr_libs-0.2.2/gr_libs/ml/planner → gr_libs-0.2.6/gr_libs/environment/_utils}/__init__.py +0 -0
  42. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/environment/_utils/utils.py +0 -0
  43. {gr_libs-0.2.2/gr_libs/_evaluation → gr_libs-0.2.6/gr_libs/evaluation}/__init__.py +0 -0
  44. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/metrics/__init__.py +0 -0
  45. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/metrics/metrics.py +0 -0
  46. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/__init__.py +0 -0
  47. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/agent.py +0 -0
  48. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/base/__init__.py +0 -0
  49. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/base/rl_agent.py +0 -0
  50. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/neural/__init__.py +0 -0
  51. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/neural/utils/__init__.py +0 -0
  52. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/neural/utils/dictlist.py +0 -0
  53. {gr_libs-0.2.2/gr_libs/ml/planner/mcts → gr_libs-0.2.6/gr_libs/ml/planner}/__init__.py +0 -0
  54. {gr_libs-0.2.2/gr_libs/ml/sequential → gr_libs-0.2.6/gr_libs/ml/planner/mcts}/__init__.py +0 -0
  55. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/planner/mcts/_utils/__init__.py +0 -0
  56. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/planner/mcts/_utils/node.py +0 -0
  57. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/planner/mcts/_utils/tree.py +0 -0
  58. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/planner/mcts/mcts_model.py +0 -0
  59. {gr_libs-0.2.2/gr_libs/problems → gr_libs-0.2.6/gr_libs/ml/sequential}/__init__.py +0 -0
  60. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/sequential/_lstm_model.py +0 -0
  61. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/tabular/__init__.py +0 -0
  62. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/tabular/state.py +0 -0
  63. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/tabular/tabular_q_learner.py +0 -0
  64. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/tabular/tabular_rl_agent.py +0 -0
  65. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/__init__.py +0 -0
  66. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/env.py +0 -0
  67. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/format.py +0 -0
  68. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/math.py +0 -0
  69. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/other.py +0 -0
  70. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/ml/utils/storage.py +0 -0
  71. {gr_libs-0.2.2/gr_libs/recognizer → gr_libs-0.2.6/gr_libs/problems}/__init__.py +0 -0
  72. {gr_libs-0.2.2/gr_libs/recognizer/_utils → gr_libs-0.2.6/gr_libs/recognizer}/__init__.py +0 -0
  73. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/gr_as_rl/__init__.py +0 -0
  74. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/graml/__init__.py +0 -0
  75. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/recognizer/graml/_gr_dataset.py +0 -0
  76. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/draco_panda_tutorial.py +0 -0
  77. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/draco_parking_tutorial.py +0 -0
  78. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs/tutorials/graql_minigrid_tutorial.py +0 -0
  79. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs.egg-info/dependency_links.txt +0 -0
  80. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs.egg-info/requires.txt +0 -0
  81. {gr_libs-0.2.2 → gr_libs-0.2.6}/gr_libs.egg-info/top_level.txt +0 -0
  82. {gr_libs-0.2.2 → gr_libs-0.2.6}/pyproject.toml +0 -0
  83. {gr_libs-0.2.2 → gr_libs-0.2.6}/setup.cfg +0 -0
  84. {gr_libs-0.2.2 → gr_libs-0.2.6}/tests/test_draco.py +0 -0
  85. {gr_libs-0.2.2 → gr_libs-0.2.6}/tests/test_gcdraco.py +0 -0
  86. {gr_libs-0.2.2 → gr_libs-0.2.6}/tests/test_graml.py +0 -0
  87. {gr_libs-0.2.2 → gr_libs-0.2.6}/tests/test_graql.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gr_libs
3
- Version: 0.2.2
3
+ Version: 0.2.6
4
4
  Summary: Package with goal recognition frameworks baselines
5
5
  Author: Ben Nageris
6
6
  Author-email: Matan Shamir <matan.shamir@live.biu.ac.il>, Osher Elhadad <osher.elhadad@live.biu.ac.il>
@@ -108,13 +108,16 @@ For any issues or troubleshooting, please refer to the repository's issue tracke
108
108
 
109
109
  ## Supported Algorithms
110
110
 
111
- Successors of algorithms that don't differ in their specifics are added in parentheses after the algorithm name. For example, since GC-DRACO and DRACO share the same column values, they're written on one line as DRACO (GC).
111
+ | **Algorithm** | **Supervised** | **Reinforcement Learning** | **Discrete States** | **Continuous States** | **Discrete Actions** | **Continuous Actions** | **Model-Based** | **Model-Free** | **Action-Only** | **Goal Conditioned** | **Fine-Tuning** | **Supported Environments** |
112
+ |---------------------|----------------|---------------------------|---------------------|----------------------|----------------------|-----------------------|------------------|----------------|----------------|---------------------|-----------------|-------------------------------------------|
113
+ | Graql | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | Minigrid |
114
+ | Draco | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | PointMaze, Panda Reach, Parking |
115
+ | GCDraco | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | Panda Reach, Parking |
116
+ | GCAura | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | PointMaze, Panda Reach, Parking |
117
+ | ExpertBasedGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | Panda Reach, Parking |
118
+ | BGGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | Minigrid, PointMaze |
119
+ | GCGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | Panda Reach, Parking |
112
120
 
113
- | **Algorithm** | **Supervised** | **Reinforcement Learning** | **Discrete States** | **Continuous States** | **Discrete Actions** | **Continuous Actions** | **Model-Based** | **Model-Free** | **Action-Only** |
114
- |--------------|--------------|------------------------|------------------|------------------|--------------|--------------|--------------|--------------|--------------|
115
- | GRAQL | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
116
- | DRACO (GC) | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
117
- | GRAML (GC, BG) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
118
121
 
119
122
  ## Supported Domains
120
123
 
@@ -259,20 +262,33 @@ A part of the contribution of this package is standardizing the evaluations of M
259
262
  consts.py provides a set of ODGR problems on which the framework can be evaluated.
260
263
  The 'evaluations' sub-package provides scripts to analyze the results of the all_experiments.py execution, done over the ODGR the problems defined at consts.py.
261
264
 
262
- In order to parallelize executions of odgr_executor.py, you can edit all_experiments.py with your combination of domains, environments and tasks.
263
- This script use multiprocessing to simultaniously execute many odgr_executor.py python executions as child processes.
265
+ #### Running all_experiments.py
264
266
 
265
- It logs failures and successful executions for debugability.
267
+ You can now run `all_experiments.py` with your desired combination of domains, environments, tasks, and recognizers directly from the command line, without editing the script:
266
268
 
267
- After execution, another level of abstraction for the results is created. For example, when running for Graql in the minigrid domain:
268
269
  ```sh
269
- outputs\summaries\detailed_summary_minigrid_Graql.txt
270
+ python gr_libs/all_experiments.py \
271
+ --domains minigrid parking \
272
+ --envs MiniGrid-SimpleCrossingS13N4 Parking-S-14-PC- \
273
+ --tasks L1 L2 L3 L4 L5 \
274
+ --recognizers ExpertBasedGraml Graql \
275
+ --n 5
270
276
  ```
271
- Will show the accuracies for every ODGR problem, for every percentage and type of input in a table-like .txt format, whike:
277
+
278
+ - `--domains`: List of domains to run experiments on.
279
+ - `--envs`: List of environments (must be in the same order as domains).
280
+ - `--tasks`: List of tasks (applied to all domain/env pairs).
281
+ - `--recognizers`: List of recognizers/algorithms to evaluate.
282
+ - `--n`: Number of times to execute each task (default: 5).
283
+
284
+ This script uses multiprocessing to simultaneously execute many `odgr_executor.py` runs as child processes. It logs failures and successful executions for debugability.
285
+
286
+ After execution summary files are generated in `outputs/summaries/` for further analysis and plotting.
287
+
288
+ another execution example:
272
289
  ```sh
273
- outputs\summaries\compiled_summary_minigrid_Graql.txt
290
+ python gr_libs/all_experiments.py --domains parking --envs Parking-S-14-PC- --tasks L1 L2 L3 L4 L5 --recognizers GCAura GCGraml GCDraco BGGraml Draco --n 5
274
291
  ```
275
- Will show the same results in a more compact summary.
276
292
 
277
293
  ### Using analysis scripts
278
294
  The repository provides benchmark domains and scripts for analyzing experimental results. The `evaluation` directory contains tools for processing and visualizing the results from odgr_executor.py and all_experiments.py.
@@ -79,13 +79,16 @@ For any issues or troubleshooting, please refer to the repository's issue tracke
79
79
 
80
80
  ## Supported Algorithms
81
81
 
82
- Successors of algorithms that don't differ in their specifics are added in parentheses after the algorithm name. For example, since GC-DRACO and DRACO share the same column values, they're written on one line as DRACO (GC).
82
+ | **Algorithm** | **Supervised** | **Reinforcement Learning** | **Discrete States** | **Continuous States** | **Discrete Actions** | **Continuous Actions** | **Model-Based** | **Model-Free** | **Action-Only** | **Goal Conditioned** | **Fine-Tuning** | **Supported Environments** |
83
+ |---------------------|----------------|---------------------------|---------------------|----------------------|----------------------|-----------------------|------------------|----------------|----------------|---------------------|-----------------|-------------------------------------------|
84
+ | Graql | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | Minigrid |
85
+ | Draco | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | PointMaze, Panda Reach, Parking |
86
+ | GCDraco | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ | Panda Reach, Parking |
87
+ | GCAura | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ✅ | ✅ | PointMaze, Panda Reach, Parking |
88
+ | ExpertBasedGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | Panda Reach, Parking |
89
+ | BGGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | Minigrid, PointMaze |
90
+ | GCGraml | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | Panda Reach, Parking |
83
91
 
84
- | **Algorithm** | **Supervised** | **Reinforcement Learning** | **Discrete States** | **Continuous States** | **Discrete Actions** | **Continuous Actions** | **Model-Based** | **Model-Free** | **Action-Only** |
85
- |--------------|--------------|------------------------|------------------|------------------|--------------|--------------|--------------|--------------|--------------|
86
- | GRAQL | ❌ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ |
87
- | DRACO (GC) | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
88
- | GRAML (GC, BG) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
89
92
 
90
93
  ## Supported Domains
91
94
 
@@ -230,20 +233,33 @@ A part of the contribution of this package is standardizing the evaluations of M
230
233
  consts.py provides a set of ODGR problems on which the framework can be evaluated.
231
234
  The 'evaluations' sub-package provides scripts to analyze the results of the all_experiments.py execution, done over the ODGR the problems defined at consts.py.
232
235
 
233
- In order to parallelize executions of odgr_executor.py, you can edit all_experiments.py with your combination of domains, environments and tasks.
234
- This script use multiprocessing to simultaniously execute many odgr_executor.py python executions as child processes.
236
+ #### Running all_experiments.py
235
237
 
236
- It logs failures and successful executions for debugability.
238
+ You can now run `all_experiments.py` with your desired combination of domains, environments, tasks, and recognizers directly from the command line, without editing the script:
237
239
 
238
- After execution, another level of abstraction for the results is created. For example, when running for Graql in the minigrid domain:
239
240
  ```sh
240
- outputs\summaries\detailed_summary_minigrid_Graql.txt
241
+ python gr_libs/all_experiments.py \
242
+ --domains minigrid parking \
243
+ --envs MiniGrid-SimpleCrossingS13N4 Parking-S-14-PC- \
244
+ --tasks L1 L2 L3 L4 L5 \
245
+ --recognizers ExpertBasedGraml Graql \
246
+ --n 5
241
247
  ```
242
- Will show the accuracies for every ODGR problem, for every percentage and type of input in a table-like .txt format, whike:
248
+
249
+ - `--domains`: List of domains to run experiments on.
250
+ - `--envs`: List of environments (must be in the same order as domains).
251
+ - `--tasks`: List of tasks (applied to all domain/env pairs).
252
+ - `--recognizers`: List of recognizers/algorithms to evaluate.
253
+ - `--n`: Number of times to execute each task (default: 5).
254
+
255
+ This script uses multiprocessing to simultaneously execute many `odgr_executor.py` runs as child processes. It logs failures and successful executions for debugability.
256
+
257
+ After execution summary files are generated in `outputs/summaries/` for further analysis and plotting.
258
+
259
+ another execution example:
243
260
  ```sh
244
- outputs\summaries\compiled_summary_minigrid_Graql.txt
261
+ python gr_libs/all_experiments.py --domains parking --envs Parking-S-14-PC- --tasks L1 L2 L3 L4 L5 --recognizers GCAura GCGraml GCDraco BGGraml Draco --n 5
245
262
  ```
246
- Will show the same results in a more compact summary.
247
263
 
248
264
  ### Using analysis scripts
249
265
  The repository provides benchmark domains and scripts for analyzing experimental results. The `evaluation` directory contains tools for processing and visualizing the results from odgr_executor.py and all_experiments.py.
@@ -1,6 +1,11 @@
1
1
  """gr_libs: Baselines for goal recognition executions on gym environments."""
2
2
 
3
- from gr_libs.recognizer.gr_as_rl.gr_as_rl_recognizer import Draco, GCDraco, Graql
3
+ from gr_libs.recognizer.gr_as_rl.gr_as_rl_recognizer import (
4
+ Draco,
5
+ GCDraco,
6
+ Graql,
7
+ GCAura,
8
+ )
4
9
  from gr_libs.recognizer.graml.graml_recognizer import ExpertBasedGraml, GCGraml
5
10
 
6
11
  try:
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.2'
21
- __version_tuple__ = version_tuple = (0, 2, 2)
20
+ __version__ = version = '0.2.6'
21
+ __version_tuple__ = version_tuple = (0, 2, 6)
@@ -1,67 +1,43 @@
1
1
  """ executes odgr_executor parallely on a set of problems defined in consts.py """
2
2
 
3
+ import argparse
3
4
  import concurrent.futures
4
5
  import os
5
6
  import subprocess
6
7
  import sys
7
- import threading
8
8
 
9
9
  import dill
10
10
  import numpy as np
11
11
 
12
12
  from gr_libs.ml.utils.storage import get_experiment_results_path
13
13
 
14
- # Define the lists
15
- # domains = ['minigrid', 'point_maze', 'parking', 'panda']
16
- # envs = {
17
- # 'minigrid': ['obstacles', 'lava_crossing'],
18
- # 'point_maze': ['four_rooms', 'lava_crossing'],
19
- # 'parking': ['gc_agent', 'gd_agent'],
20
- # 'panda': ['gc_agent', 'gd_agent']
21
- # }
22
- # tasks = {
23
- # 'minigrid': ['L111', 'L222', 'L333', 'L444', 'L555'],
24
- # 'point_maze': ['L111', 'L222', 'L333', 'L444', 'L555'],
25
- # 'parking': ['L111', 'L222', 'L333', 'L444', 'L555'],
26
- # 'panda': ['L111', 'L222', 'L333', 'L444', 'L555']
27
- # }
28
- configs = {
29
- "minigrid": {
30
- "MiniGrid-SimpleCrossingS13N4": ["L1", "L2", "L3", "L4", "L5"],
31
- "MiniGrid-LavaCrossingS9N2": ["L1", "L2", "L3", "L4", "L5"],
32
- }
33
- # 'point_maze': {
34
- # 'PointMaze-FourRoomsEnvDense-11x11': ['L1', 'L2', 'L3', 'L4', 'L5'],
35
- # 'PointMaze-ObstaclesEnvDense-11x11': ['L1', 'L2', 'L3', 'L4', 'L5']
36
- # }
37
- # 'parking': {
38
- # 'Parking-S-14-PC-': ['L1', 'L2', 'L3', 'L4', 'L5'],
39
- # 'Parking-S-14-PC-': ['L1', 'L2', 'L3', 'L4', 'L5']
40
- # }
41
- # 'panda': {
42
- # 'PandaMyReachDense': ['L1', 'L2', 'L3', 'L4', 'L5'],
43
- # 'PandaMyReachDense': ['L1', 'L2', 'L3', 'L4', 'L5']
44
- # }
45
- }
46
- # for minigrid:
47
- # TODO assert these instead i the beggingning of the code before beginning
48
- # with the actual threading
49
- recognizers = ["ExpertBasedGraml", "Graql"]
50
- # recognizers = ['Graql']
51
-
52
- # for point_maze:
53
- # recognizers = ['ExpertBasedGraml']
54
- # recognizers = ['Draco']
55
-
56
- # for parking:
57
- # recognizers = ['GCGraml']
58
- # recognizers = ['GCDraco']
14
+ parser = argparse.ArgumentParser()
15
+ parser.add_argument("--domains", nargs="+", required=True, help="List of domains")
16
+ parser.add_argument(
17
+ "--envs",
18
+ nargs="+",
19
+ required=True,
20
+ help="List of environments (same order as domains)",
21
+ )
22
+ parser.add_argument(
23
+ "--tasks", nargs="+", required=True, help="List of tasks (e.g. L1 L2 L3 L4 L5)"
24
+ )
25
+ parser.add_argument(
26
+ "--recognizers", nargs="+", required=True, help="List of recognizers"
27
+ )
28
+ parser.add_argument(
29
+ "--n", type=int, default=5, help="Number of times to execute each task"
30
+ )
31
+ args = parser.parse_args()
59
32
 
60
- # for panda:
61
- # recognizers = ['GCGraml']
62
- # recognizers = ['GCDraco']
33
+ # Build configs dynamically
34
+ configs = {}
35
+ for domain, env in zip(args.domains, args.envs):
36
+ configs.setdefault(domain, {})
37
+ configs[domain][env] = args.tasks
63
38
 
64
- n = 5 # Number of times to execute each task
39
+ recognizers = args.recognizers
40
+ n = args.n
65
41
 
66
42
 
67
43
  # Function to read results from the result file
@@ -97,40 +73,31 @@ def run_experiment(domain, env, task, recognizer, i, generate_new=False):
97
73
  Returns:
98
74
  tuple: A tuple containing the experiment details and the results.
99
75
  """
100
- cmd = f"python gr_libs/odgr_executor.py --domain {domain} --recognizer \
101
- {recognizer} --env_name {env} --task {task} --collect_stats"
102
- print(f"Starting execution: {cmd}")
76
+ cmd = f"python gr_libs/odgr_executor.py --domain {domain} --recognizer {recognizer} --env_name {env} --task {task} --collect_stats --experiment_num {i}"
103
77
  try:
104
78
  res_file_path = get_experiment_results_path(domain, env, task, recognizer)
105
- res_file_path_txt = os.path.join(res_file_path, "res.txt")
106
- i_res_file_path_txt = os.path.join(res_file_path, f"res_{i}.txt")
107
- res_file_path_pkl = os.path.join(res_file_path, "res.pkl")
108
79
  i_res_file_path_pkl = os.path.join(res_file_path, f"res_{i}.pkl")
80
+ i_res_file_path_txt = os.path.join(res_file_path, f"res_{i}.txt")
109
81
  if generate_new or (
110
82
  not os.path.exists(i_res_file_path_txt)
111
83
  or not os.path.exists(i_res_file_path_pkl)
112
84
  ):
113
- if os.path.exists(i_res_file_path_txt) or os.path.exists(
114
- i_res_file_path_pkl
115
- ):
116
- i_res_file_path_txt = i_res_file_path_txt.replace(f"_{i}", f"_{i}_new")
117
- i_res_file_path_pkl = i_res_file_path_pkl.replace(f"_{i}", f"_{i}_new")
118
- process = subprocess.Popen(cmd, shell=True)
119
- process.wait()
85
+ process = subprocess.Popen(
86
+ cmd,
87
+ shell=True,
88
+ stdout=subprocess.PIPE,
89
+ stderr=subprocess.PIPE,
90
+ text=True,
91
+ )
92
+ stdout, stderr = process.communicate()
120
93
  if process.returncode != 0:
121
- print(f"Execution failed: {cmd}")
122
- print(f"Error: {result.stderr}")
94
+ print(f"Execution failed: {cmd}\nSTDOUT:\n{stdout}\nSTDERR:\n{stderr}")
123
95
  return None
124
96
  else:
125
97
  print(f"Finished execution successfully: {cmd}")
126
- file_lock = threading.Lock()
127
- with file_lock:
128
- os.rename(res_file_path_pkl, i_res_file_path_pkl)
129
- os.rename(res_file_path_txt, i_res_file_path_txt)
130
98
  else:
131
99
  print(
132
- f"File {i_res_file_path_txt} already exists. Skipping execution \
133
- of {cmd}"
100
+ f"File {i_res_file_path_txt} already exists. Skipping execution of {cmd}"
134
101
  )
135
102
  return ((domain, env, task, recognizer), read_results(i_res_file_path_pkl))
136
103
  except Exception as e:
@@ -252,43 +219,42 @@ for key, percentage_dict in compiled_accuracies.items():
252
219
  std_dev = np.std(accuracies)
253
220
  compiled_summary[key][percentage][is_cons] = (avg_accuracy, std_dev)
254
221
 
255
- # Write different summary results to different files
222
+ # Write different summary results to different files, one per recognizer
256
223
  if not os.path.exists(os.path.join("outputs", "summaries")):
257
224
  os.makedirs(os.path.join("outputs", "summaries"))
258
- detailed_summary_file_path = os.path.join(
259
- "outputs",
260
- "summaries",
261
- f"detailed_summary_{''.join(configs.keys())}_{recognizers[0]}.txt",
262
- )
263
- compiled_summary_file_path = os.path.join(
264
- "outputs",
265
- "summaries",
266
- f"compiled_summary_{''.join(configs.keys())}_{recognizers[0]}.txt",
267
- )
268
- with open(detailed_summary_file_path, "w") as f:
269
- for key, percentage_dict in detailed_summary.items():
270
- domain, env, task, recognizer = key
271
- f.write(f"{domain}\t{env}\t{task}\t{recognizer}\n")
272
- for percentage, cons_info in percentage_dict.items():
273
- for is_cons, (avg_accuracy, std_dev) in cons_info.items():
274
- f.write(
275
- f"\t\t{percentage}\t{is_cons}\t{avg_accuracy:.4f}\t{std_dev:.4f}\n"
276
- )
277
225
 
278
- with open(compiled_summary_file_path, "w") as f:
279
- for key, percentage_dict in compiled_summary.items():
280
- for percentage, cons_info in percentage_dict.items():
281
- for is_cons, (avg_accuracy, std_dev) in cons_info.items():
282
- f.write(
283
- f"{key[0]}\t{key[1]}\t{percentage}\t{is_cons}\t{avg_accuracy:.4f}\t{std_dev:.4f}\n"
284
- )
285
- domain, recognizer = key
286
- f.write(f"{domain}\t{recognizer}\n")
287
- for percentage, cons_info in percentage_dict.items():
288
- for is_cons, (avg_accuracy, std_dev) in cons_info.items():
289
- f.write(
290
- f"\t\t{percentage}\t{is_cons}\t{avg_accuracy:.4f}\t{std_dev:.4f}\n"
291
- )
226
+ for recognizer in recognizers:
227
+ compiled_summary_file_path = os.path.join(
228
+ "outputs",
229
+ "summaries",
230
+ f"compiled_summary_{''.join(configs.keys())}_{recognizer}.txt",
231
+ )
232
+ with open(compiled_summary_file_path, "w") as f:
233
+ for key, percentage_dict in compiled_summary.items():
234
+ domain, recog = key
235
+ if recog != recognizer:
236
+ continue # Only write results for this recognizer
237
+ for percentage, cons_info in percentage_dict.items():
238
+ for is_cons, (avg_accuracy, std_dev) in cons_info.items():
239
+ f.write(
240
+ f"{domain}\t{recog}\t{percentage}\t{is_cons}\t{avg_accuracy:.4f}\t{std_dev:.4f}\n"
241
+ )
242
+ print(f"Compiled summary results written to {compiled_summary_file_path}")
292
243
 
293
- print(f"Detailed summary results written to {detailed_summary_file_path}")
294
- print(f"Compiled summary results written to {compiled_summary_file_path}")
244
+ detailed_summary_file_path = os.path.join(
245
+ "outputs",
246
+ "summaries",
247
+ f"detailed_summary_{''.join(configs.keys())}_{recognizer}.txt",
248
+ )
249
+ with open(detailed_summary_file_path, "w") as f:
250
+ for key, percentage_dict in detailed_summary.items():
251
+ domain, env, task, recog = key
252
+ if recog != recognizer:
253
+ continue # Only write results for this recognizer
254
+ f.write(f"{domain}\t{env}\t{task}\t{recog}\n")
255
+ for percentage, cons_info in percentage_dict.items():
256
+ for is_cons, (avg_accuracy, std_dev) in cons_info.items():
257
+ f.write(
258
+ f"\t\t{percentage}\t{is_cons}\t{avg_accuracy:.4f}\t{std_dev:.4f}\n"
259
+ )
260
+ print(f"Detailed summary results written to {detailed_summary_file_path}")
@@ -1,8 +1,10 @@
1
- """ environment.py """
1
+ """environment.py"""
2
2
 
3
3
  import os
4
+ import sys
4
5
  from abc import abstractmethod
5
6
  from collections import namedtuple
7
+ from contextlib import contextmanager
6
8
 
7
9
  import gymnasium as gym
8
10
  import numpy as np
@@ -12,6 +14,8 @@ from minigrid.wrappers import ImgObsWrapper, RGBImgPartialObsWrapper
12
14
  from PIL import Image
13
15
  from stable_baselines3.common.vec_env import DummyVecEnv
14
16
 
17
+ from gr_envs.wrappers.goal_wrapper import GoalRecognitionWrapper
18
+
15
19
  MINIGRID, PANDA, PARKING, POINT_MAZE = "minigrid", "panda", "parking", "point_maze"
16
20
 
17
21
  QLEARNING = "QLEARNING"
@@ -23,6 +27,23 @@ LSTMProperties = namedtuple(
23
27
  )
24
28
 
25
29
 
30
+ @contextmanager
31
+ def suppress_output():
32
+ """
33
+ Context manager to suppress stdout and stderr (including C/C++ prints).
34
+ """
35
+ with open(os.devnull, "w") as devnull:
36
+ old_stdout = sys.stdout
37
+ old_stderr = sys.stderr
38
+ sys.stdout = devnull
39
+ sys.stderr = devnull
40
+ try:
41
+ yield
42
+ finally:
43
+ sys.stdout = old_stdout
44
+ sys.stderr = old_stderr
45
+
46
+
26
47
  class EnvProperty:
27
48
  """
28
49
  Base class for environment properties.
@@ -91,6 +112,12 @@ class EnvProperty:
91
112
  Convert a list of problems to a string tuple.
92
113
  """
93
114
 
115
+ @abstractmethod
116
+ def goal_to_str(self, goal):
117
+ """
118
+ Convert a goal to a string representation.
119
+ """
120
+
94
121
  @abstractmethod
95
122
  def goal_to_problem_str(self, goal):
96
123
  """
@@ -135,9 +162,10 @@ class EnvProperty:
135
162
 
136
163
  def create_vec_env(self, kwargs):
137
164
  """
138
- Create a vectorized environment.
165
+ Create a vectorized environment, suppressing prints from gym/pybullet/panda-gym.
139
166
  """
140
- env = gym.make(**kwargs)
167
+ with suppress_output():
168
+ env = gym.make(**kwargs)
141
169
  return DummyVecEnv([lambda: env])
142
170
 
143
171
  @abstractmethod
@@ -146,6 +174,29 @@ class EnvProperty:
146
174
  Change the goal to a specific desired goal.
147
175
  """
148
176
 
177
+ def is_goal_in_subspace(self, goal):
178
+ """
179
+ Check if a goal is within the specified goal subspace.
180
+
181
+ Args:
182
+ goal: The goal to check
183
+ goal_subspace: The goal subspace to check against
184
+
185
+ Returns:
186
+ bool: True if the goal is within the subspace, False otherwise
187
+ """
188
+ env = gym.make(id=self.name)
189
+ while env is not None and hasattr(env, "env"):
190
+ if isinstance(env, GoalRecognitionWrapper) and hasattr(
191
+ env, "is_goal_in_subspace"
192
+ ):
193
+ # If the environment has a goal recognition wrapper, use its method
194
+ return env.is_goal_in_subspace(goal)
195
+ # Traverse through wrappers to find the base environment
196
+ env = env.env
197
+
198
+ return True
199
+
149
200
 
150
201
  class GCEnvProperty(EnvProperty):
151
202
  """
@@ -174,16 +225,25 @@ class MinigridProperty(EnvProperty):
174
225
  super().__init__(name)
175
226
  self.domain_name = "minigrid"
176
227
 
228
+ def goal_to_str(self, goal):
229
+ """
230
+ Convert a goal to a string representation.
231
+ """
232
+ return f"{goal[0]}x{goal[1]}"
233
+
177
234
  def goal_to_problem_str(self, goal):
178
235
  """
179
236
  Convert a goal to a problem string.
180
237
  """
181
- return self.name + f"-DynamicGoal-{goal[0]}x{goal[1]}-v0"
238
+ return self.name + f"-DynamicGoal-{self.goal_to_str(goal)}-v0"
182
239
 
183
- def str_to_goal(self, problem_name):
240
+ def str_to_goal(self, problem_name=None):
184
241
  """
185
242
  Convert a problem name to a goal.
186
243
  """
244
+ if problem_name is None:
245
+ problem_name = self.name
246
+
187
247
  parts = problem_name.split("-")
188
248
  goal_part = [part for part in parts if "x" in part]
189
249
  width, height = goal_part[0].split("x")
@@ -305,30 +365,36 @@ class PandaProperty(GCEnvProperty):
305
365
  super().__init__(name)
306
366
  self.domain_name = "panda"
307
367
 
308
- def str_to_goal(self, problem_name):
368
+ def str_to_goal(self, problem_name=None):
309
369
  """
310
370
  Convert a problem name to a goal.
311
371
  """
372
+ if problem_name is None:
373
+ return "general"
312
374
  try:
313
375
  numeric_part = problem_name.split("PandaMyReachDenseX")[1]
314
376
  components = [
315
377
  component.replace("-v3", "").replace("y", ".").replace("M", "-")
316
378
  for component in numeric_part.split("X")
317
379
  ]
318
- floats = []
319
- for component in components:
320
- floats.append(float(component))
321
- return np.array([floats], dtype=np.float32)
380
+ floats = [float(component) for component in components]
381
+ return np.array([floats])
322
382
  except Exception:
323
383
  return "general"
324
384
 
325
- def goal_to_problem_str(self, goal):
385
+ def goal_to_str(self, goal):
326
386
  """
327
- Convert a goal to a problem string.
387
+ Convert a goal to a string representation.
328
388
  """
329
- goal_str = "X".join(
389
+ return "X".join(
330
390
  [str(float(g)).replace(".", "y").replace("-", "M") for g in goal[0]]
331
391
  )
392
+
393
+ def goal_to_problem_str(self, goal):
394
+ """
395
+ Convert a goal to a problem string.
396
+ """
397
+ goal_str = self.goal_to_str(goal)
332
398
  return f"PandaMyReachDenseX{goal_str}-v3"
333
399
 
334
400
  def gc_adaptable(self):
@@ -430,10 +496,34 @@ class ParkingProperty(GCEnvProperty):
430
496
  super().__init__(name)
431
497
  self.domain_name = "parking"
432
498
 
499
+ def str_to_goal(self, problem_name=None):
500
+ """
501
+ Convert a problem name to a goal.
502
+ """
503
+ if not problem_name:
504
+ problem_name = self.name
505
+ # Extract the goal from the part
506
+ return int(problem_name.split("GI-")[1].split("-v0")[0])
507
+
508
+ def goal_to_str(self, goal):
509
+ """
510
+ Convert a goal to a string representation.
511
+ """
512
+ if isinstance(goal, int):
513
+ return str(goal)
514
+ elif isinstance(goal, str):
515
+ return goal
516
+ else:
517
+ raise ValueError(
518
+ f"Unsupported goal type: {type(goal)}. Expected int or str."
519
+ )
520
+
433
521
  def goal_to_problem_str(self, goal):
434
522
  """
435
523
  Convert a goal to a problem string.
436
524
  """
525
+ if "-GI-" in self.name:
526
+ return self.name.split("-GI-")[0] + f"-GI-{goal}-v0"
437
527
  return self.name.split("-v0")[0] + f"-GI-{goal}-v0"
438
528
 
439
529
  def gc_adaptable(self):
@@ -516,9 +606,11 @@ class PointMazeProperty(EnvProperty):
516
606
  super().__init__(name)
517
607
  self.domain_name = "point_maze"
518
608
 
519
- def str_to_goal(self):
609
+ def str_to_goal(self, problem_name=None):
520
610
  """Convert a problem name to a goal."""
521
- parts = self.name.split("-")
611
+ if not problem_name:
612
+ problem_name = self.name
613
+ parts = problem_name.split("-")
522
614
  # Find the part containing the goal size (usually after "DynamicGoal")
523
615
  sizes_parts = [part for part in parts if "x" in part]
524
616
  goal_part = sizes_parts[1]
@@ -526,9 +618,15 @@ class PointMazeProperty(EnvProperty):
526
618
  width, height = goal_part.split("x")
527
619
  return (int(width), int(height))
528
620
 
621
+ def goal_to_str(self, goal):
622
+ """
623
+ Convert a goal to a string representation.
624
+ """
625
+ return f"{goal[0]}x{goal[1]}"
626
+
529
627
  def gc_adaptable(self):
530
628
  """Check if the environment is goal-conditioned adaptable."""
531
- return False
629
+ return True
532
630
 
533
631
  def problem_list_to_str_tuple(self, problems):
534
632
  """Convert a list of problems to a string tuple."""
@@ -554,7 +652,12 @@ class PointMazeProperty(EnvProperty):
554
652
  """
555
653
  Convert a goal to a problem string.
556
654
  """
557
- return self.name + f"-Goal-{goal[0]}x{goal[1]}"
655
+ possible_suffixes = ["-Goals-", "-Goal-", "-MultiGoals-", "-GoalConditioned-"]
656
+ for suffix in possible_suffixes:
657
+ if suffix in self.name:
658
+ return self.name.split(suffix)[0] + f"-Goal-{self.goal_to_str(goal)}"
659
+
660
+ return self.name + f"-Goal-{self.goal_to_str(goal)}"
558
661
 
559
662
  def change_done_by_specific_desired(self, obs, desired, old_success_done):
560
663
  """
@@ -572,6 +675,12 @@ class PointMazeProperty(EnvProperty):
572
675
  assert isinstance(done, np.ndarray)
573
676
  return done[0]
574
677
 
678
+ def use_goal_directed_problem(self):
679
+ """
680
+ Check if the environment uses a goal-directed problem.
681
+ """
682
+ return True
683
+
575
684
  def is_success(self, info):
576
685
  """
577
686
  Check if the episode is successful.