tinybaselines 0.1.0a4__tar.gz → 0.1.0a5__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 (70) hide show
  1. tinybaselines-0.1.0a5/MANIFEST.in +1 -0
  2. {tinybaselines-0.1.0a4/tinybaselines.egg-info → tinybaselines-0.1.0a5}/PKG-INFO +6 -2
  3. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/README.md +5 -1
  4. tinybaselines-0.1.0a5/examples/cartpole/README.md +5 -0
  5. tinybaselines-0.1.0a5/examples/cartpole/checkpoint.png +0 -0
  6. tinybaselines-0.1.0a5/examples/lunar_lander/README.md +6 -0
  7. tinybaselines-0.1.0a5/examples/lunar_lander/checkpoint.png +0 -0
  8. tinybaselines-0.1.0a5/examples/pendulum/README.md +6 -0
  9. tinybaselines-0.1.0a5/examples/pendulum/checkpoint.png +0 -0
  10. tinybaselines-0.1.0a5/examples/puffer/README.md +57 -0
  11. tinybaselines-0.1.0a5/examples/puffer/checkpoint.png +0 -0
  12. tinybaselines-0.1.0a5/examples/puffer/env.py +83 -0
  13. tinybaselines-0.1.0a5/examples/puffer/results/observations.jsonl +10 -0
  14. tinybaselines-0.1.0a5/examples/puffer/smoke.py +43 -0
  15. tinybaselines-0.1.0a5/examples/puffer/squared_bridge.c +17 -0
  16. tinybaselines-0.1.0a5/examples/puffer/squared_smoke.c +39 -0
  17. tinybaselines-0.1.0a5/examples/puffer/train.py +66 -0
  18. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/pyproject.toml +1 -1
  19. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5/tinybaselines.egg-info}/PKG-INFO +6 -2
  20. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines.egg-info/SOURCES.txt +14 -0
  21. tinybaselines-0.1.0a4/MANIFEST.in +0 -1
  22. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/LICENSE +0 -0
  23. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/__init__.py +0 -0
  24. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/cartpole/results/cpu.jsonl +0 -0
  25. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/cartpole/train.py +0 -0
  26. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/__init__.py +0 -0
  27. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/config.py +0 -0
  28. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/reference.py +0 -0
  29. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/requirements-reference.txt +0 -0
  30. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/requirements.txt +0 -0
  31. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-initial-tinygrad-thread4.jsonl +0 -0
  32. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-initial-torch.jsonl +0 -0
  33. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-protocol.json +0 -0
  34. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-tinygrad-thread10.jsonl +0 -0
  35. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-tinygrad-thread4-error.jsonl +0 -0
  36. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/phase-torch-thread4.jsonl +0 -0
  37. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/protocol.json +0 -0
  38. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/tinygrad-cpu.jsonl +0 -0
  39. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/2026-10-26/torch-cpu.jsonl +0 -0
  40. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/results/cpu-padding.jsonl +0 -0
  41. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/run_learning.py +0 -0
  42. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/lunar_lander/train.py +0 -0
  43. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/__init__.py +0 -0
  44. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/env.py +0 -0
  45. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/requirements.txt +0 -0
  46. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/results/cpu-2.jsonl +0 -0
  47. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/results/cpu-3.jsonl +0 -0
  48. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/results/cpu.jsonl +0 -0
  49. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/examples/pendulum/train.py +0 -0
  50. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/requirements.txt +0 -0
  51. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/setup.cfg +0 -0
  52. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_cartpole.py +0 -0
  53. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_checkpoint.py +0 -0
  54. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_core.py +0 -0
  55. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_evaluation.py +0 -0
  56. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_learning.py +0 -0
  57. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_learning_run.py +0 -0
  58. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_parity.py +0 -0
  59. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_pendulum.py +0 -0
  60. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_rollout.py +0 -0
  61. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tests/test_training.py +0 -0
  62. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/__init__.py +0 -0
  63. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/evaluation.py +0 -0
  64. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/policies.py +0 -0
  65. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/ppo.py +0 -0
  66. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/rollout.py +0 -0
  67. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines/training.py +0 -0
  68. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines.egg-info/dependency_links.txt +0 -0
  69. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines.egg-info/requires.txt +0 -0
  70. {tinybaselines-0.1.0a4 → tinybaselines-0.1.0a5}/tinybaselines.egg-info/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+ recursive-include examples *.py *.txt *.json *.jsonl *.c *.png README.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinybaselines
