Compare commits

..

5 Commits

  1. 47
      css/src/style.scss
  2. 77
      css/style.css
  3. 2
      css/style.min.css
  4. BIN
      img/robot.png
  5. BIN
      img/station.png
  6. 83
      index.html
  7. 2
      js/controls.js
  8. 37
      js/rl.js
  9. 915
      js/view.js

@ -1,8 +1,11 @@
// compileCompressed
*{
margin: 0;
padding: 0;
}
body{
margin: 0;
padding: 0;
// background-color: ;
font-family: sans-serif;
}
@ -13,17 +16,30 @@ body{
#canvas{
height: 100%;
}
nav{
position: absolute;
top: 10px;
left: 10px;
}
button{
margin: 0.3em;
}
.absolute{
position: absolute;
top:0;
left:0;
}
.stage{
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.plot{
position: absolute;
top: 2vh;
@ -33,9 +49,38 @@ nav{
}
.sliders{
position: absolute;
top: 20vh;
left: 2vw;
width: 20vw;
}
#formula{
position: absolute;
top: 71.5vh;
width: 90vw;
}
.score{
position: absolute;
top: 7vh;
left: 2vw;
width: 20vw;
height: 10vw;
}
.lightbox{
padding: 2em;
position: absolute;
top:0;
left: 50%;
transform: translateX(-50%) translateY(-100%);
z-index: 10;
max-width: 50%;
background-color: #BBB;
transition: all 1s;
&.active{
top:20%;
transform: translateX(-50%) translateY(-50%);
}
}

@ -0,0 +1,77 @@
* {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
#container {
height: 100vh;
position: relative;
}
#canvas {
height: 100%;
}
nav {
position: absolute;
top: 10px;
left: 10px;
}
.absolute {
position: absolute;
top: 0;
left: 0;
}
.plot {
position: absolute;
top: 2vh;
right: 2vw;
width: 20vw;
height: 10vw;
}
.sliders {
position: absolute;
top: 20vh;
left: 2vw;
width: 20vw;
}
#formula {
position: absolute;
top: 71.5vh;
width: 90vw;
}
.score {
position: absolute;
top: 7vh;
left: 2vw;
width: 20vw;
}
.lightbox {
padding: 2em;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%) translateY(-100%);
z-index: 10;
width: 50%;
height: 40%;
background-color: #BBB;
transition: all 1s;
}
.lightbox.active {
top: 50%;
transform: translateX(-50%) translateY(-50%);
}

2
css/style.min.css vendored

