First simple realisation
This commit is contained in:
parent
7ddfae5e90
commit
4c4134b908
@ -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) {
|
||||||
|
@ -19,4 +19,8 @@ export default class Journal {
|
|||||||
humanMoves.slice(-humanCount)
|
humanMoves.slice(-humanCount)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get length() {
|
||||||
|
return this.moves.length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
|
@ -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>
|
Loading…
Reference in New Issue
Block a user