3
- Version: 0.1.0a4
3
+ Version: 0.1.0a5
4
4
  Summary: PPO in tinygrad.
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.11
@@ -21,7 +21,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
21
21
  ```sh
22
22
  python3.11 -m venv .venv
23
23
  source .venv/bin/activate
24
- python -m pip install tinybaselines==0.1.0a4
24
+ python -m pip install tinybaselines==0.1.0a5
25
25
  ```
26
26
 
27
27
  Install Gymnasium and Box2D to run this example:
@@ -79,6 +79,10 @@ Each `learn` call starts fresh episodes and a new transition counter.
79
79
 
80
80
  ## Repository examples
81
81
 
82
+ Example READMEs and screenshots: [LunarLander](examples/lunar_lander/README.md),
83
+ [CartPole](examples/cartpole/README.md), [Pendulum](examples/pendulum/README.md),
84
+ and [Squared Continuous](examples/puffer/README.md).
85
+
82
86
  From a checkout, run the full LunarLander trainer:
83
87
 
84
88
  ```sh
@@ -9,7 +9,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
9
9
  ```sh
10
10
  python3.11 -m venv .venv
11
11
  source .venv/bin/activate
12
- python -m pip install tinybaselines==0.1.0a4
12
+ python -m pip install tinybaselines==0.1.0a5
13
13
  ```
14
14
 
15
15
  Install Gymnasium and Box2D to run this example:
@@ -67,6 +67,10 @@ Each `learn` call starts fresh episodes and a new transition counter.
67
67
 
68
68
  ## Repository examples
69
69
 
70
+ Example READMEs and screenshots: [LunarLander](examples/lunar_lander/README.md),
71
+ [CartPole](examples/cartpole/README.md), [Pendulum](examples/pendulum/README.md),
72
+ and [Squared Continuous](examples/puffer/README.md).
73
+
70
74
  From a checkout, run the full LunarLander trainer:
71
75
 
72
76
  ```sh
