Skip to content

Commit

Permalink
Fix tons of bugs
Browse files Browse the repository at this point in the history
Fix tons of bugs, but there’s still sth. wrong in logic
  • Loading branch information
suquark committed Jan 27, 2017
1 parent 57140b2 commit 4148d88
Show file tree
Hide file tree
Showing 23 changed files with 446 additions and 319 deletions.
50 changes: 27 additions & 23 deletions RL/deepqlearn.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
AvgWindow
} from 'util.js';

import { Vol } from 'vol.js';

import { migrate } from 'conf.js';

import { Net } from 'topology/vallia.js';
Expand Down Expand Up @@ -78,7 +80,7 @@ class DQN {
this.tdtrainer = tdtrainer;
// create [state -> value of all possible actions] modeling net for the value function
this.value_net = this.tdtrainer.net;
net_checker(this.value_net);
this.net_checker(this.value_net);

// // and finally we need a Temporal Difference Learning trainer!
// let tdtrainer_options = {
Expand Down Expand Up @@ -121,7 +123,7 @@ class DQN {
// and return the argmax action and its value
let action_values = this.value_net.forward(new Vol(s));
let maxk = action_values.max_index();
return { action: maxk, value: action_values[maxk] };
return { action: maxk, value: action_values.w[maxk] };
}

getNetInput(xt) {
Expand Down Expand Up @@ -230,6 +232,28 @@ class DQN {
this.average_loss_window.add(avcost);
}
}

net_checker(net) {
// this is an advanced usage feature, because size of the input to the network, and number of
// actions must check out. This is not very pretty Object Oriented programming but I can't see
// a way out of it :(
let layer_defs = net.layers;
if (layer_defs.length < 2) {
console.warn('TROUBLE! must have at least 2 layers');
}
if (layer_defs[0].layer_type !== 'input') {
console.warn('TROUBLE! first layer must be input layer!');
}
if (layer_defs[layer_defs.length - 1].layer_type !== 'regression') {
console.warn('TROUBLE! last layer must be input regression!');
}
if (layer_defs[0].out_depth * layer_defs[0].out_sx * layer_defs[0].out_sy !== this.net_inputs) {
console.warn('TROUBLE! Number of inputs must be num_states * temporal_window + num_actions * temporal_window + num_states!');
}
if (layer_defs[layer_defs.length - 1].out_size !== this.num_actions) {
console.warn('TROUBLE! Number of regression neurons should be num_actions!');
}
}
}

