Skip to content

Commit 7d6377a

Browse files
authored
Add EnvFactory.ClassicControl typings, Improve README (#2)
* add classic control factory * build in all branches * remove regex * add readme data
1 parent 563f3c3 commit 7d6377a

File tree

4 files changed

+138
-8
lines changed

4 files changed

+138
-8
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: Build
22

33
on:
44
push:
5-
branches: [ main ]
65
jobs:
76
Build:
87
runs-on: ubuntu-latest

README.md

Lines changed: 94 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,105 @@
11
# ScalaPy Gym Facade
2-
A ScalaPy Facade for OpenAI Gym!
2+
A [ScalaPy](https://scalapy.dev/) Facade for OpenAI Gym!
33
## Quality
44
[![DeepSource](https://deepsource.io/gh/cric96/scalapy-gym.svg/?label=active+issues&show_trend=true&token=sesd4g2NALBojik4-0diuFj8)](https://deepsource.io/gh/cric96/scalapy-gym/?ref=repository-badge)
55
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/63e1dd4638ba4874983e89abb354ed26)](https://www.codacy.com/gh/cric96/scalapy-gym/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cric96/scalapy-gym&utm_campaign=Badge_Grade)
66
[![Codacy Badge](https://app.codacy.com/project/badge/Coverage/63e1dd4638ba4874983e89abb354ed26)](https://www.codacy.com/gh/cric96/scalapy-gym/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cric96/scalapy-gym&utm_campaign=Badge_Coverage)
77
## CI status
8-
![Build](https://github.com/cric96/scalapy-gym/actions/workflows/build.yml/badge.svg)
8+
| Main | Develop |
9+
|---|---|
10+
| ![Build](https://github.com/cric96/scalapy-gym/actions/workflows/build.yml/badge.svg) | ![Build](https://github.com/cric96/scalapy-gym/actions/workflows/build.yml/badge.svg?branch=develop) |
911
## Links
1012
[![Scala Doc](https://img.shields.io/badge/-Scala%20doc-red?logo=scala)](https://cric96.github.io/scalapy-gym/latest/api/)
11-
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.cric96/scalapy-gym_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.cric96/scalapy-gym_2.13/badge.svg)
13+
14+
## What this project supports
15+
The main aim of this facade consist in using the basic environment describe in [OpenAI Gym](http://gym.openai.com/envs/#classic_control).
16+
17+
Currently, there is no interesting in creating environment Scala side. The workflow idea is:
18+
- develop your reinforcement learning in Scala,
19+
- create a functional facade to interact with ScalaPy Gym
20+
- test your algorithms in Open AI baselines and share your results!
21+
22+
## Installation
23+
First of all, you should setup your ScalaPy project correctly, please refer to [this](https://scalapy.dev/docs/) documentation:
24+
25+
Then, you should add this library as dependecy in your sbt file:
26+
```
27+
libraryDependencies += "io.github.cric96" %% "scalapy-gym" % "<x.y.z>"
28+
```
29+
The latest version is: [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.cric96/scalapy-gym_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.github.cric96/scalapy-gym_2.13/badge.svg)
30+
31+
Then you should install OpenAI dependencies. I suggest you to use `pyenv`. BTW, the main dependencies are:
32+
- gym
33+
- scipy
34+
35+
Look to [requirements.txt](/requirements.txt).
36+
37+
To use other environment (`box2d` or `MuJuCo` and `Atari`), please refer to [OpenAI Documentation](http://gym.openai.com/docs/).
38+
39+
## How to use
40+
41+
This library try to make environments type safe. So you add to define:
42+
- action type
43+
- observation type
44+
- action space type
45+
- observation space type
46+
47+
For example, for [FrozenLake](http://gym.openai.com/envs/FrozenLake-v0/) you should write:
48+
```scala
49+
val env = Gym.make[Int, Int, Discrete, Discrete]("FrozenLake-v0")
50+
```
51+
52+
If you do not care about the action and observation type, you can type:
53+
```scala
54+
val env = Gym.unsafe("FrozenLake-v0")
55+
```
56+
57+
A simple loop that advance in the simulation could be:
58+
```scala
59+
import io.github.cric96.gym.Gym
60+
val env = Gym.unsafe("FrozenLake-v0") // or EnvFactory.ToyText.frozenLakeV0
61+
env.reset()
62+
val observations = (0 to 1000)
63+
.tapEach(_ => env.render)
64+
.map(env.step(env.actionSpace.sample()))
65+
env.close()
66+
```
67+
68+
The python counterpart is:
69+
```python
70+
71+
val env = Gym.unsafe("FrozenLake-v0")
72+
env.reset()
73+
for _ in range(1000):
74+
env.render()
75+
env.step(env.action_space.sample()) # take a random action
76+
env.close()
77+
```
78+
79+
As you can see, the experience is very similar :)
80+
81+
Some environments, has already the correct typing (Looks to [EnvFactory](/src/main/scala/gym/envs/EnvFactory.scala))
82+
83+
### Typings
84+
- ToyTest
85+
- [x] FrozenLake
86+
- [x] FrozenLake
87+
- [x] GuessingGame
88+
- [x] HotterColder
89+
- [x] nChain
90+
- [x] Roulette
91+
- ClassicControl
92+
- [x] Acrobot
93+
- [x] CartPole
94+
- [x] MountainCar
95+
- [x] MountainCarContinuous
96+
- [x] Pendulum
97+
- [ ] Atari
98+
- [ ] Box2D
99+
- [ ] MuJoCo
100+
- [ ] Robotics
101+
- [ ] Algorithms
102+
12103

13104
## Example
14105
- [Basic Q-Learning implementation](https://github.com/cric96/scala-rl-examples/blob/main/qlearning.ipynb)

src/main/scala/gym/envs/EnvFactory.scala

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package io.github.cric96
22
package gym.envs
33

4-
import gym.Gym
4+
import gym.{ExternalType, Gym}
55
import gym.core.Env
66
import gym.spaces.{Box, Discrete, Tuple}
77

88
/** a facade for some of the standard open ai environments */
9-
object EnvFactory {
9+
object EnvFactory extends App {
1010

1111
object ToyText {
1212

@@ -22,5 +22,21 @@ object EnvFactory {
2222
def rouletteV0(): Env[Int, Int, Discrete, Discrete] = Gym.make[Int, Int, Discrete, Discrete]("Roulette-v0")
2323
}
2424

25-
object ClassicControl
25+
object ClassicControl {
26+
27+
def acrobotV1(): Env[Int, ExternalType.NumpyArray, Discrete, Box] =
28+
Gym.make[Int, ExternalType.NumpyArray, Discrete, Box]("Acrobot-v1")
29+
30+
def cartPoleV1(): Env[Int, ExternalType.NumpyArray, Discrete, Box] =
31+
Gym.make[Int, ExternalType.NumpyArray, Discrete, Box]("CartPole-v1")
32+
33+
def mountainCarV0(): Env[Int, ExternalType.NumpyArray, Discrete, Box] =
34+
Gym.make[Int, ExternalType.NumpyArray, Discrete, Box]("MountainCar-v0")
35+
36+
def mountainCarContinuousV0(): Env[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box] =
37+
Gym.make[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box]("MountainCarContinuous-v0")
38+
39+
def pendulumV0(): Env[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box] =
40+
Gym.make[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box]("Pendulum-v0")
41+
}
2642
}

src/test/scala/gym/envs/EnvFactoryTest.scala

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package io.github.cric96
22
package gym.envs
33

4+
import gym.ExternalType
45
import gym.core.Env
5-
import gym.envs.EnvFactory.ToyText
6+
import gym.envs.EnvFactory.{ClassicControl, ToyText}
67
import gym.spaces.{Box, Discrete, Space, Tuple}
78

89
import me.shadaj.scalapy.readwrite.{Reader, Writer}
@@ -58,6 +59,29 @@ object EnvFactoryTest extends TestSuite {
5859
assert(checkEnv[Int, Int, Discrete, Discrete](ToyText.rouletteV0()))
5960
}
6061
}
62+
63+
test("ClassicControl") {
64+
test("acrobotV1 should be correctly typed") {
65+
assert(checkEnv[Int, ExternalType.NumpyArray, Discrete, Box](ClassicControl.acrobotV1()))
66+
}
67+
test("cartPoleV1 should be correctly typed") {
68+
assert(checkEnv[Int, ExternalType.NumpyArray, Discrete, Box](ClassicControl.cartPoleV1()))
69+
}
70+
test("mountainCarV0 should be correctly typed") {
71+
assert(checkEnv[Int, ExternalType.NumpyArray, Discrete, Box](ClassicControl.mountainCarV0()))
72+
}
73+
74+
test("mountainCarContinuousV0 should be correctly typed") {
75+
assert(
76+
checkEnv[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box](
77+
ClassicControl.mountainCarContinuousV0()
78+
)
79+
)
80+
}
81+
test("pendulumV0 should be correctly typed") {
82+
assert(checkEnv[ExternalType.NumpyArray, ExternalType.NumpyArray, Box, Box](ClassicControl.pendulumV0()))
83+
}
84+
}
6185
}
6286
}
6387
}

0 commit comments

Comments
 (0)