@game_ryo/lsji 0.1.0 → 0.1.1
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.
- package/package.json +4 -1
- package/docs/README.md +0 -43
- package/docs/blog/2019-05-28-first-blog-post.mdx +0 -12
- package/docs/blog/2019-05-29-long-blog-post.mdx +0 -44
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -24
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.mdx +0 -29
- package/docs/blog/authors.yml +0 -25
- package/docs/blog/tags.yml +0 -19
- package/docs/docs/api/agent.md +0 -151
- package/docs/docs/api/env.md +0 -133
- package/docs/docs/api/environments.md +0 -102
- package/docs/docs/api/qlearning.md +0 -138
- package/docs/docs/api/storage.md +0 -168
- package/docs/docs/architecture.md +0 -155
- package/docs/docs/cli.md +0 -210
- package/docs/docs/contributing.md +0 -162
- package/docs/docs/core-concepts.md +0 -152
- package/docs/docs/examples/advanced-training.md +0 -244
- package/docs/docs/examples/custom-environment.md +0 -198
- package/docs/docs/examples/custom-storage.md +0 -251
- package/docs/docs/getting-started.md +0 -91
- package/docs/docusaurus.config.ts +0 -149
- package/docs/package-lock.json +0 -19522
- package/docs/package.json +0 -49
- package/docs/sidebars.ts +0 -33
- package/docs/src/components/HomepageFeatures/index.tsx +0 -71
- package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- package/docs/src/css/custom.css +0 -79
- package/docs/src/pages/index.module.css +0 -23
- package/docs/src/pages/index.tsx +0 -44
- package/docs/src/pages/markdown-page.mdx +0 -7
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.png +0 -0
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docs/tsconfig.json +0 -12
- package/legacy/worker.js +0 -166
- package/legacy/wrangler.toml +0 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@game_ryo/lsji",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "A general-purpose reinforcement learning agent framework (Node.js)",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -22,5 +22,8 @@
|
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"vitest": "^2.0.0"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
25
28
|
}
|
|
26
29
|
}
|
package/docs/README.md
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Website
|
|
2
|
-
|
|
3
|
-
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
**Note**: feel free to use the package manager of your choice.
|
|
12
|
-
|
|
13
|
-
## Local Development
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm run start
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
|
20
|
-
|
|
21
|
-
## Build
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm run build
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
|
28
|
-
|
|
29
|
-
## Deployment
|
|
30
|
-
|
|
31
|
-
Using SSH:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
USE_SSH=true npm run deploy
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
Not using SSH:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
GIT_USER=<Your GitHub username> npm run deploy
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
If you are using GitHub Pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
slug: first-blog-post
|
|
3
|
-
title: First Blog Post
|
|
4
|
-
authors: [slorber, yangshun]
|
|
5
|
-
tags: [hola, docusaurus]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Lorem ipsum dolor sit amet...
|
|
9
|
-
|
|
10
|
-
{/* truncate */}
|
|
11
|
-
|
|
12
|
-
...consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
slug: long-blog-post
|
|
3
|
-
title: Long Blog Post
|
|
4
|
-
authors: yangshun
|
|
5
|
-
tags: [hello, docusaurus]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
This is the summary of a very long blog post,
|
|
9
|
-
|
|
10
|
-
Use a `{/*` `truncate` `*/}` comment to limit blog post size in the list view.
|
|
11
|
-
|
|
12
|
-
{/* truncate */}
|
|
13
|
-
|
|
14
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
15
|
-
|
|
16
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
17
|
-
|
|
18
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
19
|
-
|
|
20
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
21
|
-
|
|
22
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
23
|
-
|
|
24
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
25
|
-
|
|
26
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
27
|
-
|
|
28
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
29
|
-
|
|
30
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
31
|
-
|
|
32
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
33
|
-
|
|
34
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
35
|
-
|
|
36
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
37
|
-
|
|
38
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
39
|
-
|
|
40
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
41
|
-
|
|
42
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
43
|
-
|
|
44
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
slug: mdx-blog-post
|
|
3
|
-
title: MDX Blog Post
|
|
4
|
-
authors: [slorber]
|
|
5
|
-
tags: [docusaurus]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Blog posts support [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features), such as [MDX](https://mdxjs.com/).
|
|
9
|
-
|
|
10
|
-
:::tip
|
|
11
|
-
|
|
12
|
-
Use the power of React to create interactive blog posts.
|
|
13
|
-
|
|
14
|
-
:::
|
|
15
|
-
|
|
16
|
-
{/* truncate */}
|
|
17
|
-
|
|
18
|
-
For example, use JSX to create an interactive button:
|
|
19
|
-
|
|
20
|
-
```js
|
|
21
|
-
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
<button onClick={() => alert('button clicked!')}>Click me!</button>
|
|
Binary file
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
slug: welcome
|
|
3
|
-
title: Welcome
|
|
4
|
-
authors: [slorber, yangshun]
|
|
5
|
-
tags: [facebook, hello, docusaurus]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
[Docusaurus blogging features](https://docusaurus.io/docs/blog) are powered by the [blog plugin](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog).
|
|
9
|
-
|
|
10
|
-
Here are a few tips you might find useful.
|
|
11
|
-
|
|
12
|
-
{/* truncate */}
|
|
13
|
-
|
|
14
|
-
Simply add Markdown files (or folders) to the `blog` directory.
|
|
15
|
-
|
|
16
|
-
Regular blog authors can be added to `authors.yml`.
|
|
17
|
-
|
|
18
|
-
The blog post date can be extracted from filenames, such as:
|
|
19
|
-
|
|
20
|
-
- `2019-05-30-welcome.md`
|
|
21
|
-
- `2019-05-30-welcome/index.md`
|
|
22
|
-
|
|
23
|
-
A blog post folder can be convenient to co-locate blog post images:
|
|
24
|
-
|
|
25
|
-

|
|
26
|
-
|
|
27
|
-
The blog supports tags as well!
|
|
28
|
-
|
|
29
|
-
**And if you don't want a blog**: just delete this directory, and use `blog: false` in your Docusaurus config.
|
package/docs/blog/authors.yml
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
yangshun:
|
|
2
|
-
name: Yangshun Tay
|
|
3
|
-
title: Ex-Meta Staff Engineer, Co-founder GreatFrontEnd
|
|
4
|
-
url: https://linkedin.com/in/yangshun
|
|
5
|
-
image_url: https://github.com/yangshun.png
|
|
6
|
-
page: true
|
|
7
|
-
socials:
|
|
8
|
-
x: yangshunz
|
|
9
|
-
linkedin: yangshun
|
|
10
|
-
github: yangshun
|
|
11
|
-
newsletter: https://www.greatfrontend.com
|
|
12
|
-
|
|
13
|
-
slorber:
|
|
14
|
-
name: Sébastien Lorber
|
|
15
|
-
title: Docusaurus maintainer
|
|
16
|
-
url: https://sebastienlorber.com
|
|
17
|
-
image_url: https://github.com/slorber.png
|
|
18
|
-
page:
|
|
19
|
-
# customize the url of the author page at /blog/authors/<permalink>
|
|
20
|
-
permalink: '/all-sebastien-lorber-articles'
|
|
21
|
-
socials:
|
|
22
|
-
x: sebastienlorber
|
|
23
|
-
linkedin: sebastienlorber
|
|
24
|
-
github: slorber
|
|
25
|
-
newsletter: https://thisweekinreact.com
|
package/docs/blog/tags.yml
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
facebook:
|
|
2
|
-
label: Facebook
|
|
3
|
-
permalink: /facebook
|
|
4
|
-
description: Facebook tag description
|
|
5
|
-
|
|
6
|
-
hello:
|
|
7
|
-
label: Hello
|
|
8
|
-
permalink: /hello
|
|
9
|
-
description: Hello tag description
|
|
10
|
-
|
|
11
|
-
docusaurus:
|
|
12
|
-
label: Docusaurus
|
|
13
|
-
permalink: /docusaurus
|
|
14
|
-
description: Docusaurus tag description
|
|
15
|
-
|
|
16
|
-
hola:
|
|
17
|
-
label: Hola
|
|
18
|
-
permalink: /hola
|
|
19
|
-
description: Hola tag description
|
package/docs/docs/api/agent.md
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Agent API
|
|
3
|
-
description: High-level agent orchestration
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Agent API
|
|
7
|
-
|
|
8
|
-
The `Agent` class provides high-level orchestration of Q-Learning, Storage, and Environment.
|
|
9
|
-
|
|
10
|
-
## Import
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
import { Agent } from 'lsji';
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Constructor
|
|
17
|
-
|
|
18
|
-
```typescript
|
|
19
|
-
const agent = new Agent({
|
|
20
|
-
qlearning: QLearning, // Required: Q-Learning engine
|
|
21
|
-
storage: Storage, // Required: Storage backend
|
|
22
|
-
env: Env // Optional: Environment for train/play
|
|
23
|
-
});
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Methods
|
|
27
|
-
|
|
28
|
-
### `start()`
|
|
29
|
-
Enable the system for training and play.
|
|
30
|
-
|
|
31
|
-
```typescript
|
|
32
|
-
await agent.start();
|
|
33
|
-
// Returns: { status: 'success', message: 'System STARTED' }
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### `stop()`
|
|
37
|
-
Disable the system (pauses training and play).
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
await agent.stop();
|
|
41
|
-
// Returns: { status: 'success', message: 'System STOPPED' }
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### `status()`
|
|
45
|
-
Get current system status and statistics.
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
const status = await agent.status();
|
|
49
|
-
// Returns:
|
|
50
|
-
{
|
|
51
|
-
status: 'running' | 'stopped',
|
|
52
|
-
todayTotal: number, // Battles today
|
|
53
|
-
limit: 90000, // Daily limit
|
|
54
|
-
performance: [ // Per-mode statistics
|
|
55
|
-
{ mode: 'train', total: 100, win_rate: 65.5 },
|
|
56
|
-
{ mode: 'test', total: 50, win_rate: 72.0 }
|
|
57
|
-
],
|
|
58
|
-
aiBrain: [ // Full Q-table
|
|
59
|
-
{ state: '0', action: 0, q_value: 0.45 },
|
|
60
|
-
{ state: '0', action: 1, q_value: 0.12 },
|
|
61
|
-
...
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### `train(options)`
|
|
67
|
-
Train the agent.
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
const result = await agent.train({
|
|
71
|
-
episodes: 200, // Number of episodes (default: 200)
|
|
72
|
-
actionSelector: (episode, lastAction) => number, // Custom pattern (optional)
|
|
73
|
-
batchSize: 200 // DB batch size (default: 200)
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// Returns:
|
|
77
|
-
{
|
|
78
|
-
episodes: 200,
|
|
79
|
-
wins: 85,
|
|
80
|
-
losses: 62,
|
|
81
|
-
draws: 53
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**Built-in Training Patterns:**
|
|
86
|
-
```typescript
|
|
87
|
-
import { TrainingPattern, getTrainingAction } from 'lsji';
|
|
88
|
-
|
|
89
|
-
// Pattern 0: Random (default)
|
|
90
|
-
await agent.train({ episodes: 500 });
|
|
91
|
-
|
|
92
|
-
// Pattern 1: Always Rock
|
|
93
|
-
await agent.train({
|
|
94
|
-
episodes: 500,
|
|
95
|
-
actionSelector: (ep, last) => getTrainingAction(TrainingPattern.ALWAYS_ROCK, ep, last)
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// Pattern 2: Counter
|
|
99
|
-
await agent.train({
|
|
100
|
-
episodes: 500,
|
|
101
|
-
actionSelector: (ep, last) => getTrainingAction(TrainingPattern.COUNTER, ep, last)
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Pattern 3: Sequential
|
|
105
|
-
await agent.train({
|
|
106
|
-
episodes: 500,
|
|
107
|
-
actionSelector: (ep, last) => getTrainingAction(TrainingPattern.SEQUENTIAL, ep, last)
|
|
108
|
-
});
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### `play(options)`
|
|
112
|
-
Play a single step against the agent.
|
|
113
|
-
|
|
114
|
-
```typescript
|
|
115
|
-
const result = await agent.play({
|
|
116
|
-
userAction: 0 // Optional: user action for envs that need it
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// Returns:
|
|
120
|
-
{
|
|
121
|
-
action: 1, // Agent's chosen action
|
|
122
|
-
reward: 1, // Reward received
|
|
123
|
-
done: false, // Episode ended
|
|
124
|
-
info: { opponentAction: 0 } // Environment-specific info
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### `setEnvironment(env)`
|
|
129
|
-
Inject or change the environment at runtime.
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
agent.setEnvironment(new MyCustomEnv());
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Example
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
import { Agent, QLearning, createStorage, RockPaperScissorsEnv } from 'lsji';
|
|
139
|
-
|
|
140
|
-
const storage = await createStorage('sqlite', { path: './agent.db' });
|
|
141
|
-
const qlearning = new QLearning({ alpha: 0.1, gamma: 0.9, epsilon: 0.1, storage });
|
|
142
|
-
const env = new RockPaperScissorsEnv({ opponent: 'random' });
|
|
143
|
-
|
|
144
|
-
const agent = new Agent({ qlearning, storage, env });
|
|
145
|
-
|
|
146
|
-
await agent.train({ episodes: 1000 });
|
|
147
|
-
const result = await agent.play(0); // Play Rock
|
|
148
|
-
console.log(`AI played: ${result.action}, Result: ${result.reward > 0 ? 'WIN' : result.reward < 0 ? 'LOSE' : 'DRAW'}`);
|
|
149
|
-
|
|
150
|
-
await storage.close();
|
|
151
|
-
```
|
package/docs/docs/api/env.md
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Env Interface
|
|
3
|
-
description: Base environment interface for RL problems
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Env Interface
|
|
7
|
-
|
|
8
|
-
All reinforcement learning environments must extend the abstract `Env` class.
|
|
9
|
-
|
|
10
|
-
## Import
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
import { Env } from 'lsji';
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Abstract Methods
|
|
17
|
-
|
|
18
|
-
### `getState()`
|
|
19
|
-
Return current state as a string key.
|
|
20
|
-
|
|
21
|
-
```typescript
|
|
22
|
-
getState(): string;
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### `step(action)`
|
|
26
|
-
Execute an action and return the result.
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
async step(action: number): Promise<StepResult>;
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**StepResult:**
|
|
33
|
-
```typescript
|
|
34
|
-
interface StepResult {
|
|
35
|
-
state: string; // New state
|
|
36
|
-
reward: number; // Reward for this step
|
|
37
|
-
done: boolean; // Episode ended
|
|
38
|
-
info?: object; // Additional info
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### `actionSize()`
|
|
43
|
-
Return number of possible actions.
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
actionSize(): number;
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### `reset()`
|
|
50
|
-
Reset environment to initial state.
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
async reset(): Promise<string>; // Returns initial state
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Optional Methods
|
|
57
|
-
|
|
58
|
-
### `render()`
|
|
59
|
-
Human-readable representation for debugging.
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
render(): string;
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## StateEncoder Utility
|
|
66
|
-
|
|
67
|
-
Helper for encoding/decoding complex states:
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { StateEncoder } from 'lsji';
|
|
71
|
-
|
|
72
|
-
// Encode object to string
|
|
73
|
-
const key = StateEncoder.encode({ position: 5, inventory: ['sword'] });
|
|
74
|
-
// Returns: '{"position":5,"inventory":["sword"]}'
|
|
75
|
-
|
|
76
|
-
// Decode string to object
|
|
77
|
-
const state = StateEncoder.decode(key);
|
|
78
|
-
// Returns: { position: 5, inventory: ['sword'] }
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Creating a Custom Environment
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { Env } from 'lsji';
|
|
85
|
-
|
|
86
|
-
class GridWorldEnv extends Env {
|
|
87
|
-
constructor() {
|
|
88
|
-
super();
|
|
89
|
-
this.position = 0;
|
|
90
|
-
this.gridSize = 10;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
getState() {
|
|
94
|
-
return String(this.position);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
async step(action) {
|
|
98
|
-
// Actions: 0=left, 1=right
|
|
99
|
-
if (action === 0) this.position = Math.max(0, this.position - 1);
|
|
100
|
-
if (action === 1) this.position = Math.min(this.gridSize - 1, this.position + 1);
|
|
101
|
-
|
|
102
|
-
const done = this.position === this.gridSize - 1;
|
|
103
|
-
const reward = done ? 1 : -0.01;
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
state: String(this.position),
|
|
107
|
-
reward,
|
|
108
|
-
done,
|
|
109
|
-
info: { position: this.position }
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
actionSize() {
|
|
114
|
-
return 2;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async reset() {
|
|
118
|
-
this.position = 0;
|
|
119
|
-
return '0';
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
render() {
|
|
123
|
-
return `GridWorld: position ${this.position}/${this.gridSize - 1}`;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## Best Practices
|
|
129
|
-
|
|
130
|
-
1. **State as string** — Use simple string keys for Q-table indexing
|
|
131
|
-
2. **Deterministic rewards** — Same state-action should give consistent rewards
|
|
132
|
-
3. **Action space** — Keep action space small for tabular Q-learning
|
|
133
|
-
4. **Reset** — Always implement proper reset for episode boundaries
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Built-in Environments
|
|
3
|
-
description: Pre-built environments for quick start
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Built-in Environments
|
|
7
|
-
|
|
8
|
-
LSJI includes a Rock-Paper-Scissors environment for demonstration and testing.
|
|
9
|
-
|
|
10
|
-
## Import
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
import {
|
|
14
|
-
RockPaperScissorsEnv,
|
|
15
|
-
TrainingPattern,
|
|
16
|
-
getTrainingAction
|
|
17
|
-
} from 'lsji';
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## RockPaperScissorsEnv
|
|
21
|
-
|
|
22
|
-
Classic Rock-Paper-Scissors game environment.
|
|
23
|
-
|
|
24
|
-
### Constructor
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
const env = new RockPaperScissorsEnv({
|
|
28
|
-
opponent: 'random' // 'random' | 'always_rock' | 'counter' | 'sequential'
|
|
29
|
-
});
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### Opponent Strategies
|
|
33
|
-
|
|
34
|
-
| Strategy | Description |
|
|
35
|
-
|----------|-------------|
|
|
36
|
-
| `'random'` | Uniform random actions (default) |
|
|
37
|
-
| `'always_rock'` | Always plays Rock (0) |
|
|
38
|
-
| `'counter'` | Plays counter to agent's previous action |
|
|
39
|
-
| `'sequential'` | Cycles through Rock→Scissors→Paper |
|
|
40
|
-
|
|
41
|
-
### Methods
|
|
42
|
-
|
|
43
|
-
All standard `Env` methods plus:
|
|
44
|
-
|
|
45
|
-
```typescript
|
|
46
|
-
// Static helpers
|
|
47
|
-
RockPaperScissorsEnv.getHandName(0); // 'Rock'
|
|
48
|
-
RockPaperScissorsEnv.getHandName(1); // 'Scissors'
|
|
49
|
-
RockPaperScissorsEnv.getHandName(2); // 'Paper'
|
|
50
|
-
|
|
51
|
-
const { judge, reward, outcome } = RockPaperScissorsEnv.calculateOutcome(0, 2);
|
|
52
|
-
// judge: 2, reward: 1, outcome: 'WIN'
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Training Patterns
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { TrainingPattern, getTrainingAction } from 'lsji';
|
|
59
|
-
|
|
60
|
-
// Pattern IDs
|
|
61
|
-
TrainingPattern.RANDOM; // 0
|
|
62
|
-
TrainingPattern.ALWAYS_ROCK; // 1
|
|
63
|
-
TrainingPattern.COUNTER; // 2
|
|
64
|
-
TrainingPattern.SEQUENTIAL; // 3
|
|
65
|
-
|
|
66
|
-
// Get action for pattern
|
|
67
|
-
const action = getTrainingAction(TrainingPattern.COUNTER, episode, lastAction);
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Example
|
|
71
|
-
|
|
72
|
-
```typescript
|
|
73
|
-
import {
|
|
74
|
-
Agent, QLearning, createStorage,
|
|
75
|
-
RockPaperScissorsEnv, TrainingPattern, getTrainingAction
|
|
76
|
-
} from 'lsji';
|
|
77
|
-
|
|
78
|
-
const storage = await createStorage('sqlite', { path: './rps.db' });
|
|
79
|
-
const qlearning = new QLearning({ alpha: 0.1, gamma: 0.9, epsilon: 0.1, storage });
|
|
80
|
-
|
|
81
|
-
// Train against counter opponent
|
|
82
|
-
const env = new RockPaperScissorsEnv({ opponent: 'counter' });
|
|
83
|
-
const agent = new Agent({ qlearning, storage, env });
|
|
84
|
-
|
|
85
|
-
await agent.train({
|
|
86
|
-
episodes: 1000,
|
|
87
|
-
actionSelector: (ep, last) => getTrainingAction(TrainingPattern.RANDOM, ep, last)
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
// Play against random opponent
|
|
91
|
-
const playEnv = new RockPaperScissorsEnv({ opponent: 'random' });
|
|
92
|
-
agent.setEnvironment(playEnv);
|
|
93
|
-
|
|
94
|
-
const result = await agent.play(0); // You play Rock
|
|
95
|
-
console.log(`AI: ${RockPaperScissorsEnv.getHandName(result.action)} | ${result.reward > 0 ? 'WIN' : 'LOSE'}`);
|
|
96
|
-
|
|
97
|
-
await storage.close();
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Creating Custom Environments
|
|
101
|
-
|
|
102
|
-
See [Custom Environment Example](/docs/examples/custom-environment) for a complete guide.
|