@@ -0,0 +1,5 @@
1
+ # CartPole
2
+
3
+ ![The pole upright over the cart](checkpoint.png)
4
+
5
+ Step 450 of a 500-step sampled episode from a reloaded PPO checkpoint.
@@ -0,0 +1,6 @@
1
+ # LunarLander
2
+
3
+ ![The lander resting between the landing flags](checkpoint.png)
4
+
5
+ Safe landing in a sampled episode from a reloaded PPO checkpoint.
6
+ The episode return was 219.8.
@@ -0,0 +1,6 @@
1
+ # Pendulum
2
+
3
+ ![The pendulum balancing near upright](checkpoint.png)
4
+
5
+ Balancing near upright at step 150. The reloaded PPO policy scored −123.9
6
+ in this sampled episode.
@@ -0,0 +1,57 @@
1
+ # PufferLib Squared Continuous
2
+
3
+ ![The cyan agent one diagonal move from the red target](checkpoint.png)
4
+
5
+ Live board one move before the reloaded PPO policy earned +1. The next step
6
+ reached the target and reset the board.
7
+
8
+ Native CPU smoke test on macOS. It calls PufferLib's reset and step functions
9
+ directly and opens no window. Run from the tinybaselines checkout:
10
+
11
+ ```sh
12
+ puffer_smoke=$(mktemp -d)
13
+ git init "$puffer_smoke/pufferlib"
14
+ git -C "$puffer_smoke/pufferlib" fetch --depth=1 https://github.com/PufferAI/PufferLib.git ea7f989371270d2948f96728bda8aec5e7634a4c
15
+ git -C "$puffer_smoke/pufferlib" checkout --detach FETCH_HEAD
16
+ curl -fL https://github.com/raysan5/raylib/releases/download/5.5/raylib-5.5_macos.tar.gz \
17
+ -o "$puffer_smoke/raylib.tar.gz"
18
+ tar -xzf "$puffer_smoke/raylib.tar.gz" -C "$puffer_smoke"
19
+ clang -O2 -I"$puffer_smoke/pufferlib" -I"$puffer_smoke/pufferlib/src" \
20
+ -I"$puffer_smoke/raylib-5.5_macos/include" examples/puffer/squared_smoke.c \
21
+ "$puffer_smoke/raylib-5.5_macos/lib/libraylib.a" \
22
+ -framework Cocoa -framework IOKit -framework CoreVideo -framework OpenGL \
23
+ -o "$puffer_smoke/squared_smoke"
24
+ "$puffer_smoke/squared_smoke"
25
+ ```
26
+
27
+ With tinybaselines installed, build the Python adapter's shared library and run
28
+ its reset checks and one PPO update:
29
+
30
+ ```sh
31
+ clang -O2 -dynamiclib -I"$puffer_smoke/pufferlib" -I"$puffer_smoke/pufferlib/src" \
32
+ -I"$puffer_smoke/raylib-5.5_macos/include" examples/puffer/squared_bridge.c \
33
+ "$puffer_smoke/raylib-5.5_macos/lib/libraylib.a" \
34
+ -framework Cocoa -framework IOKit -framework CoreVideo -framework OpenGL \
35
+ -o "$puffer_smoke/libsquared.dylib"
36
+ DEV=CPU BEAM=0 python -m examples.puffer.smoke "$puffer_smoke/libsquared.dylib"
37
+ ```
38
+
39
+ Train for 204,800 transitions across four environments:
40
+
41
+ ```sh
42
+ DEV=CPU BEAM=0 python -m examples.puffer.train "$puffer_smoke/libsquared.dylib" \
43
+ --output runs/puffer-squared-ppo
44
+ ```
45
+
46
+ The run saves `ppo.safetensors` and records goals over 100 sampled episodes
47
+ before training and after checkpoint reload.
48
+
49
+ The default observation is the centered agent and target coordinates, divided by
50
+ 5. Use `--observations board` for the flat grid or `--observations relative` for
51
+ the agent coordinates and signed target offset. Use the same observation mode
52
+ when evaluating a saved policy.
53
+
54
+ At the same budget, three runs per mode reached 56/300 goals with the board,
55
+ 299/300 with absolute coordinates, and 296/300 with relative coordinates. Each
56
+ score uses 100 fresh sampled episodes per reloaded checkpoint.
57
+ [Settings and episode returns](results/observations.jsonl).
@@ -0,0 +1,83 @@
1
+ from ctypes import CDLL, c_uint, c_void_p
2
+
3
+ import numpy as np
4
+
5
+
6
+ class SquaredVectorEnv:
7
+ """Headless native environments. Observations and rewards reuse their buffers."""
8
+
9
+ metadata = {'autoreset_mode': 'SameStep'}
10
+
11
+ def __init__(self, library, num_envs=4):
12
+ if num_envs <= 0:
13
+ raise ValueError('num_envs must be positive')
14
+ self.num_envs = num_envs
15
+ self._lib = CDLL(str(library))
16
+ self._lib.squared_create.argtypes = [c_void_p] * 4 + [c_uint]
17
+ self._lib.squared_create.restype = c_void_p
18
+ for name in ('puf_reset', 'puf_step', 'squared_destroy'):
19
+ function = getattr(self._lib, name)
20
+ function.argtypes = [c_void_p]
21
+ function.restype = None
22
+
23
+ self._observations = np.empty((num_envs, 121), dtype=np.uint8)
24
+ self._actions = np.zeros((num_envs, 2), dtype=np.float32)
25
+ self._rewards = np.zeros(num_envs, dtype=np.float32)
26
+ self._terminals = np.zeros(num_envs, dtype=np.float32)
27
+ self._envs = []
28
+ try:
29
+ for i, seed in enumerate(np.random.SeedSequence().generate_state(num_envs)):
30
+ handle = self._lib.squared_create(
31
+ self._observations[i].ctypes.data, self._actions[i].ctypes.data,
32
+ self._rewards[i:i+1].ctypes.data, self._terminals[i:i+1].ctypes.data, int(seed))
33
+ if not handle:
34
+ raise MemoryError('could not allocate Squared Continuous')
35
+ self._envs.append(handle)
36
+ except BaseException:
37
+ self.close()
38
+ raise
39
+
40
+ def reset(self):
41
+ if not self._envs:
42
+ raise RuntimeError('environment is closed')
43
+ for handle in self._envs:
44
+ self._lib.puf_reset(handle)
45
+ self._rewards.fill(0)
46
+ self._terminals.fill(0)
47
+ return self._observations, {}
48
+
49
+ def step(self, actions):
50
+ if not self._envs:
51
+ raise RuntimeError('environment is closed')
52
+ self._actions[:] = actions
53
+ for handle in self._envs:
54
+ self._lib.puf_step(handle)
55
+ # The native timeout is a terminal loss, with an immediate reset.
56
+ return self._observations, self._rewards, self._terminals.astype(bool), np.zeros(self.num_envs, bool), {}
57
+
58
+ def close(self):
59
+ for handle in self._envs:
60
+ self._lib.squared_destroy(handle)
61
+ self._envs.clear()
62
+
63
+
64
+ class CoordinateSquaredVectorEnv(SquaredVectorEnv):
65
+ def __init__(self, library, num_envs=4, *, relative):
66
+ super().__init__(library, num_envs)
67
+ self.relative = relative
68
+
69
+ def _observe(self, board):
70
+ def position(tile):
71
+ return np.column_stack(np.divmod((board == tile).argmax(axis=1), 11))
72
+
73
+ agent, target = position(1), position(2)
74
+ target_features = target - agent if self.relative else target - 5
75
+ return np.concatenate((agent - 5, target_features), axis=1).astype(np.float32) / 5
76
+
77
+ def reset(self):
78
+ board, info = super().reset()
79
+ return self._observe(board), info
80
+
81
+ def step(self, actions):
82
+ board, *transition = super().step(actions)
83
+ return self._observe(board), *transition
@@ -0,0 +1,10 @@
1
+ {"event":"config","platform":"macOS-27.0.1-arm64-arm-64bit","python":"3.11.14","versions":{"tinygrad":"0.14.0","numpy":"2.4.6"},"library_sha256":"c83b0740db881ebd616282528e4b224a456d92074b7666b156edaff8f744c0c1","device":"CPU","num_envs":4,"requested_timesteps":204800,"rollout_steps":2048,"deterministic":false,"policy":{"action_dim":2,"hidden_dim":64,"actor_layers":2,"critic_layers":2},"ppo":{"pi_lr":0.0003000000142492354,"vf_lr":0.0010000000474974513,"gamma":0.99,"lamda":0.95,"K_epochs":4,"eps_clip":0.2,"batch_size":256,"vf_coef":0.5,"entropy_coef":0.001},"modes":{"board":{"source_commit":"5629a259ba3d9a6f8e1ea93e7b72bc41913eee64","state_dim":121},"relative":{"source_commit":"5629a259ba3d9a6f8e1ea93e7b72bc41913eee64","state_dim":4},"absolute":{"source_commit":"5629a259ba3d9a6f8e1ea93e7b72bc41913eee64","state_dim":4}},"evaluation_episodes":100,"run_order":["board-1","relative-1","relative-2","board-2","board-3","relative-3","absolute-1","absolute-2","absolute-3"]}
2
+ {"event":"result","observations":"board","trial":1,"training_seconds":67.8307276670239,"initial":{"goals":10,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0]},"final":{"goals":25,"episodes":100,"episode_returns":[-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,1.0,-1.0,-1.0]}}
3
+ {"event":"result","observations":"board","trial":2,"training_seconds":65.84727108303923,"initial":{"goals":4,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0]},"final":{"goals":18,"episodes":100,"episode_returns":[1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0]}}
4
+ {"event":"result","observations":"board","trial":3,"training_seconds":67.56618995795725,"initial":{"goals":4,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0]},"final":{"goals":13,"episodes":100,"episode_returns":[-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0]}}
5
+ {"event":"result","observations":"relative","trial":1,"training_seconds":61.09397924999939,"initial":{"goals":16,"episodes":100,"episode_returns":[-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0]},"final":{"goals":99,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
6
+ {"event":"result","observations":"relative","trial":2,"training_seconds":60.07157345901942,"initial":{"goals":16,"episodes":100,"episode_returns":[1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0]},"final":{"goals":100,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
7
+ {"event":"result","observations":"relative","trial":3,"training_seconds":61.71542754204711,"initial":{"goals":10,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0]},"final":{"goals":97,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
8
+ {"event":"result","observations":"absolute","trial":1,"training_seconds":61.760505666956306,"initial":{"goals":13,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0]},"final":{"goals":99,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
9
+ {"event":"result","observations":"absolute","trial":2,"training_seconds":59.79912408301607,"initial":{"goals":16,"episodes":100,"episode_returns":[1.0,1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0]},"final":{"goals":100,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
10
+ {"event":"result","observations":"absolute","trial":3,"training_seconds":60.650998707977124,"initial":{"goals":7,"episodes":100,"episode_returns":[-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0,-1.0]},"final":{"goals":100,"episodes":100,"episode_returns":[1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0]}}
@@ -0,0 +1,43 @@
1
+ import sys
2
+ from contextlib import closing
3
+
4
+ import numpy as np
5
+
6
+ from tinybaselines import GaussianActorCritic, PPO, learn
7
+ from .env import SquaredVectorEnv
8
+
9
+
10
+ def main(library):
11
+ with closing(SquaredVectorEnv(library)) as env:
12
+ observations, _ = env.reset()
13
+ observations[observations == 2] = 0
14
+ observations[:, 61] = 2 # One tile right of the centered agent.
15
+ actions = np.zeros((4, 2), dtype=np.float32)
16
+ actions[:2, 1] = 1
17
+ observations, rewards, terminated, truncated, _ = env.step(actions)
18
+ np.testing.assert_array_equal(rewards, [1, 1, 0, 0])
19
+ np.testing.assert_array_equal(terminated, [True, True, False, False])
20
+ assert not truncated.any() and np.all(observations[2:, 61] == 2)
21
+ assert np.all(observations[:, 60] == 1)
22
+ env.reset()
23
+ actions.fill(0)
24
+ for _ in range(33):
25
+ _, rewards, terminated, truncated, _ = env.step(actions)
26
+ assert np.all(rewards == 0) and not terminated.any() and not truncated.any()
27
+ observations, rewards, terminated, truncated, _ = env.step(actions)
28
+ assert np.all(rewards == -1) and terminated.all() and not truncated.any()
29
+ assert np.all(observations[:, 60] == 1)
30
+ print('Goal and timeout rewards and terminal flags survive same-step resets.')
31
+
32
+ policy = GaussianActorCritic(121, 2, 16, 1, 1)
33
+ ppo = PPO(policy, pi_lr=1e-3, vf_lr=1e-3, gamma=0.99, lamda=0.95, K_epochs=1,
34
+ eps_clip=0.2, batch_size=256, vf_coef=0.5, entropy_coef=0.01)
35
+ before = policy.log_std.numpy().copy()
36
+ step, = learn(env, ppo, total_timesteps=256, rollout_steps=256)
37
+ assert step.timesteps == 256 and step.episode_returns
38
+ assert np.isfinite(policy.log_std.numpy()).all() and not np.array_equal(policy.log_std.numpy(), before)
39
+ print(f'One PPO update on {step.timesteps} transitions, {len(step.episode_returns)} finished episodes.')
40
+
41
+
42
+ if __name__ == '__main__':
43
+ main(sys.argv[1])
@@ -0,0 +1,17 @@
1
+ #include "ocean/squared_continuous/squared_continuous.h"
2
+
3
+ Squared* squared_create(obs_t* observations, float* actions, float* reward, float* terminal, unsigned int seed) {
4
+ Squared* env = calloc(1, sizeof(*env));
5
+ if (!env) return NULL;
6
+ DictItem size = {.key = "size", .value = 11};
7
+ Dict options = {.items = &size, .size = 1, .cap = 1};
8
+ env->rng = seed;
9
+ env->agents[0] = (Agent){.observations = observations, .actions = actions,
10
+ .rewards = reward, .terminals = terminal};
11
+ puf_init(env, &options);
12
+ return env;
13
+ }
14
+
15
+ void squared_destroy(Squared* env) {
16
+ free(env);
17
+ }
@@ -0,0 +1,39 @@
1
+ #include <assert.h>
2
+
3
+ #include "ocean/squared_continuous/squared_continuous.h"
4
+
5
+ int main(void) {
6
+ obs_t observations[OBS_SIZE] = {0};
7
+ float actions[NUM_ATNS] = {0}, reward = 0, terminal = 0;
8
+ DictItem size = {.key = "size", .value = 11};
9
+ Dict options = {.items = &size, .size = 1, .cap = 1};
10
+ Squared env = {.rng = 1};
11
+ env.agents[0] = (Agent){.observations = observations, .actions = actions,
12
+ .rewards = &reward, .terminals = &terminal};
13
+ puf_init(&env, &options);
14
+ puf_reset(&env);
15
+
16
+ const int center = OBS_SIZE / 2;
17
+ assert(env.num_agents == 1 && observations[center] == AGENT && !IsWindowReady());
18
+ memset(observations, EMPTY, sizeof(observations));
19
+ observations[center] = AGENT;
20
+ observations[center + 1] = TARGET;
21
+
22
+ actions[1] = 0.2f;
23
+ puf_step(&env);
24
+ assert(reward == 0 && terminal == 0 && observations[center] == AGENT);
25
+ actions[1] = 0.3f;
26
+ puf_step(&env);
27
+ assert(reward == 1 && terminal == 1 && env.tick == 0 && observations[center] == AGENT);
28
+
29
+ actions[1] = 0;
30
+ for (int i = 0; i < 3 * env.size; i++) {
31
+ puf_step(&env);
32
+ assert(reward == 0 && terminal == 0);
33
+ }
34
+ puf_step(&env);
35
+ assert(reward == -1 && terminal == 1 && env.tick == 0 && observations[center] == AGENT);
36
+ assert(!IsWindowReady());
37
+ puf_close(&env);
38
+ puts("Squared Continuous: movement threshold, goal, timeout, and same-step reset passed.");
39
+ }
@@ -0,0 +1,66 @@
1
+ import argparse
2
+ from contextlib import closing
3
+ from hashlib import sha256
4
+ from importlib.metadata import version
5
+ import json
6
+ from pathlib import Path
7
+ import platform
8
+ import subprocess
9
+ from time import perf_counter
10
+
11
+ from tinybaselines import GaussianActorCritic, PPO, evaluate, learn
12
+ from .env import CoordinateSquaredVectorEnv, SquaredVectorEnv
13
+
14
+
15
+ def run(library, output, total_timesteps, observations='absolute'):
16
+ output.mkdir(parents=True, exist_ok=False)
17
+ def make_env():
18
+ if observations == 'board':
19
+ return SquaredVectorEnv(library, num_envs=4)
20
+ return CoordinateSquaredVectorEnv(library, num_envs=4, relative=observations == 'relative')
21
+
22
+ state_dim = 121 if observations == 'board' else 4
23
+ policy = GaussianActorCritic(state_dim, 2, 64, 2, 2)
24
+ ppo = PPO(policy, pi_lr=3e-4, vf_lr=1e-3, gamma=0.99, lamda=0.95, K_epochs=4,
25
+ eps_clip=0.2, batch_size=256, vf_coef=0.5, entropy_coef=0.001)
26
+
27
+ with (output / 'metrics.jsonl').open('x') as log:
28
+ def record(event, **fields):
29
+ line = json.dumps(dict(event=event, **fields), allow_nan=False)
30
+ print(line, file=log, flush=True)
31
+ print(line, flush=True)
32
+
33
+ def score(event, actor):
34
+ with closing(make_env()) as env:
35
+ returns = list(map(float, evaluate(env, actor, num_episodes=100, deterministic=False)))
36
+ assert len(returns) == 100 and all(value in (-1, 1) for value in returns)
37
+ record(event, goals=returns.count(1), episodes=len(returns), episode_returns=returns)
38
+
39
+ commit = subprocess.run(['git', 'rev-parse', 'HEAD'], capture_output=True, text=True).stdout.strip()
40
+ record('config', source_commit=commit or None, platform=platform.platform(), python=platform.python_version(),
41
+ versions={name: version(name) for name in ('tinygrad', 'numpy')},
42
+ library_sha256=sha256(library.read_bytes()).hexdigest(), device=ppo.device,
43
+ num_envs=4, requested_timesteps=total_timesteps, rollout_steps=2048,
44
+ deterministic=False, observations=observations, policy=policy.config, ppo=ppo.config)
45
+ score('initial', policy)
46
+ timesteps = 0
47
+ with closing(make_env()) as env:
48
+ started = perf_counter()
49
+ for step in learn(env, ppo, total_timesteps=total_timesteps, rollout_steps=2048):
50
+ timesteps = step.timesteps
51
+ record('update', **step._asdict())
52
+ training_seconds = perf_counter() - started
53
+ checkpoint = output / 'ppo.safetensors'
54
+ ppo.save(checkpoint)
55
+ record('checkpoint', timesteps=timesteps, training_seconds=training_seconds, path=checkpoint.name)
56
+ score('final', PPO.load(checkpoint).actor_critic)
57
+
58
+
59
+ if __name__ == '__main__':
60
+ parser = argparse.ArgumentParser(description='Train PPO on headless Squared Continuous.')
61
+ parser.add_argument('library', type=Path)
62
+ parser.add_argument('--output', required=True, type=Path)
63
+ parser.add_argument('--timesteps', type=int, default=204_800)
64
+ parser.add_argument('--observations', choices=('board', 'absolute', 'relative'), default='absolute')
65
+ args = parser.parse_args()
66
+ run(args.library, args.output, args.timesteps, args.observations)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tinybaselines"
7
- version = "0.1.0a4"
7
+ version = "0.1.0a5"
8
8
  description = "PPO in tinygrad."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinybaselines
3
- Version: 0.1.0a4
3
+ Version: 0.1.0a5
4
4
  Summary: PPO in tinygrad.
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.11
@@ -21,7 +21,7 @@ Use Python 3.11 and clang. The library install does not include Gymnasium.
21
21
  ```sh
22
22
  python3.11 -m venv .venv
23
23
  source .venv/bin/activate
24
- python -m pip install tinybaselines==0.1.0a4
24
+ python -m pip install tinybaselines==0.1.0a5
25
25
  ```
26
26
 
27
27
  Install Gymnasium and Box2D to run this example:
@@ -79,6 +79,10 @@ Each `learn` call starts fresh episodes and a new transition counter.
79
79
 
80
80
  ## Repository examples
81
81
 
82
+ Example READMEs and screenshots: [LunarLander](examples/lunar_lander/README.md),
83
+ [CartPole](examples/cartpole/README.md), [Pendulum](examples/pendulum/README.md),
84
+ and [Squared Continuous](examples/puffer/README.md).
85
+
82
86
  From a checkout, run the full LunarLander trainer:
83
87
 
84
88
  ```sh
@@ -4,9 +4,13 @@ README.md
4
4
  pyproject.toml
5
5
  requirements.txt
6
6
  examples/__init__.py
7
+ examples/cartpole/README.md
8
+ examples/cartpole/checkpoint.png
7
9
  examples/cartpole/train.py
8
10
  examples/cartpole/results/cpu.jsonl
11
+ examples/lunar_lander/README.md
9
12
  examples/lunar_lander/__init__.py
13
+ examples/lunar_lander/checkpoint.png
10
14
  examples/lunar_lander/config.py
11
15
  examples/lunar_lander/reference.py
12
16
  examples/lunar_lander/requirements-reference.txt
@@ -23,13 +27,23 @@ examples/lunar_lander/results/2026-10-26/phase-torch-thread4.jsonl
23
27
  examples/lunar_lander/results/2026-10-26/protocol.json
24
28
  examples/lunar_lander/results/2026-10-26/tinygrad-cpu.jsonl
25
29
  examples/lunar_lander/results/2026-10-26/torch-cpu.jsonl
30
+ examples/pendulum/README.md
26
31
  examples/pendulum/__init__.py
32
+ examples/pendulum/checkpoint.png
27
33
  examples/pendulum/env.py
28
34
  examples/pendulum/requirements.txt
29
35
  examples/pendulum/train.py
30
36
  examples/pendulum/results/cpu-2.jsonl
31
37
  examples/pendulum/results/cpu-3.jsonl
32
38
  examples/pendulum/results/cpu.jsonl
39
+ examples/puffer/README.md
40
+ examples/puffer/checkpoint.png
41
+ examples/puffer/env.py
42
+ examples/puffer/smoke.py
43
+ examples/puffer/squared_bridge.c
44
+ examples/puffer/squared_smoke.c
45
+ examples/puffer/train.py
46
+ examples/puffer/results/observations.jsonl
33
47
  tests/test_cartpole.py
34
48
  tests/test_checkpoint.py
35
49
  tests/test_core.py
@@ -1 +0,0 @@
1
- recursive-include examples *.py *.txt *.json *.jsonl
File without changes