UNPKG

monte-carlo-simulator

Version:

Business decision framework with Monte Carlo risk analysis - instant via npx

173 lines 6.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseSimulation = void 0; /** * Abstract base class for all Monte Carlo simulations * Provides common utilities and enforces consistent architecture */ class BaseSimulation { config; parameters = {}; constructor(config) { this.config = config; if (config) { this.initializeFromConfig(config); } } // Optional method for parameter grouping defineParameterGroups() { return []; } /** * Generate complete simulation configuration */ generateConfig() { const metadata = this.defineMetadata(); const parameters = this.defineParameters(); const outputs = this.defineOutputs(); const groups = this.defineParameterGroups(); return { name: metadata.name, category: metadata.category, description: metadata.description, version: metadata.version, tags: metadata.tags, parameters, outputs, simulation: { logic: this.generateSimulationLogic() }, ...(groups.length > 0 && { groups }) }; } /** * Run simulation with given parameters */ simulate(params) { this.parameters = { ...params }; this.validateParameters(); return this.calculateScenario(params); } /** * Generate multiple scenario comparisons */ compareScenarios(scenarios) { return scenarios.map(scenario => ({ name: scenario.name, results: this.simulate(scenario.parameters) })); } // Monte Carlo utility functions available to all simulations random() { return Math.random(); } round(value, decimals = 0) { const factor = Math.pow(10, decimals); return Math.round(value * factor) / factor; } min(...values) { return Math.min(...values); } max(...values) { return Math.max(...values); } clamp(value, min, max) { return Math.min(Math.max(value, min), max); } normalDistribution(mean, stdDev) { // Box-Muller transformation for normal distribution const u1 = this.random(); const u2 = this.random(); const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return mean + stdDev * z0; } triangularDistribution(min, max, mode) { const u = this.random(); const c = (mode - min) / (max - min); if (u < c) { return min + Math.sqrt(u * (max - min) * (mode - min)); } else { return max - Math.sqrt((1 - u) * (max - min) * (max - mode)); } } logNormalDistribution(mean, stdDev) { return Math.exp(this.normalDistribution(mean, stdDev)); } percentileDistribution(values, percentile) { const sorted = values.slice().sort((a, b) => a - b); const index = (percentile / 100) * (sorted.length - 1); const lower = Math.floor(index); const upper = Math.ceil(index); const weight = index - lower; if (lower === upper) { return sorted[lower]; } return sorted[lower] * (1 - weight) + sorted[upper] * weight; } // Parameter validation validateParameters() { const parameterDefs = this.defineParameters(); const parameterMap = new Map(parameterDefs.map(p => [p.key, p])); for (const [key, value] of Object.entries(this.parameters)) { const def = parameterMap.get(key); if (!def) continue; if (def.type === 'number' && typeof value === 'number') { if (def.min !== undefined && value < def.min) { throw new Error(`Parameter ${key} value ${value} is below minimum ${def.min}`); } if (def.max !== undefined && value > def.max) { throw new Error(`Parameter ${key} value ${value} exceeds maximum ${def.max}`); } } if (def.type === 'select' && def.options && !def.options.includes(value)) { throw new Error(`Parameter ${key} value ${value} is not in allowed options: ${def.options.join(', ')}`); } } } // Initialize from existing configuration (for backward compatibility) initializeFromConfig(config) { // Extract default values from parameters const defaultParams = {}; config.parameters.forEach(param => { defaultParams[param.key] = param.default; }); this.parameters = defaultParams; } // Generate simulation logic as string (for YAML export) generateSimulationLogic() { // This will be overridden by derived classes that need to export to YAML // For now, return a placeholder that indicates this is a TypeScript-based simulation return `// This simulation is implemented in TypeScript // Use the simulate() method to run calculations throw new Error('This simulation must be run through the TypeScript API')`; } // Helper method to get parameter value with type safety getParameter(key, defaultValue) { const value = this.parameters[key]; return value !== undefined ? value : defaultValue; } // Helper method to check if parameter exists hasParameter(key) { return Object.prototype.hasOwnProperty.call(this.parameters, key); } // Generate parameter validation schema getParameterSchema() { const parameters = this.defineParameters(); const schema = {}; parameters.forEach(param => { schema[param.key] = { type: param.type, required: true, ...(param.min !== undefined && { min: param.min }), ...(param.max !== undefined && { max: param.max }), ...(param.options && { enum: param.options }), description: param.description }; }); return schema; } } exports.BaseSimulation = BaseSimulation; //# sourceMappingURL=BaseSimulation.js.map