Complete general functions

This commit is contained in:
znetsixe
2025-05-26 17:09:18 +02:00
parent 47dfe3850f
commit 2e57034f14
44 changed files with 6776 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
class DynamicClusterDeviation {
constructor() {
this.clusters = []; // Stores clusters as { center, spread, count }
}
update(value) {
console.log(`\nProcessing value: ${value}`);
// If no clusters exist, create the first one
if (this.clusters.length === 0) {
this.clusters.push({ center: value, spread: 0, count: 1 });
console.log(` → First cluster created at ${value}`);
return { value, isOutlier: false };
}
// Step 1: Find the closest cluster
let bestMatch = null;
let minDistance = Infinity;
for (const cluster of this.clusters) {
const distance = Math.abs(value - cluster.center);
console.log(` Checking against cluster at ${cluster.center} (spread: ${cluster.spread}, count: ${cluster.count}) → distance: ${distance}`);
if (distance < minDistance) {
bestMatch = cluster;
minDistance = distance;
}
}
console.log(` Closest cluster found at ${bestMatch.center} with distance: ${minDistance}`);
// Step 2: Compute dynamic threshold
const dynamicThreshold = 1 + 5 / Math.sqrt(bestMatch.count + 1);
const allowedDeviation = dynamicThreshold * (bestMatch.spread || 1);
console.log(` Dynamic threshold: ${dynamicThreshold.toFixed(2)}, Allowed deviation: ${allowedDeviation.toFixed(2)}`);
// Step 3: Check if value fits within the dynamically adjusted cluster spread
if (minDistance <= allowedDeviation) {
// Update cluster dynamically
const newCenter = (bestMatch.center * bestMatch.count + value) / (bestMatch.count + 1);
const newSpread = Math.max(bestMatch.spread, minDistance);
bestMatch.center = newCenter;
bestMatch.spread = newSpread;
bestMatch.count += 1;
console.log(` ✅ Value fits in cluster! Updating cluster:`);
console.log(` → New center: ${newCenter.toFixed(2)}`);
console.log(` → New spread: ${newSpread.toFixed(2)}`);
console.log(` → New count: ${bestMatch.count}`);
return { value, isOutlier: false };
} else {
// If too far, create a new cluster
this.clusters.push({ center: value, spread: 0, count: 1 });
console.log(` ❌ Outlier detected! New cluster created at ${value}`);
return { value, isOutlier: true };
}
}
}
// Rolling window simulation with outlier detection
/*
const detector = new DynamicClusterDeviation();
const dataStream = [10, 10.2, 10.5, 9.8, 11, 50, 10.3, 200, 201, 200.1, 205, 202, 250, 260, 270, 280, 290, 300];
// Define the number of elements per rolling window chunk.
const windowSize = 5;
let rollingWindow = [];
dataStream.forEach((value, index) => {
console.log(`\n=== Processing value ${index + 1} ===`);
rollingWindow.push(value);
const result = detector.update(value);
console.log(`Current rolling window: [${rollingWindow.join(', ')}]`);
console.log(`Result: value=${result.value} (${result.isOutlier ? 'Outlier' : 'Inlier'})`);
// Once the window size is reached, show current cluster states and reset the window for the next chunk.
if (rollingWindow.length === windowSize) {
console.log("\n--- Rolling window chunk finished ---");
console.log("Detector cluster states:", JSON.stringify(detector.clusters, null, 2));
rollingWindow = [];
}
});
console.log("\nFinal detector cluster states:", JSON.stringify(detector.clusters, null, 2));
*/