First simple realisation

This commit is contained in:
Anton Vakhrushev 2018-06-05 18:20:47 +03:00
parent 7ddfae5e90
commit 4c4134b908
7 changed files with 108 additions and 27 deletions

View File

@ -16,29 +16,29 @@ export default class Daemon {
this.epsilon = epsilon; this.epsilon = epsilon;
} }
get power() {
return this.humanCount + this.robotCount;
}
predict(journal) { predict(journal) {
const steps = this._getStepSlice(journal); const steps = this._getStepSlice(journal);
const w0 = this._getWeight([...steps, 0]); const w0 = this._getWeight([...steps, 0]);
const w1 = this._getWeight([...steps, 1]); const w1 = this._getWeight([...steps, 1]);
if (w1 > w0) { return w1 > w0 ? 1 : 0;
return 1;
} else {
return 0;
}
} }
adjust(movements, humanValue, stepNumber) { adjust(journal, humanValue) {
const steps = this._getStepSlice(movements); const steps = this._getStepSlice(journal);
const weightAdjustment = this._getWeightAdjustment(stepNumber); const adjustmentWeight = this._getAdjustmentWeight(journal.length);
this._adjustWeight([...steps, humanValue], weightAdjustment); this._adjustWeight([...steps, humanValue], adjustmentWeight);
} }
_getStepSlice(movements) { _getStepSlice(journal) {
return movements.getLastMovements(this.humanCount, this.robotCount); return journal.getLastMovements(this.humanCount, this.robotCount);
} }
_getWeightAdjustment(stepNumber) { _getAdjustmentWeight(stepNumber) {
return Math.pow(1 + this.epsilon, stepNumber); return Math.pow(1 + this.epsilon, stepNumber);
} }
@ -51,6 +51,7 @@ export default class Daemon {
_setWeight(steps, value) { _setWeight(steps, value) {
const key = create_key(steps); const key = create_key(steps);
this.weights[key] = value; this.weights[key] = value;
console.log('WEIGHTS', this.weights);
} }
_adjustWeight(steps, weight) { _adjustWeight(steps, weight) {

View File

@ -19,4 +19,8 @@ export default class Journal {
humanMoves.slice(-humanCount) humanMoves.slice(-humanCount)
); );
} }
get length() {
return this.moves.length;
}
} }

View File

@ -1,13 +1,23 @@
import History from './Journal'; import Journal from './Journal';
import Supervisor from './Supervisor'; import Supervisor from './Supervisor';
import Daemon from './Daemon';
export default class Predictor { export default class Predictor {
movements; score;
journal;
supervisor; supervisor;
score = 0;
constructor() { constructor() {
this.movements = new History(); this.score = 0;
this.supervisor = new Supervisor(); this.journal = new Journal();
this.supervisor = new Supervisor([new Daemon(3, 3)]);
}
pass(value) {
const prediction = this.supervisor.predict(this.journal);
this.score += prediction === value ? -1 : 1;
this.supervisor.adjust(this.journal, value);
this.journal.makeMove(value, prediction);
return prediction;
} }
} }

View File

@ -1,9 +1,61 @@
const DEFAULT_EPSILON = 0.01;
export default class Supervisor { export default class Supervisor {
daemons = []; daemons = [];
epsilon;
constructor(daemons) { constructor(daemons, epsilon = DEFAULT_EPSILON) {
this.daemons = daemons; if (!daemons) {
throw Error('Empty daemon list');
}
this.daemons = daemons.map(daemon => ({
daemon: daemon,
rate: 0,
}));
this.epsilon = epsilon;
} }
predict(movements) {} predict(journal) {
const predictions = this._createPredictions(journal);
const ordered = this._sortPredictions(predictions);
console.log(ordered);
return ordered[0].value;
}
adjust(journal, humanValue) {
const predictions = this._createPredictions(journal);
for (const prediction of predictions) {
if (prediction.value === humanValue) {
prediction.daemon.rate += this._getAdjustmentWeight(
journal.length
);
}
prediction.daemon.daemon.adjust(journal, humanValue);
}
}
_createPredictions(journal) {
return this.daemons.map(daemon => ({
daemon: daemon,
power: daemon.daemon.power,
rate: daemon.rate,
value: daemon.daemon.predict(journal),
}));
}
_sortPredictions(predictions) {
return predictions.sort((result1, result2) => {
const rateDiff = result2.rate - result1.rate;
if (Math.abs(rateDiff) > 0.000001) {
return rateDiff;
}
return result1.power - result2.power;
});
}
_getAdjustmentWeight(stepNumber) {
return Math.pow(1 + this.epsilon, stepNumber);
}
} }

View File

@ -1,6 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import Predictor from './Predictor';
import './style.css'; import './style.css';
import Predictor from './Predictor';
new Vue({ new Vue({
el: '#app', el: '#app',
@ -8,8 +8,17 @@ new Vue({
predictor: new Predictor(), predictor: new Predictor(),
}, },
methods: { methods: {
click(v) {
const value = v ? 1 : 0;
this.pass(value);
},
press(evt) {
const value = evt.key === '1' ? 0 : 1;
this.pass(value);
},
pass(value) { pass(value) {
console.log('PASS', value); const prediction = this.predictor.pass(value);
console.log('PREDICTED', prediction, 'PASS', value);
}, },
}, },
}); });

View File

@ -8,6 +8,11 @@ test('Get prediction for beginning', function() {
expect(d.predict(m)).toEqual(0); expect(d.predict(m)).toEqual(0);
}); });
test('Can get power', function() {
const d = new Daemon(5, 8);
expect(d.power).toEqual(13);
});
test('Daemon 1-1', function() { test('Daemon 1-1', function() {
const m = new History(); const m = new History();
const d = new Daemon(1, 1); const d = new Daemon(1, 1);

View File

@ -1,18 +1,18 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Hello</title> <title>Predictor</title>
</head> </head>
<body> <body>
<main id="app" class="app"> <main id="app" class="app" tabindex="0" v-on:keyup="press">
<span class="score"> <span class="score">
{{ predictor.score }} {{ predictor.score }}
</span> </span>
<div class="buttons"> <div class="buttons">
<button value="0" v-on:click="pass(0)">0</button> <button value="0" v-on:click="click(0)">0</button>
<button value="1" v-on:click="pass(1)">1</button> <button value="1" v-on:click="click(1)">1</button>
</div> </div>
</main> </main>
<script src="/dist/app.js"></script> <script src="dist/app.js"></script>
</body> </body>
</html> </html>