@ruvector/edge-net 0.4.6 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Swarm Intelligence Plugin
3
+ *
4
+ * Distributed optimization using bio-inspired algorithms:
5
+ * - Particle Swarm Optimization (PSO)
6
+ * - Ant Colony Optimization (ACO)
7
+ * - Genetic Algorithm (GA)
8
+ * - Differential Evolution (DE)
9
+ *
10
+ * @module @ruvector/edge-net/plugins/swarm-intelligence
11
+ */
12
+
13
+ import { EventEmitter } from 'events';
14
+
15
+ export class SwarmIntelligencePlugin extends EventEmitter {
16
+ constructor(config = {}) {
17
+ super();
18
+
19
+ this.config = {
20
+ algorithm: config.algorithm || 'pso',
21
+ populationSize: config.populationSize || 50,
22
+ iterations: config.iterations || 100,
23
+ dimensions: config.dimensions || 10,
24
+ };
25
+
26
+ this.swarms = new Map(); // swarmId -> SwarmState
27
+ }
28
+
29
+ /**
30
+ * Create optimization swarm
31
+ */
32
+ createSwarm(swarmId, options = {}) {
33
+ const swarm = {
34
+ id: swarmId,
35
+ algorithm: options.algorithm || this.config.algorithm,
36
+ dimensions: options.dimensions || this.config.dimensions,
37
+ bounds: options.bounds || { min: -10, max: 10 },
38
+ fitnessFunction: options.fitnessFunction || this._defaultFitness,
39
+ particles: [],
40
+ globalBest: null,
41
+ globalBestFitness: Infinity,
42
+ iteration: 0,
43
+ status: 'initialized',
44
+ };
45
+
46
+ // Initialize particles
47
+ for (let i = 0; i < this.config.populationSize; i++) {
48
+ swarm.particles.push(this._createParticle(swarm));
49
+ }
50
+
51
+ this.swarms.set(swarmId, swarm);
52
+ this.emit('swarm:created', { swarmId, algorithm: swarm.algorithm });
53
+
54
+ return swarm;
55
+ }
56
+
57
+ /**
58
+ * Create single particle
59
+ */
60
+ _createParticle(swarm) {
61
+ const position = Array(swarm.dimensions).fill(0).map(() =>
62
+ swarm.bounds.min + Math.random() * (swarm.bounds.max - swarm.bounds.min)
63
+ );
64
+
65
+ return {
66
+ position,
67
+ velocity: Array(swarm.dimensions).fill(0).map(() => (Math.random() - 0.5) * 2),
68
+ bestPosition: [...position],
69
+ bestFitness: Infinity,
70
+ fitness: Infinity,
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Default fitness function (minimize sum of squares)
76
+ */
77
+ _defaultFitness(position) {
78
+ return position.reduce((sum, x) => sum + x * x, 0);
79
+ }
80
+
81
+ /**
82
+ * Run optimization step
83
+ */
84
+ step(swarmId) {
85
+ const swarm = this.swarms.get(swarmId);
86
+ if (!swarm) throw new Error(`Swarm not found: ${swarmId}`);
87
+
88
+ swarm.status = 'running';
89
+ swarm.iteration++;
90
+
91
+ switch (swarm.algorithm) {
92
+ case 'pso':
93
+ this._psoStep(swarm);
94
+ break;
95
+ case 'ga':
96
+ this._gaStep(swarm);
97
+ break;
98
+ case 'de':
99
+ this._deStep(swarm);
100
+ break;
101
+ case 'aco':
102
+ this._acoStep(swarm);
103
+ break;
104
+ default:
105
+ this._psoStep(swarm);
106
+ }
107
+
108
+ this.emit('swarm:step', {
109
+ swarmId,
110
+ iteration: swarm.iteration,
111
+ bestFitness: swarm.globalBestFitness,
112
+ });
113
+
114
+ return {
115
+ iteration: swarm.iteration,
116
+ bestFitness: swarm.globalBestFitness,
117
+ bestPosition: swarm.globalBest,
118
+ };
119
+ }
120
+
121
+ /**
122
+ * Particle Swarm Optimization step
123
+ */
124
+ _psoStep(swarm) {
125
+ const w = 0.7; // Inertia weight
126
+ const c1 = 1.5; // Cognitive coefficient
127
+ const c2 = 1.5; // Social coefficient
128
+
129
+ for (const particle of swarm.particles) {
130
+ // Update velocity
131
+ for (let d = 0; d < swarm.dimensions; d++) {
132
+ const r1 = Math.random();
133
+ const r2 = Math.random();
134
+
135
+ particle.velocity[d] =
136
+ w * particle.velocity[d] +
137
+ c1 * r1 * (particle.bestPosition[d] - particle.position[d]) +
138
+ c2 * r2 * ((swarm.globalBest?.[d] || 0) - particle.position[d]);
139
+ }
140
+
141
+ // Update position
142
+ for (let d = 0; d < swarm.dimensions; d++) {
143
+ particle.position[d] += particle.velocity[d];
144
+ // Clamp to bounds
145
+ particle.position[d] = Math.max(swarm.bounds.min,
146
+ Math.min(swarm.bounds.max, particle.position[d]));
147
+ }
148
+
149
+ // Evaluate fitness
150
+ particle.fitness = swarm.fitnessFunction(particle.position);
151
+
152
+ // Update personal best
153
+ if (particle.fitness < particle.bestFitness) {
154
+ particle.bestFitness = particle.fitness;
155
+ particle.bestPosition = [...particle.position];
156
+ }
157
+
158
+ // Update global best
159
+ if (particle.fitness < swarm.globalBestFitness) {
160
+ swarm.globalBestFitness = particle.fitness;
161
+ swarm.globalBest = [...particle.position];
162
+ }
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Genetic Algorithm step
168
+ */
169
+ _gaStep(swarm) {
170
+ const mutationRate = 0.1;
171
+ const crossoverRate = 0.8;
172
+
173
+ // Evaluate all
174
+ for (const particle of swarm.particles) {
175
+ particle.fitness = swarm.fitnessFunction(particle.position);
176
+ if (particle.fitness < swarm.globalBestFitness) {
177
+ swarm.globalBestFitness = particle.fitness;
178
+ swarm.globalBest = [...particle.position];
179
+ }
180
+ }
181
+
182
+ // Selection (tournament)
183
+ const selected = [];
184
+ for (let i = 0; i < swarm.particles.length; i++) {
185
+ const a = swarm.particles[Math.floor(Math.random() * swarm.particles.length)];
186
+ const b = swarm.particles[Math.floor(Math.random() * swarm.particles.length)];
187
+ selected.push(a.fitness < b.fitness ? a : b);
188
+ }
189
+
190
+ // Crossover and mutation
191
+ for (let i = 0; i < swarm.particles.length; i += 2) {
192
+ const p1 = selected[i];
193
+ const p2 = selected[i + 1] || selected[0];
194
+
195
+ if (Math.random() < crossoverRate && swarm.particles[i + 1]) {
196
+ const crossPoint = Math.floor(Math.random() * swarm.dimensions);
197
+ for (let d = crossPoint; d < swarm.dimensions; d++) {
198
+ const temp = swarm.particles[i].position[d];
199
+ swarm.particles[i].position[d] = p2.position[d];
200
+ swarm.particles[i + 1].position[d] = temp;
201
+ }
202
+ }
203
+
204
+ // Mutation
205
+ for (const particle of [swarm.particles[i], swarm.particles[i + 1]]) {
206
+ if (!particle) continue;
207
+ for (let d = 0; d < swarm.dimensions; d++) {
208
+ if (Math.random() < mutationRate) {
209
+ particle.position[d] += (Math.random() - 0.5) *
210
+ (swarm.bounds.max - swarm.bounds.min) * 0.1;
211
+ particle.position[d] = Math.max(swarm.bounds.min,
212
+ Math.min(swarm.bounds.max, particle.position[d]));
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Differential Evolution step
221
+ */
222
+ _deStep(swarm) {
223
+ const F = 0.8; // Mutation factor
224
+ const CR = 0.9; // Crossover rate
225
+
226
+ const newPositions = [];
227
+
228
+ for (let i = 0; i < swarm.particles.length; i++) {
229
+ // Select 3 random distinct particles
230
+ const indices = [];
231
+ while (indices.length < 3) {
232
+ const idx = Math.floor(Math.random() * swarm.particles.length);
233
+ if (idx !== i && !indices.includes(idx)) indices.push(idx);
234
+ }
235
+
236
+ const [a, b, c] = indices.map(idx => swarm.particles[idx]);
237
+
238
+ // Create mutant
239
+ const mutant = a.position.map((v, d) =>
240
+ v + F * (b.position[d] - c.position[d])
241
+ );
242
+
243
+ // Crossover
244
+ const trial = swarm.particles[i].position.map((v, d) =>
245
+ Math.random() < CR ? mutant[d] : v
246
+ );
247
+
248
+ // Clamp
249
+ trial.forEach((v, d) => {
250
+ trial[d] = Math.max(swarm.bounds.min, Math.min(swarm.bounds.max, v));
251
+ });
252
+
253
+ const trialFitness = swarm.fitnessFunction(trial);
254
+
255
+ if (trialFitness < swarm.particles[i].fitness) {
256
+ newPositions.push({ idx: i, position: trial, fitness: trialFitness });
257
+ }
258
+ }
259
+
260
+ // Apply updates
261
+ for (const { idx, position, fitness } of newPositions) {
262
+ swarm.particles[idx].position = position;
263
+ swarm.particles[idx].fitness = fitness;
264
+
265
+ if (fitness < swarm.globalBestFitness) {
266
+ swarm.globalBestFitness = fitness;
267
+ swarm.globalBest = [...position];
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Ant Colony Optimization step (simplified for continuous optimization)
274
+ */
275
+ _acoStep(swarm) {
276
+ const evaporationRate = 0.1;
277
+ const pheromoneDeposit = 1.0;
278
+
279
+ // Use pheromone as bias toward best solutions
280
+ if (!swarm.pheromone) {
281
+ swarm.pheromone = Array(swarm.dimensions).fill(0);
282
+ }
283
+
284
+ for (const particle of swarm.particles) {
285
+ // Move influenced by pheromone
286
+ for (let d = 0; d < swarm.dimensions; d++) {
287
+ const bias = swarm.pheromone[d] * 0.1;
288
+ particle.position[d] += (Math.random() - 0.5) * 2 + bias;
289
+ particle.position[d] = Math.max(swarm.bounds.min,
290
+ Math.min(swarm.bounds.max, particle.position[d]));
291
+ }
292
+
293
+ particle.fitness = swarm.fitnessFunction(particle.position);
294
+
295
+ if (particle.fitness < swarm.globalBestFitness) {
296
+ swarm.globalBestFitness = particle.fitness;
297
+ swarm.globalBest = [...particle.position];
298
+ }
299
+ }
300
+
301
+ // Update pheromone
302
+ for (let d = 0; d < swarm.dimensions; d++) {
303
+ swarm.pheromone[d] *= (1 - evaporationRate);
304
+ if (swarm.globalBest) {
305
+ swarm.pheromone[d] += pheromoneDeposit / (1 + Math.abs(swarm.globalBest[d]));
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Run full optimization
312
+ */
313
+ async optimize(swarmId, options = {}) {
314
+ const maxIterations = options.iterations || this.config.iterations;
315
+ const targetFitness = options.targetFitness ?? -Infinity;
316
+
317
+ const swarm = this.swarms.get(swarmId);
318
+ if (!swarm) throw new Error(`Swarm not found: ${swarmId}`);
319
+
320
+ while (swarm.iteration < maxIterations && swarm.globalBestFitness > targetFitness) {
321
+ this.step(swarmId);
322
+
323
+ // Yield for async operation
324
+ if (swarm.iteration % 10 === 0) {
325
+ await new Promise(resolve => setImmediate(resolve));
326
+ }
327
+ }
328
+
329
+ swarm.status = 'completed';
330
+
331
+ this.emit('swarm:completed', {
332
+ swarmId,
333
+ iterations: swarm.iteration,
334
+ bestFitness: swarm.globalBestFitness,
335
+ bestPosition: swarm.globalBest,
336
+ });
337
+
338
+ return {
339
+ iterations: swarm.iteration,
340
+ bestFitness: swarm.globalBestFitness,
341
+ bestPosition: swarm.globalBest,
342
+ };
343
+ }
344
+
345
+ /**
346
+ * Distribute optimization across network nodes
347
+ */
348
+ async distributeOptimization(swarmId, nodes, network) {
349
+ const swarm = this.swarms.get(swarmId);
350
+ if (!swarm) throw new Error(`Swarm not found: ${swarmId}`);
351
+
352
+ // Split particles among nodes
353
+ const particlesPerNode = Math.ceil(swarm.particles.length / nodes.length);
354
+ const tasks = [];
355
+
356
+ for (let i = 0; i < nodes.length; i++) {
357
+ const startIdx = i * particlesPerNode;
358
+ const endIdx = Math.min(startIdx + particlesPerNode, swarm.particles.length);
359
+ const nodeParticles = swarm.particles.slice(startIdx, endIdx);
360
+
361
+ tasks.push({
362
+ nodeId: nodes[i],
363
+ particles: nodeParticles.map(p => ({ position: p.position })),
364
+ globalBest: swarm.globalBest,
365
+ iteration: swarm.iteration,
366
+ });
367
+ }
368
+
369
+ this.emit('distributed', { swarmId, nodeCount: nodes.length });
370
+
371
+ return tasks;
372
+ }
373
+
374
+ getSwarm(swarmId) {
375
+ return this.swarms.get(swarmId);
376
+ }
377
+
378
+ getStats() {
379
+ return {
380
+ activeSwarms: this.swarms.size,
381
+ config: this.config,
382
+ };
383
+ }
384
+ }
385
+
386
+ export default SwarmIntelligencePlugin;
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Edge-Net Plugin System
3
+ *
4
+ * Secure, modular plugin architecture for extending edge-net functionality.
5
+ *
6
+ * Features:
7
+ * - Official plugin catalog (practical to exotic)
8
+ * - Custom plugin SDK for user-created plugins
9
+ * - Capability-based security sandboxing
10
+ * - Lazy loading with verification
11
+ * - Plugin bundles for common use cases
12
+ *
13
+ * @module @ruvector/edge-net/plugins
14
+ *
15
+ * @example
16
+ * ```javascript
17
+ * // Load official plugins
18
+ * import { PluginManager, PLUGIN_CATALOG, PLUGIN_BUNDLES } from '@ruvector/edge-net/plugins';
19
+ *
20
+ * const plugins = PluginManager.getInstance();
21
+ *
22
+ * // View available plugins
23
+ * console.log(plugins.getCatalog());
24
+ *
25
+ * // Load a bundle
26
+ * await plugins.loadBundle('privacy-focused');
27
+ *
28
+ * // Load individual plugin
29
+ * const encryption = await plugins.load('privacy.e2e-encryption');
30
+ *
31
+ * // Create custom plugin
32
+ * import { BasePlugin, generatePluginTemplate, getRegistry } from '@ruvector/edge-net/plugins/sdk';
33
+ *
34
+ * class MyPlugin extends BasePlugin {
35
+ * static manifest = { ... };
36
+ * async onInit() { ... }
37
+ * }
38
+ *
39
+ * getRegistry().register(MyPlugin);
40
+ * ```
41
+ */
42
+
43
+ // Core exports
44
+ export { PLUGIN_CATALOG, PLUGIN_BUNDLES, PluginCategory, PluginTier, Capability } from './plugin-manifest.js';
45
+ export { PluginLoader, PluginManager } from './plugin-loader.js';
46
+ export {
47
+ BasePlugin,
48
+ validateManifest,
49
+ validatePlugin,
50
+ PluginRegistry,
51
+ generatePluginTemplate,
52
+ getRegistry,
53
+ } from './plugin-sdk.js';
54
+
55
+ // Implementation exports (for direct use)
56
+ export { CompressionPlugin } from './implementations/compression.js';
57
+ export { E2EEncryptionPlugin } from './implementations/e2e-encryption.js';
58
+ export { FederatedLearningPlugin } from './implementations/federated-learning.js';
59
+ export { ReputationStakingPlugin } from './implementations/reputation-staking.js';
60
+ export { SwarmIntelligencePlugin } from './implementations/swarm-intelligence.js';
61
+
62
+ // Convenience function to get started quickly
63
+ import { PluginManager } from './plugin-loader.js';
64
+
65
+ /**
66
+ * Quick start - get plugin manager with standard bundle
67
+ */
68
+ export async function initPlugins(options = {}) {
69
+ const manager = PluginManager.getInstance(options);
70
+
71
+ if (options.bundle) {
72
+ await manager.loadBundle(options.bundle);
73
+ }
74
+
75
+ return manager;
76
+ }
77
+
78
+ /**
79
+ * List all available plugins with their status
80
+ */
81
+ export function listPlugins() {
82
+ const manager = PluginManager.getInstance();
83
+ return manager.getCatalog();
84
+ }
85
+
86
+ export default {
87
+ initPlugins,
88
+ listPlugins,
89
+ PluginManager,
90
+ };