Skip to main content
Glama
RealTimeProblemDecomposer.ts28.3 kB
/** * Real-Time Problem Decomposer * * Provides real-time problem decomposition with multiple strategies, * hierarchical problem structure representation, priority analysis, * dependency mapping, and critical path identification. */ import { PriorityItem, Problem, ProblemDependency, } from "../interfaces/systematic-thinking.js"; import { Context } from "../types/core.js"; export interface DecompositionStrategy { name: string; description: string; apply(problem: Problem, context?: Context): Promise<Problem[]>; getApplicabilityScore(problem: Problem): number; } export interface HierarchicalProblemNode { id: string; problem: Problem; parent_id?: string; children_ids: string[]; level: number; priority_score: number; critical_path_member: boolean; } export interface DecompositionResult { original_problem: Problem; hierarchical_structure: HierarchicalProblemNode[]; dependencies: ProblemDependency[]; critical_path: string[]; priority_ranking: PriorityItem[]; decomposition_strategies_used: string[]; processing_time_ms: number; confidence: number; } export class RealTimeProblemDecomposer { private strategies: Map<string, DecompositionStrategy>; private initialized: boolean = false; constructor() { this.strategies = new Map(); } async initialize(): Promise<void> { if (this.initialized) { return; } // Initialize decomposition strategies this.strategies.set("functional", new FunctionalDecompositionStrategy()); this.strategies.set("temporal", new TemporalDecompositionStrategy()); this.strategies.set("stakeholder", new StakeholderDecompositionStrategy()); this.strategies.set("component", new ComponentDecompositionStrategy()); this.strategies.set("risk", new RiskBasedDecompositionStrategy()); this.strategies.set("resource", new ResourceBasedDecompositionStrategy()); this.strategies.set( "complexity", new ComplexityBasedDecompositionStrategy() ); this.initialized = true; } async decomposeRealTime( problem: Problem, context?: Context ): Promise<DecompositionResult> { const startTime = Date.now(); if (!this.initialized) { await this.initialize(); } // Ensure minimum processing time for measurement accuracy await new Promise((resolve) => setTimeout(resolve, 1)); // Step 1: Select optimal decomposition strategies const selectedStrategies = this.selectOptimalStrategies(problem); // Step 2: Apply strategies in parallel for real-time performance const decompositionResults = await Promise.all( selectedStrategies.map(async (strategy) => ({ strategy: strategy.name, problems: await strategy.apply(problem, context), })) ); // Step 3: Merge and deduplicate results const allSubProblems = this.mergeAndDeduplicateProblems(decompositionResults); // Step 4: Build hierarchical structure const hierarchicalStructure = this.buildHierarchicalStructure( problem, allSubProblems ); // Step 5: Identify dependencies in real-time const dependencies = await this.identifyDependenciesRealTime( hierarchicalStructure ); // Step 6: Calculate critical path const criticalPath = this.calculateCriticalPathRealTime( hierarchicalStructure, dependencies ); // Step 7: Perform priority analysis const priorityRanking = this.performPriorityAnalysis( hierarchicalStructure, dependencies, criticalPath ); // Step 8: Update critical path membership this.updateCriticalPathMembership(hierarchicalStructure, criticalPath); const processingTime = Date.now() - startTime; return { original_problem: problem, hierarchical_structure: hierarchicalStructure, dependencies, critical_path: criticalPath, priority_ranking: priorityRanking, decomposition_strategies_used: selectedStrategies.map((s) => s.name), processing_time_ms: processingTime, confidence: this.calculateDecompositionConfidence( hierarchicalStructure, dependencies, processingTime ), }; } private selectOptimalStrategies(problem: Problem): DecompositionStrategy[] { const strategies: Array<{ strategy: DecompositionStrategy; score: number; }> = []; for (const strategy of this.strategies.values()) { const score = strategy.getApplicabilityScore(problem); if (score > 0.3) { // Only use strategies with reasonable applicability strategies.push({ strategy, score }); } } // Sort by score and select top 3-4 strategies for optimal performance return strategies .sort((a, b) => b.score - a.score) .slice(0, 4) .map((s) => s.strategy); } private mergeAndDeduplicateProblems( decompositionResults: Array<{ strategy: string; problems: Problem[] }> ): Problem[] { const allProblems: Problem[] = []; const seenDescriptions = new Set<string>(); for (const result of decompositionResults) { for (const problem of result.problems) { const normalizedDesc = this.normalizeDescription(problem.description); if (!seenDescriptions.has(normalizedDesc)) { seenDescriptions.add(normalizedDesc); allProblems.push(problem); } } } return allProblems; } private normalizeDescription(description: string): string { return description .toLowerCase() .replace(/[^a-z0-9\s]/g, "") .replace(/\s+/g, " ") .trim(); } private buildHierarchicalStructure( rootProblem: Problem, subProblems: Problem[] ): HierarchicalProblemNode[] { const nodes: HierarchicalProblemNode[] = []; // Create root node const rootId = this.generateProblemId(rootProblem); const rootNode: HierarchicalProblemNode = { id: rootId, problem: rootProblem, children_ids: [], level: 0, priority_score: 0, // Will be calculated later critical_path_member: false, }; nodes.push(rootNode); // Create sub-problem nodes and establish parent-child relationships for (const subProblem of subProblems) { const subId = this.generateProblemId(subProblem); const subNode: HierarchicalProblemNode = { id: subId, problem: subProblem, parent_id: rootId, children_ids: [], level: 1, priority_score: 0, // Will be calculated later critical_path_member: false, }; nodes.push(subNode); rootNode.children_ids.push(subId); } // Identify potential sub-sub-problems and create deeper hierarchy this.buildDeeperHierarchy(nodes, subProblems); return nodes; } private buildDeeperHierarchy( nodes: HierarchicalProblemNode[], problems: Problem[] ): void { // Look for problems that could be sub-problems of other sub-problems const level1Nodes = nodes.filter((n) => n.level === 1); for (const parentNode of level1Nodes) { for (const problem of problems) { const problemId = this.generateProblemId(problem); // Skip if this problem is already in the hierarchy if (nodes.some((n) => n.id === problemId)) { continue; } // Check if this problem could be a child of the parent node if (this.isSubProblemOf(problem, parentNode.problem)) { const childId = this.generateProblemId(problem); const childNode: HierarchicalProblemNode = { id: childId, problem, parent_id: parentNode.id, children_ids: [], level: 2, priority_score: 0, critical_path_member: false, }; nodes.push(childNode); parentNode.children_ids.push(childId); } } } } private isSubProblemOf(candidate: Problem, parent: Problem): boolean { const candidateDesc = candidate.description.toLowerCase(); const parentDesc = parent.description.toLowerCase(); // Check if candidate description contains key terms from parent const parentKeywords = parentDesc .split(/\s+/) .filter((word) => word.length > 3); const matchingKeywords = parentKeywords.filter((keyword) => candidateDesc.includes(keyword) ); // Also check domain and complexity relationship const sameOrRelatedDomain = candidate.domain === parent.domain; const lowerComplexity = candidate.complexity <= parent.complexity; return ( matchingKeywords.length >= 2 && sameOrRelatedDomain && lowerComplexity ); } private async identifyDependenciesRealTime( nodes: HierarchicalProblemNode[] ): Promise<ProblemDependency[]> { const dependencies: ProblemDependency[] = []; // Use parallel processing for dependency identification const dependencyPromises: Promise<ProblemDependency | null>[] = []; for (let i = 0; i < nodes.length; i++) { for (let j = 0; j < nodes.length; j++) { if (i !== j) { dependencyPromises.push( this.analyzeDependencyRealTime(nodes[i], nodes[j]) ); } } } const results = await Promise.all(dependencyPromises); for (const dependency of results) { if (dependency) { dependencies.push(dependency); } } return dependencies; } private async analyzeDependencyRealTime( node1: HierarchicalProblemNode, node2: HierarchicalProblemNode ): Promise<ProblemDependency | null> { const problem1 = node1.problem; const problem2 = node2.problem; // Quick dependency analysis optimized for real-time performance const dependencyType = this.identifyDependencyType(problem1, problem2); if (dependencyType) { return { from: node1.id, to: node2.id, type: dependencyType.type, strength: dependencyType.strength, }; } return null; } private identifyDependencyType( problem1: Problem, problem2: Problem ): { type: ProblemDependency["type"]; strength: number } | null { const desc1 = problem1.description.toLowerCase(); const desc2 = problem2.description.toLowerCase(); // Prerequisite patterns (optimized for speed) const prerequisitePatterns = [ { pattern: /plan.*implement/, strength: 0.9 }, { pattern: /design.*build/, strength: 0.8 }, { pattern: /research.*develop/, strength: 0.7 }, { pattern: /analyze.*solve/, strength: 0.8 }, ]; for (const { pattern, strength } of prerequisitePatterns) { if (pattern.test(`${desc1} ${desc2}`)) { return { type: "prerequisite", strength }; } } // Resource dependencies const sharedResources = problem1.resource_requirements.filter((r) => problem2.resource_requirements.includes(r) ); if (sharedResources.length > 0) { return { type: "resource", strength: Math.min(0.8, sharedResources.length * 0.3), }; } // Constraint dependencies const sharedConstraints = problem1.constraints.filter((c) => problem2.constraints.includes(c) ); if (sharedConstraints.length > 0) { return { type: "constraint", strength: Math.min(0.7, sharedConstraints.length * 0.25), }; } // Temporal dependencies if ( problem1.time_sensitivity > 0.7 && problem2.time_sensitivity > 0.7 && problem1.domain === problem2.domain ) { return { type: "temporal", strength: 0.6 }; } return null; } private calculateCriticalPathRealTime( nodes: HierarchicalProblemNode[], dependencies: ProblemDependency[] ): string[] { // If no dependencies, return a simple path through high-priority nodes if (dependencies.length === 0) { // Sort nodes by priority and time sensitivity, return top nodes as critical path const sortedNodes = [...nodes].sort((a, b) => { const priorityA = a.problem.time_sensitivity * 0.6 + a.problem.complexity * 0.4; const priorityB = b.problem.time_sensitivity * 0.6 + b.problem.complexity * 0.4; return priorityB - priorityA; }); // Return top 3 nodes or all nodes if less than 3 return sortedNodes .slice(0, Math.min(3, sortedNodes.length)) .map((n) => n.id); } // Optimized critical path calculation using topological sort const inDegree = new Map<string, number>(); const adjList = new Map<string, string[]>(); // Initialize for (const node of nodes) { inDegree.set(node.id, 0); adjList.set(node.id, []); } // Build adjacency list and calculate in-degrees for (const dep of dependencies) { adjList.get(dep.from)?.push(dep.to); inDegree.set(dep.to, (inDegree.get(dep.to) ?? 0) + 1); } // Find nodes with no incoming edges (starting points) const queue: string[] = []; for (const [nodeId, degree] of inDegree.entries()) { if (degree === 0) { queue.push(nodeId); } } const criticalPath: string[] = []; // Process nodes in topological order while (queue.length > 0) { const current = queue.shift(); if (!current) break; // Safety check, though this should never happen criticalPath.push(current); // Process neighbors const neighbors = adjList.get(current) ?? []; for (const neighbor of neighbors) { const newDegree = (inDegree.get(neighbor) ?? 0) - 1; inDegree.set(neighbor, newDegree); if (newDegree === 0) { queue.push(neighbor); } } } // If critical path is empty or too short, ensure we have at least the root node if (criticalPath.length === 0) { const rootNode = nodes.find((n) => n.level === 0); if (rootNode) { criticalPath.push(rootNode.id); } } return criticalPath; } private performPriorityAnalysis( nodes: HierarchicalProblemNode[], dependencies: ProblemDependency[], criticalPath: string[] ): PriorityItem[] { const priorities: PriorityItem[] = []; for (const node of nodes) { const priorityScore = this.calculateNodePriority( node, dependencies, criticalPath ); node.priority_score = priorityScore; // Update node with calculated priority priorities.push({ problem_id: node.id, priority_score: priorityScore, reasoning: this.generatePriorityReasoning( node, dependencies, criticalPath ), }); } return priorities.sort((a, b) => b.priority_score - a.priority_score); } private calculateNodePriority( node: HierarchicalProblemNode, dependencies: ProblemDependency[], criticalPath: string[] ): number { let score = 0.3; // Base score const problem = node.problem; // Factor in problem characteristics score += problem.complexity * 0.2; score += problem.time_sensitivity * 0.25; score += problem.uncertainty * 0.15; // Factor in hierarchical level (higher level = higher priority) score += (3 - node.level) * 0.1; // Factor in dependency count const dependencyCount = dependencies.filter( (dep) => dep.from === node.id || dep.to === node.id ).length; score += Math.min(dependencyCount * 0.05, 0.2); // Critical path bonus if (criticalPath.includes(node.id)) { score += 0.3; } // Stakeholder count factor score += Math.min(problem.stakeholders.length * 0.03, 0.15); return Math.min(score, 1.0); } private generatePriorityReasoning( node: HierarchicalProblemNode, dependencies: ProblemDependency[], criticalPath: string[] ): string { const reasons: string[] = []; const problem = node.problem; reasons.push(`Priority: ${(node.priority_score * 100).toFixed(0)}%`); if (criticalPath.includes(node.id)) { reasons.push("On critical path"); } if (problem.time_sensitivity > 0.7) { reasons.push("Time-sensitive"); } if (problem.complexity > 0.7) { reasons.push("High complexity"); } if (node.level === 0) { reasons.push("Root problem"); } const dependencyCount = dependencies.filter( (dep) => dep.from === node.id || dep.to === node.id ).length; if (dependencyCount > 2) { reasons.push(`${dependencyCount} dependencies`); } return reasons.join(", "); } private updateCriticalPathMembership( nodes: HierarchicalProblemNode[], criticalPath: string[] ): void { for (const node of nodes) { node.critical_path_member = criticalPath.includes(node.id); } } private calculateDecompositionConfidence( nodes: HierarchicalProblemNode[], dependencies: ProblemDependency[], processingTime: number ): number { let confidence = 0.7; // Base confidence // Factor in number of nodes (more nodes = more thorough decomposition) const nodeCount = nodes.length; if (nodeCount > 3) confidence += 0.1; if (nodeCount > 6) confidence += 0.1; // Factor in dependency identification const avgDependencyStrength = dependencies.length > 0 ? dependencies.reduce((sum, dep) => sum + dep.strength, 0) / dependencies.length : 0; confidence += avgDependencyStrength * 0.1; // Factor in processing time (faster = higher confidence in real-time context) if (processingTime < 1000) confidence += 0.1; // Under 1 second if (processingTime < 500) confidence += 0.1; // Under 0.5 seconds // Factor in problem characteristics - simpler problems should have higher confidence if (nodes.length > 0) { const rootNode = nodes.find((n) => n.level === 0); if (rootNode) { const problem = rootNode.problem; // Lower complexity and uncertainty = higher confidence confidence += (1 - problem.complexity) * 0.1; confidence += (1 - problem.uncertainty) * 0.1; // Fewer constraints = higher confidence if (problem.constraints.length <= 2) confidence += 0.05; } } return Math.min(confidence, 1.0); } private generateProblemId(problem: Problem): string { // Generate a consistent ID from problem description const hash = problem.description .toLowerCase() .replace(/[^a-z0-9]/g, "") .substring(0, 16); return `prob_${hash}_${Date.now().toString(36)}`; } // Public method to get available strategies getAvailableStrategies(): string[] { return Array.from(this.strategies.keys()); } // Public method to get strategy details getStrategyDetails(strategyName: string): DecompositionStrategy | undefined { return this.strategies.get(strategyName); } } // Decomposition Strategy Implementations class FunctionalDecompositionStrategy implements DecompositionStrategy { name = "functional"; description = "Decomposes problems by functional requirements and capabilities"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { const subProblems: Problem[] = []; const description = problem.description.toLowerCase(); const functionalKeywords = [ "authentication", "authorization", "validation", "processing", "storage", "retrieval", "analysis", "reporting", "monitoring", "logging", "caching", "optimization", "integration", "communication", ]; for (const keyword of functionalKeywords) { if (description.includes(keyword)) { subProblems.push({ description: `Implement ${keyword} functionality for ${problem.description}`, domain: problem.domain, complexity: problem.complexity * 0.6, uncertainty: problem.uncertainty * 0.8, constraints: problem.constraints, stakeholders: problem.stakeholders, time_sensitivity: problem.time_sensitivity, resource_requirements: problem.resource_requirements, }); } } return subProblems; } getApplicabilityScore(problem: Problem): number { const description = problem.description.toLowerCase(); const functionalIndicators = [ /function|feature|capability|requirement/i, /implement|develop|build|create/i, /system|application|platform|service/i, ]; let score = 0.3; for (const indicator of functionalIndicators) { if (indicator.test(description)) { score += 0.2; } } return Math.min(score, 1.0); } } class TemporalDecompositionStrategy implements DecompositionStrategy { name = "temporal"; description = "Decomposes problems by time phases and milestones"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { const phases = [ { name: "immediate", factor: 0.3, urgency: 1.0 }, { name: "short-term", factor: 0.6, urgency: 0.7 }, { name: "medium-term", factor: 0.8, urgency: 0.5 }, { name: "long-term", factor: 1.0, urgency: 0.3 }, ]; return phases.map((phase) => ({ description: `${ phase.name.charAt(0).toUpperCase() + phase.name.slice(1) } phase: ${problem.description}`, domain: problem.domain, complexity: problem.complexity * phase.factor, uncertainty: problem.uncertainty * (phase.factor + 0.2), constraints: problem.constraints, stakeholders: problem.stakeholders, time_sensitivity: phase.urgency, resource_requirements: problem.resource_requirements, })); } getApplicabilityScore(problem: Problem): number { let score = 0.4; // Base score for temporal applicability if (problem.time_sensitivity > 0.5) score += 0.3; if (problem.description.toLowerCase().includes("phase")) score += 0.2; if (problem.description.toLowerCase().includes("timeline")) score += 0.2; return Math.min(score, 1.0); } } class StakeholderDecompositionStrategy implements DecompositionStrategy { name = "stakeholder"; description = "Decomposes problems by stakeholder needs and perspectives"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { return problem.stakeholders.map((stakeholder) => ({ description: `Address ${stakeholder} needs for ${problem.description}`, domain: problem.domain, complexity: problem.complexity * 0.5, uncertainty: problem.uncertainty * 0.7, constraints: problem.constraints, stakeholders: [stakeholder], time_sensitivity: problem.time_sensitivity, resource_requirements: problem.resource_requirements, })); } getApplicabilityScore(problem: Problem): number { let score = 0.2; score += problem.stakeholders.length * 0.15; if (problem.description.toLowerCase().includes("user")) score += 0.2; if (problem.description.toLowerCase().includes("stakeholder")) score += 0.3; return Math.min(score, 1.0); } } class ComponentDecompositionStrategy implements DecompositionStrategy { name = "component"; description = "Decomposes problems by system components and modules"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { const subProblems: Problem[] = []; const description = problem.description.toLowerCase(); const componentPatterns = [ { pattern: /frontend|ui|interface/, name: "Frontend" }, { pattern: /backend|server|api/, name: "Backend" }, { pattern: /database|storage|data/, name: "Data Layer" }, { pattern: /security|auth/, name: "Security" }, { pattern: /performance|optimization/, name: "Performance" }, { pattern: /testing|quality/, name: "Quality Assurance" }, ]; for (const { pattern, name } of componentPatterns) { if (pattern.test(description)) { subProblems.push({ description: `${name} component for ${problem.description}`, domain: problem.domain, complexity: problem.complexity * 0.7, uncertainty: problem.uncertainty * 0.8, constraints: problem.constraints, stakeholders: problem.stakeholders, time_sensitivity: problem.time_sensitivity, resource_requirements: problem.resource_requirements, }); } } return subProblems; } getApplicabilityScore(problem: Problem): number { const description = problem.description.toLowerCase(); const componentIndicators = [ /component|module|service|layer/i, /architecture|system|platform/i, /frontend|backend|database/i, ]; let score = 0.3; for (const indicator of componentIndicators) { if (indicator.test(description)) { score += 0.2; } } return Math.min(score, 1.0); } } class RiskBasedDecompositionStrategy implements DecompositionStrategy { name = "risk"; description = "Decomposes problems by risk factors and mitigation strategies"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { const riskFactors = [ "technical_risk", "timeline_risk", "resource_risk", "quality_risk", "integration_risk", "user_acceptance_risk", ]; return riskFactors.map((risk) => ({ description: `Mitigate ${risk.replace("_", " ")} for ${ problem.description }`, domain: problem.domain, complexity: problem.complexity * 0.6, uncertainty: problem.uncertainty * 1.2, // Risk increases uncertainty constraints: [...problem.constraints, "risk_mitigation"], stakeholders: problem.stakeholders, time_sensitivity: problem.time_sensitivity * 1.1, resource_requirements: [ ...problem.resource_requirements, "risk_analysis", ], })); } getApplicabilityScore(problem: Problem): number { let score = 0.2; if (problem.uncertainty > 0.6) score += 0.3; if (problem.complexity > 0.7) score += 0.2; if (problem.description.toLowerCase().includes("risk")) score += 0.4; return Math.min(score, 1.0); } } class ResourceBasedDecompositionStrategy implements DecompositionStrategy { name = "resource"; description = "Decomposes problems by resource requirements and constraints"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { return problem.resource_requirements.map((resource) => ({ description: `Manage ${resource} for ${problem.description}`, domain: problem.domain, complexity: problem.complexity * 0.5, uncertainty: problem.uncertainty * 0.9, constraints: problem.constraints, stakeholders: problem.stakeholders, time_sensitivity: problem.time_sensitivity, resource_requirements: [resource], })); } getApplicabilityScore(problem: Problem): number { let score = 0.1; score += problem.resource_requirements.length * 0.15; if (problem.constraints.includes("resource_constraint")) score += 0.3; return Math.min(score, 1.0); } } class ComplexityBasedDecompositionStrategy implements DecompositionStrategy { name = "complexity"; description = "Decomposes problems by complexity levels and simplification"; async apply(problem: Problem, _context?: Context): Promise<Problem[]> { if (problem.complexity < 0.5) { return []; // Not applicable for simple problems } const complexityLevels = [ { name: "core", factor: 0.4 }, { name: "extended", factor: 0.7 }, { name: "advanced", factor: 1.0 }, ]; return complexityLevels.map((level) => ({ description: `${ level.name.charAt(0).toUpperCase() + level.name.slice(1) } complexity level for ${problem.description}`, domain: problem.domain, complexity: problem.complexity * level.factor, uncertainty: problem.uncertainty * level.factor, constraints: problem.constraints, stakeholders: problem.stakeholders, time_sensitivity: problem.time_sensitivity, resource_requirements: problem.resource_requirements, })); } getApplicabilityScore(problem: Problem): number { let score = 0.1; if (problem.complexity > 0.5) score += 0.3; if (problem.complexity > 0.8) score += 0.4; return Math.min(score, 1.0); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server