@visactor/vmind
Version:
<div align="center"> <a href="https://github.com/VisActor#gh-light-mode-only" target="_blank"> <img alt="VisActor Logo" width="200" src="https://github.com/VisActor/.github/blob/main/profile/logo_500_200_light.svg"/> </a> <a href="https://githu
84 lines (79 loc) • 4.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.Adwin = void 0;
const bucket_1 = require("./bucket");
class Adwin {
constructor(delta = .002, maxBuckets = 5, minClock = 32, minWinLen = 10, minSubWinLen = 5) {
this.delta = delta, this.maxBuckets = maxBuckets, this.minClock = minClock, this.minWinLen = minWinLen,
this.minSubWinLen = minSubWinLen, this.time = 0, this.windowLen = 0, this.windowSum = 0,
this.windowVariance = 0, this.bucketRowCount = 0, this.bucketRowList = new bucket_1.AdwinRowBucketList(this.maxBuckets);
}
setInput(value) {
return this.time++, this.insertElement(value), this.reduceWindow();
}
insertElement(value) {
this.bucketRowList.head.insertBucket(value, 0);
let incrementVariance = 0;
if (this.windowLen > 0) {
const mean = this.windowSum / this.windowLen;
incrementVariance = this.windowLen * (value - mean) ** 2 / (this.windowLen + 1);
}
this.windowLen++, this.windowVariance += incrementVariance, this.windowSum += value,
this.compressBucketRow();
}
compressBucketRow() {
let bucketRow = this.bucketRowList.head, bucketRowLevel = 0;
for (;null !== bucketRow && bucketRow.bucketCount === this.maxBuckets + 1; ) {
{
let nextBucketRow = bucketRow.nextBucketRow;
null === nextBucketRow && (this.bucketRowList.addToTail(), nextBucketRow = bucketRow.nextBucketRow,
this.bucketRowCount++);
const n1 = 2 ** bucketRowLevel, n2 = 2 ** bucketRowLevel, mean1 = bucketRow.bucketSum[0] / n1, mean2 = bucketRow.bucketSum[1] / n2, nextTotal = bucketRow.bucketSum[0] + bucketRow.bucketSum[1], externalVariance = n1 * n2 * (mean1 - mean2) ** 2 / (n1 + n2), nextVariance = bucketRow.bucketVariance[0] + bucketRow.bucketVariance[1] + externalVariance;
if (nextBucketRow.insertBucket(nextTotal, nextVariance), bucketRow.compressBucket(2),
nextBucketRow.bucketCount <= this.maxBuckets) break;
}
bucketRow = bucketRow.nextBucketRow, bucketRowLevel++;
}
}
reduceWindow() {
let isChanged = !1;
if (this.time % this.minClock == 0 && this.windowLen >= this.minWinLen) {
let isReducedWidth = !0;
for (;isReducedWidth; ) {
isReducedWidth = !1;
let isExit = !1, n0 = 0, n1 = this.windowLen, sum0 = 0, sum1 = this.windowSum, bucketRow = this.bucketRowList.tail, i = this.bucketRowCount;
for (;!isExit && !bucketRow; ) {
for (let bucketNum = 0; bucketNum < bucketRow.bucketCount; bucketNum++) {
if (0 === i && bucketNum === bucketRow.bucketCount - 1) {
isExit = !0;
break;
}
n0 += 2 ** i, n1 -= 2 ** i, sum0 = bucketRow.bucketSum[bucketNum], sum1 -= bucketRow.bucketSum[bucketNum];
const diffValue = sum0 / n0 - (sum1 - n1);
if (n0 > this.minSubWinLen + 1 && n1 > this.minSubWinLen + 1 && this.reduceExpression(n0, n1, diffValue) && (isReducedWidth = !0,
isChanged = !0, this.windowLen > 0)) {
n0 -= this.deleteElement(), isExit = !0;
break;
}
}
bucketRow = bucketRow.previousBucketRow, i--;
}
}
}
return isChanged;
}
reduceExpression(n0, n1, diffValue) {
const m = 1 / (n0 - this.minSubWinLen + 1) + 1 / (n1 - this.minSubWinLen + 1), d = Math.log(2 * Math.log(this.windowLen) / this.delta), varianceWindow = this.windowVariance / this.windowLen, epsilonCut = Math.sqrt(2 * m * varianceWindow * d) + 2 / 3 * m * d;
return Math.abs(diffValue) > epsilonCut;
}
deleteElement() {
const bucketRow = this.bucketRowList.tail, deletedNumber = 2 ** this.bucketRowCount;
this.windowLen -= deletedNumber, this.windowSum -= bucketRow.bucketSum[0];
const deletedBucketMean = bucketRow.bucketSum[0] / deletedNumber, incVariance = bucketRow.bucketVariance[0] + deletedNumber * this.windowLen * Math.pow(deletedBucketMean - this.windowSum / this.windowLen, 2) / (deletedNumber + this.windowLen);
return this.windowVariance -= incVariance, bucketRow.compressBucket(1), 0 === bucketRow.bucketCount && (this.bucketRowList.removeFromTail(),
this.bucketRowCount -= 1), deletedNumber;
}
}
exports.Adwin = Adwin;
//# sourceMappingURL=adwin.js.map