function visState(brain, node) {
Expand All @@ -251,27 +275,7 @@ function visState(brain, node) {
elt.appendChild(brainvis);
}

function net_checker(net) {
// this is an advanced usage feature, because size of the input to the network, and number of
// actions must check out. This is not very pretty Object Oriented programming but I can't see
// a way out of it :(
layer_defs = net.layers;
if (layer_defs.length < 2) {
console.warn('TROUBLE! must have at least 2 layers');
}
if (layer_defs[0].layer_type !== 'input') {
console.warn('TROUBLE! first layer must be input layer!');
}
if (layer_defs[layer_defs.length - 1].layer_type !== 'regression') {
console.warn('TROUBLE! last layer must be input regression!');
}
if (layer_defs[0].out_depth * layer_defs[0].out_sx * layer_defs[0].out_sy !== this.net_inputs) {
console.warn('TROUBLE! Number of inputs must be num_states * temporal_window + num_actions * temporal_window + num_states!');
}
// if (layer_defs[layer_defs.length - 1].num_neurons !== this.num_actions) {
// console.warn('TROUBLE! Number of regression neurons should be num_actions!');
// }
}


function dist_checker(a) {
var s = 0.0;
Expand Down
14 changes: 11 additions & 3 deletions RL/helper/agent.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { clip } from 'util.js';
import { Face } from './geometry.js';
import { Digestion } from './sensors/digestion.js';
import { MultiEyes } from './sensors/naive_eye.js';
Expand All @@ -17,8 +18,7 @@ class Agent {
// 9 eyes
this.eyes.setup_array(-0.75, 0.25, 9);
this.digest = new Digestion(
{ 'type': {1: 5.0, 2: -6.0} },
{ 'alive': false }
{ 'type': {1: 5.0, 2: -6.0} }
);
// braaain
//this.brain = new deepqlearn.Brain(this.eyes.length * 3, this.actions.length);
Expand All @@ -28,6 +28,8 @@ class Agent {
this.brain = brain; // maybe nothing
this.reward_bonus = 0.0;
this.prevactionix = -1;

this.old_face = this.face.clone();
}

get position() { return this.face.origin; }
Expand Down Expand Up @@ -90,14 +92,20 @@ class Agent {
ctx.strokeStyle = "rgb(0,0,0)";

// draw agents body
//this.old_face.draw(ctx);
this.face.draw(ctx);
}

draw(ctx) {
// We have to draw old state, terrible...
this.draw_body(ctx);
// draw agents sight
this.eyes.draw();
this.eyes.face = this.old_face;
this.eyes.draw(ctx);
this.eyes.face = this.face; // restore
//this.eyes.draw(ctx);
}

}

export { Agent };
7 changes: 4 additions & 3 deletions RL/helper/effector/motor.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { normalize_angle } from 'util.js';
import { Face } from '../geometry.js';
import { Face, Vec } from '../geometry.js';

class TwoWheelMotor {

Expand Down Expand Up @@ -31,10 +31,11 @@ class TwoWheelMotor {

var np = w2p.add(vv);
var np2 = w1p.add(vv2);
let npos = np.add(np2).scale(0.5);
let npos = np.add(np2);
npos.scale(0.5);

let nangle = normalize_angle(angle - rot1 + rot2);
return new Face(npos.x, npos.y, rad, nangle);
return new Face(npos.x, npos.y, face.rad, nangle);
}
}

Expand Down
83 changes: 29 additions & 54 deletions RL/helper/geometry.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
// line intersection helper function: does line segment (p1,p2) intersect segment (p3,p4) ?
function line_intersect(p1, p2, p3, p4) {
var denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);
if (denom === 0.0) {
return false;
} // parallel lines
if (denom === 0.0) return false; // parallel lines
var ua = ((p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x)) / denom;
var ub = ((p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x)) / denom;
if (ua > 0.0 && ua < 1.0 && ub > 0.0 && ub < 1.0) {
var up = new Vec(p1.x + ua * (p2.x - p1.x), p1.y + ua * (p2.y - p1.y));
return {
ua: ua,
ub: ub,
up: up
}; // up is intersection point
return { ua: ua, ub: ub, up: up }; // up is intersection point
}
return false;
}
Expand All @@ -21,10 +15,7 @@ var line_point_intersect = function (p1, p2, p0, rad) {
var v = new Vec(p2.y - p1.y, -(p2.x - p1.x)); // perpendicular vector
var d = Math.abs((p2.x - p1.x) * (p1.y - p0.y) - (p1.x - p0.x) * (p2.y - p1.y));
d = d / v.length();
if (d > rad) {
return false;
}

if (d > rad) return false;
v.normalize();
v.scale(d);
var up = p0.add(v);
Expand All @@ -34,10 +25,7 @@ var line_point_intersect = function (p1, p2, p0, rad) {
var ua = (up.y - p1.y) / (p2.y - p1.y);
}
if (ua > 0.0 && ua < 1.0) {
return {
ua: ua,
up: up
};
return { ua: ua, up: up };
}
return false;
}
Expand All @@ -56,24 +44,30 @@ class Face {
this.angle = angle;
}

get origin() {
return this.circle.c;
get x() {
return this.circle.c.x;
}

get rad() {
return this.circle.rad;
get y() {
return this.circle.c.y;
}

get origin() { return this.circle.c; }

get rad() { return this.circle.rad; }

update(face) {
// inner update
this.circle = face.circle;
this.angle = face.angle;
}

draw(ctx) {
this.circle.draw(ctx);
clone() {
return new Face(this.x, this.y, this.rad, this.angle);
}

draw(ctx) { this.circle.draw(ctx); }

apply_clip_rect(left, top, right, bottom) {
// do clip, not return a value
this.origin.apply_clip_rect(left, top, right, bottom);
Expand All @@ -88,18 +82,14 @@ class Circle {
this.rad = r; // radius
}

intersect_circle(cir) {
return (this.c.dist_from(cir.c) < this.rad + cir.rad);
}
intersect_circle(cir) { return (this.c.dist_from(cir.c) < this.rad + cir.rad); }

intersect_line(l) {
return line_point_intersect(l.s, l.d, this.c, this.rad);
}
intersect_line(l) { return line_point_intersect(l.s, l.d, this.c, this.rad); }

draw(ctx) {
// need style provided
ctx.beginPath();
ctx.arc(this.c.x, this.c.x, this.rad, 0, Math.PI * 2, true);
ctx.arc(this.c.x, this.c.y, this.rad, 0, Math.PI * 2, true);
ctx.fill();
ctx.stroke();
}
Expand All @@ -112,18 +102,14 @@ class Line {
this.d = new Vec(dx, dy); // end
}

intersect_line(l) {
return line_intersect(this.s, this.d, l.s, l.d);
}
intersect_line(l) { return line_intersect(this.s, this.d, l.s, l.d); }

intersect_circle(circ) {
return line_point_intersect(this.s, this.d, circ.c, circ.rad);
}
intersect_circle(circ) { return line_point_intersect(this.s, this.d, circ.c, circ.rad); }

draw(ctx) {
ctx.beginPath();
ctx.moveTo(s.x, s.y);
ctx.lineTo(d.x, d.y);
ctx.moveTo(this.s.x, this.s.y);
ctx.lineTo(this.d.x, this.d.y);
ctx.stroke();
}
}
Expand All @@ -137,32 +123,21 @@ class Vec {
}

// utilities
dist_from(v) {
return Math.sqrt(Math.pow(this.x - v.x, 2) + Math.pow(this.y - v.y, 2));
}
dist_from(v) { return Math.sqrt(Math.pow(this.x - v.x, 2) + Math.pow(this.y - v.y, 2)); }

length() {
return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}
length() { return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2)); }

// new vector returning operations
add(v) {
return new Vec(this.x + v.x, this.y + v.y);
}
add(v) { return new Vec(this.x + v.x, this.y + v.y); }

sub(v) {
return new Vec(this.x - v.x, this.y - v.y);
}
sub(v) { return new Vec(this.x - v.x, this.y - v.y); }

rotate(a) { // CLOCKWISE
return new Vec(this.x * Math.cos(a) + this.y * Math.sin(a), -this.x * Math.sin(a) + this.y * Math.cos(a));
}

// in place operations
scale(s) {
this.x *= s;
this.y *= s;
}
scale(s) { this.x *= s; this.y *= s; }

normalize() {
var d = this.length();
Expand All @@ -184,4 +159,4 @@ class Vec {

}

export { Vec, Circle, Line };
export { Vec, Circle, Line, Face, near_intersect };
Loading

0 comments on commit 4148d88

Please sign in to comment.