@ -1 +1 @@
*{margin:0;padding:0}body{font-family:sans-serif}#container{height:100vh;position:relative}#canvas{height:100%}nav{position:absolute;top:10px;left:10px}.absolute{position:absolute;top:0;left:0}.plot{position:absolute;top:2vh;right:2vw;width:20vw;height:10vw}.sliders{position:absolute;top:7vh;left:2vw;width:20vw;height:10vw}
*{margin:0;padding:0}body{margin:0;padding:0;font-family:sans-serif}#container{height:100vh;position:relative}#canvas{height:100%}nav{position:absolute;top:10px;left:10px}button{margin:0.3em}.absolute{position:absolute;top:0;left:0}.stage{display:flex;justify-content:center;align-items:center;height:100vh}.plot{position:absolute;top:2vh;right:2vw;width:20vw;height:10vw}.sliders{position:absolute;top:20vh;left:2vw;width:20vw}#formula{position:absolute;top:71.5vh;width:90vw}.score{position:absolute;top:7vh;left:2vw;width:20vw}.lightbox{padding:2em;position:absolute;top:0;left:50%;transform:translateX(-50%) translateY(-100%);z-index:10;max-width:50%;background-color:#BBB;transition:all 1s}.lightbox.active{top:20%;transform:translateX(-50%) translateY(-50%)}

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/konva@4.0.0/konva.min.js"></script>
<script src='https://unpkg.com/vue/dist/vue.js'></script>
<script src='https://unpkg.com/vue/dist/vue.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/vue-konva@2.0.11/umd/vue-konva.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
@ -15,61 +15,50 @@
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script src="https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js" integrity="sha384-y23I5Q6l+B6vatafAwxRu/0oK/79VlbSz7Q9aiSZUvyWYIYsd+qj+o24G5ZU2zJz" crossorigin="anonymous"></script>
<title>RL exhibit - prototype</title>
<link rel="stylesheet" href="https://gitcdn.xyz/cdn/jzilg/embellish.css/fff9961c5fec2d1c8ff53c87b12e18d5c8db7761/embellish.min.css">
<link rel="stylesheet" href="css/style.min.css">
</head>
<body>
<div id="app">
<v-stage ref="stage" :config="stage_config">
<!-- <v-layer ref="local_layer" :config="local_layer">
<v-group ref="map_group" :config="map_config">
<v-rect v-for="(t_type, idx) in maze.map.flat()" :config="get_tile_config(idx, t_type, true)" :key="idx"></v-rect>
<v-regular-polygon :config="agent_config"></v-regular-polygon>
</v-group>
</v-layer> -->
<v-layer ref="map_layer">
<v-group ref="mini_map_group" :config="mini_map_config">
<!-- <v-group ref="grid_group">
<v-line v-for="y in maze.height+1" :config="get_grid_line_config(y-1, true)"></v-line>
<v-line v-for="x in maze.width+1" :config="get_grid_line_config(x-1)"></v-line>
</v-group> -->
<v-rect v-for="(t_type, idx) in maze.map.flat()" :config="get_tile_config(idx, t_type)" :key="idx" ></v-rect>
<v-group v-for="(action,idx) in q_table" :config="get_field_config(idx)">
<v-shape v-for="(value, key) in action" :config="get_triangle_config(value, key)"></v-shape>
<v-text v-for="i in 4" :config="get_q_text_config(action,i)"></v-text>
</v-group>
<v-regular-polygon :config="agent_config"></v-regular-polygon>
</v-group>
</v-layer>
</v-stage>
<line-chart css-classes="plot" :chart-data="datacollection" :options="plot_options"></line-chart>
<div class="sliders">
<h1>Learning Rate {{learning_rate}}</h1>
<vue-slider v-model="learning_rate" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<h1>Discount Factor {{discount_factor}}</h1>
<vue-slider v-model="discount_factor" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<h1>Epsilon {{epsilon}}</h1>
<vue-slider v-model="epsilon" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<h1>Current Score</h1>
<h2>{{score}}</h2>
<div id="test" style="position: absolute;bottom: 10vh;width:90vw"></div>
<rl-local class="stage" :machine="machine" :maze="maze" :config="stage_config" v-show="isActive('local')"></rl-local>
<rl-map class="stage" :machine="machine" :maze="maze" :config="stage_config" v-show="isActive('global')"></rl-map>
<line-chart css-classes="plot" :chart-data="datacollection" :options="plot_options" v-show="isActive('plot')"></line-chart>
<div class="sliders" v-show="isActive('sliders')">
<h1>Learning Rate {{machine.learning_rate}}</h1>
<vue-slider v-model="machine.learning_rate" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<h1>Discount Factor {{machine.discount_factor}}</h1>
<vue-slider v-model="machine.discount_factor" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<h1>Epsilon {{machine.epsilon}}</h1>
<vue-slider v-model="machine.epsilon" :drag-on-click="true" v-bind="slider_config"></vue-slider>
<div id="formula"></div>
</div>
<div class="score" v-show="isActive('score')">
<h1>Current Energy</h1>
<h2>{{machine.score}}</h2>
</div>
<navi-gation :options="navigation" v-show="isActive('navi')"></navi-gation>
</div>
<nav>
<button class="button" onclick="machine.run(1)">run 1 episode!</button>
<button class="button" onclick="machine.run(100)">run 100 episodes!</button>
<button class="button" onclick="machine.auto_step();">auto step!</button>
<button class="button" onclick="machine.greedy_step();">greedy step!</button>
<button class="button" onclick="machine.reset_machine()">reset machine</button>
</nav>
<script>
var map = [
[0, 0, 1, 8, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 0, 0],
[1, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 1, 0, 0, 0, 0, 0],
[2, 0, 1, 0, 1, 0, 0, 1]
[0, 0, 1, 8, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 0, 0, 0, 0, 1, 0, 1, 0, 1],
[0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[0, 1, 1, 1, 1, 1, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
[1, 0, 1, 0, 0, 0, 0, 1, 1, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 1, 0, 1, 0, 0, 1]
];
</script>
<script src="js/rl.js"></script>

2
js/controls.js vendored

@ -27,7 +27,7 @@ function key_callback(e) {
break;
}
var ret = 1;
if (tmp != undefined){
if (tmp != undefined && document.querySelector(".lightbox.active") == null){
ret = machine.step(tmp);
}
// show_q_table();

@ -4,6 +4,7 @@ class RL_machine {
rewards,
start_state,
end_states,
start_score,
end_score,
learning_rate,
discount_factor,
@ -14,11 +15,16 @@ class RL_machine {
this.lr = learning_rate;
this.df = discount_factor;
this.start_state = start_state;
this.start_score = start_score;
this.end_score = end_score;
this.end_states = end_states;
this.epsilon = epsilon;
this.q_table = this.actions_per_state.map((c) => c.reduce((o,n) => {o[n]=0; return o},{}));
this.reset_machine();
this.callback = null;
}
setCallback(cb){
this.callback = cb;
}
reset_machine(){
for (var q in this.q_table){
@ -27,17 +33,24 @@ class RL_machine {
}
}
this.episode = 0;
this.state = this.start_state;
this.score = 0;
this.running = false;
this.score_history = [];
this.state = this.start_state;
this.score = this.start_score;
}
new_episode(){
new_episode(reason = "failed"){
const reset = () => {
this.episode++;
this.score_history.push(this.score);
this.state = this.start_state;
this.score = this.start_score;
}
// add_new_episode_callback
this.episode++;
this.state = this.start_state;
this.score_history.push(this.score);
this.score = 0;
if (!this.running && this.callback) {
this.callback(reason).then((p) => reset());
} else {
reset();
}
}
auto_step(){
if (Math.random() < this.epsilon){
@ -52,8 +65,12 @@ class RL_machine {
step(action){
this.state = this.update_q_table(this.state, action);
// add_new_step_callback
if (this.end_states.indexOf(this.state) >= 0 || this.score < this.end_score){
this.new_episode();
if (this.end_states.indexOf(this.state) >= 0) {
this.new_episode("success");
return 2
}
if (this.score <= this.end_score){
this.new_episode("failed");
return 2
}
return 1
@ -191,4 +208,4 @@ var maze = new Maze(map, reward);
var learning_rate = 0.75;
var discount_factor = 0.8;
var machine = new RL_machine(maze.actions, maze.transactions, maze.rewards, maze.start_state, maze.end_states, -999, learning_rate, discount_factor, 0.2);
var machine = new RL_machine(maze.actions, maze.transactions, maze.rewards, maze.start_state, maze.end_states, 50, 0, learning_rate, discount_factor, 0.2);

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save