"use strict";
/**
 * entanglement.ts
 *
 * Functions for managing quantum entanglement groups in the Quantum Swarm Orchestrator.
 * Provides utilities for creating, monitoring, and optimizing agent entanglement.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.EntanglementManager = void 0;
/**
 * Class providing enhanced entanglement management capabilities
 */
class EntanglementManager {
    /**
     * Creates a new EntanglementManager
     * @param client The quantum swarm client
     */
    constructor(client) {
        this.client = client;
    }
    /**
     * Calculates compatibility between two agents
     * @param agent1 The first agent
     * @param agent2 The second agent
     * @returns Compatibility score and factors
     */
    calculateAgentCompatibility(agent1, agent2) {
        // Calculate base compatibility factors
        const quantumCompatibility = 1 - Math.abs(agent1.quantumAffinity - agent2.quantumAffinity);
        // Calculate specialty alignment
        let specialtyAlignmentScore = 0;
        let totalSpecialties = 0;
        for (const [specialty, score] of Object.entries(agent1.specializationScores)) {
            if (score > 0.3) { // Only consider meaningful specializations
                totalSpecialties++;
                const otherScore = agent2.specializationScores[specialty] || 0;
                // Higher score for complementary skills (one high, one low)
                const complementary = Math.abs(score - otherScore) > 0.4;
                specialtyAlignmentScore += complementary ? 0.7 : Math.min(score, otherScore);
            }
        }
        // Normalize specialty alignment
        const normalizedSpecialtyAlignment = totalSpecialties > 0
            ? specialtyAlignmentScore / totalSpecialties
            : 0.5;
        // Default entanglement history factor (initialized to 0.5)
        const entanglementHistory = 0.5;
        // Calculate overall compatibility score
        const compatibilityScore = ((quantumCompatibility * 0.4) +
            (normalizedSpecialtyAlignment * 0.4) +
            (entanglementHistory * 0.2));
        return {
            agentPair: [agent1.id, agent2.id],
            compatibilityScore,
            complementaryFactor: Math.abs(agent1.quantumAffinity - agent2.quantumAffinity) > 0.4 ? 0.8 : 0.3,
            historicalSuccessRate: 0.5, // Default initial value
            entanglementHistory: 0, // No entanglements yet
            specialtyAlignment: normalizedSpecialtyAlignment
        };
    }
    /**
     * Creates optimal entanglement groups from a set of agents
     * @param agents The agents to create entanglement groups from
     * @param options Options for optimizing entanglement groups
     * @returns Array of optimized entanglement groups
     */
    createOptimalEntanglementGroups(agents, options = {}) {
        const { minCompatibilityScore = 0.4, preferComplementaryAgents = true, maxGroupSize = 4, enforceCrossInstanceDiversity = true, prioritizeSpecializations = [] } = options;
        const entanglementGroups = [];
        // If we have 3 or fewer agents, put them all in one group
        if (agents.length <= 3) {
            entanglementGroups.push({
                id: `group-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
                agentIds: agents.map(a => a.id),
                entanglementStrength: 0.7, // Default initial value
                entanglementType: 'direct',
                createdAt: new Date(),
                lastInteractionAt: new Date(),
                interactionCount: 0,
                sharedInsights: [],
                coherenceMetrics: {
                    phaseAlignment: 0.5,
                    informationTransfer: 0.5,
                    correlationStrength: 0.5
                }
            });
            return entanglementGroups;
        }
        // For more agents, create a compatibility matrix
        const compatibilityMatrix = {};
        for (let i = 0; i < agents.length; i++) {
            compatibilityMatrix[agents[i].id] = {};
            for (let j = 0; j < agents.length; j++) {
                if (i === j)
                    continue;
                const compatibility = this.calculateAgentCompatibility(agents[i], agents[j]);
                compatibilityMatrix[agents[i].id][agents[j].id] = compatibility;
            }
        }
        // Create a list of ungrouped agents
        const ungroupedAgentIds = new Set(agents.map(a => a.id));
        // Group formation algorithm
        while (ungroupedAgentIds.size >= 2) {
            // Find the best pair to start a group with
            let bestPair = null;
            let bestScore = minCompatibilityScore - 0.1; // Start below threshold
            // Apply specialization priority if specified
            const specializationWeight = prioritizeSpecializations.length > 0 ? 0.3 : 0;
            for (const id1 of ungroupedAgentIds) {
                for (const id2 of ungroupedAgentIds) {
                    if (id1 === id2)
                        continue;
                    const agent1 = agents.find(a => a.id === id1);
                    const agent2 = agents.find(a => a.id === id2);
                    // Skip if cross-instance diversity is enforced and agents are from different instances
                    if (enforceCrossInstanceDiversity &&
                        agent1.drupalInstanceId &&
                        agent2.drupalInstanceId &&
                        agent1.drupalInstanceId === agent2.drupalInstanceId) {
                        continue;
                    }
                    // Get base compatibility
                    const compatibility = compatibilityMatrix[id1][id2];
                    // Skip if below minimum compatibility
                    if (compatibility.compatibilityScore < minCompatibilityScore) {
                        continue;
                    }
                    // Calculate adjusted score based on preferences
                    let adjustedScore = compatibility.compatibilityScore;
                    // Adjust for complementary agents preference
                    if (preferComplementaryAgents) {
                        adjustedScore += compatibility.complementaryFactor * 0.2;
                    }
                    // Adjust for specialization priorities
                    if (specializationWeight > 0) {
                        let specializationBonus = 0;
                        for (const specialization of prioritizeSpecializations) {
                            const score1 = agent1.specializationScores[specialization] || 0;
                            const score2 = agent2.specializationScores[specialization] || 0;
                            // At least one agent should be good at this specialization
                            if (Math.max(score1, score2) > 0.7) {
                                specializationBonus += 0.1;
                            }
                            // Perfect if they have complementary skills
                            if (Math.abs(score1 - score2) > 0.5 && Math.min(score1, score2) > 0.3) {
                                specializationBonus += 0.2;
                            }
                        }
                        adjustedScore += specializationBonus * specializationWeight;
                    }
                    if (adjustedScore > bestScore) {
                        bestScore = adjustedScore;
                        bestPair = [id1, id2];
                    }
                }
            }
            // If no suitable pair found, break
            if (!bestPair)
                break;
            // Create a new group with this pair
            const group = {
                id: `group-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
                agentIds: [...bestPair],
                entanglementStrength: bestScore,
                entanglementType: 'direct',
                createdAt: new Date(),
                lastInteractionAt: new Date(),
                interactionCount: 0,
                sharedInsights: [],
                coherenceMetrics: {
                    phaseAlignment: 0.5,
                    informationTransfer: 0.5,
                    correlationStrength: bestScore
                }
            };
            // Remove these agents from the ungrouped set
            ungroupedAgentIds.delete(bestPair[0]);
            ungroupedAgentIds.delete(bestPair[1]);
            // If we want larger groups and have ungrouped agents, add more agents to this group
            if (maxGroupSize > 2 && ungroupedAgentIds.size > 0) {
                // Find compatible agents to add to this group
                for (let i = 2; i < maxGroupSize && ungroupedAgentIds.size > 0; i++) {
                    let bestAgent = null;
                    let bestGroupScore = minCompatibilityScore - 0.1;
                    // For each ungrouped agent
                    for (const agentId of ungroupedAgentIds) {
                        // Calculate average compatibility with existing group members
                        let totalScore = 0;
                        let validPairs = 0;
                        for (const groupAgentId of group.agentIds) {
                            const compatibility = compatibilityMatrix[agentId][groupAgentId];
                            if (compatibility && compatibility.compatibilityScore >= minCompatibilityScore) {
                                totalScore += compatibility.compatibilityScore;
                                validPairs++;
                            }
                        }
                        // Only consider agents compatible with all group members
                        if (validPairs === group.agentIds.length) {
                            const avgScore = totalScore / validPairs;
                            if (avgScore > bestGroupScore) {
                                bestGroupScore = avgScore;
                                bestAgent = agentId;
                            }
                        }
                    }
                    if (bestAgent && bestGroupScore >= minCompatibilityScore) {
                        group.agentIds.push(bestAgent);
                        ungroupedAgentIds.delete(bestAgent);
                        // Update group entanglement strength (average of all pairs)
                        let totalStrength = 0;
                        let pairCount = 0;
                        for (let j = 0; j < group.agentIds.length; j++) {
                            for (let k = j + 1; k < group.agentIds.length; k++) {
                                const compatibility = compatibilityMatrix[group.agentIds[j]][group.agentIds[k]];
                                if (compatibility) {
                                    totalStrength += compatibility.compatibilityScore;
                                    pairCount++;
                                }
                            }
                        }
                        if (pairCount > 0) {
                            group.entanglementStrength = totalStrength / pairCount;
                            group.coherenceMetrics.correlationStrength = group.entanglementStrength;
                        }
                    }
                    else {
                        break; // No more compatible agents
                    }
                }
            }
            entanglementGroups.push(group);
        }
        // If any agents are left ungrouped, create small groups or add to existing ones
        if (ungroupedAgentIds.size > 0) {
            // If multiple agents are left, create new small groups
            if (ungroupedAgentIds.size >= 2) {
                const remainingAgents = Array.from(ungroupedAgentIds)
                    .map(id => agents.find(a => a.id === id))
                    .filter(Boolean);
                // Recursively create groups with remaining agents
                const additionalGroups = this.createOptimalEntanglementGroups(remainingAgents, {
                    ...options,
                    minCompatibilityScore: minCompatibilityScore * 0.8 // Lower the bar a bit
                });
                entanglementGroups.push(...additionalGroups);
            }
            // If only one agent is left, add it to the most compatible existing group
            else if (ungroupedAgentIds.size === 1) {
                const remainingAgentId = Array.from(ungroupedAgentIds)[0];
                let bestGroupIndex = 0;
                let bestAvgCompatibility = 0;
                // Find the most compatible group
                for (let i = 0; i < entanglementGroups.length; i++) {
                    const group = entanglementGroups[i];
                    // Skip if group is already at max size
                    if (group.agentIds.length >= maxGroupSize) {
                        continue;
                    }
                    // Calculate average compatibility with this group
                    let totalScore = 0;
                    for (const groupAgentId of group.agentIds) {
                        const compatibility = compatibilityMatrix[remainingAgentId][groupAgentId];
                        if (compatibility) {
                            totalScore += compatibility.compatibilityScore;
                        }
                    }
                    const avgCompatibility = totalScore / group.agentIds.length;
                    if (avgCompatibility > bestAvgCompatibility) {
                        bestAvgCompatibility = avgCompatibility;
                        bestGroupIndex = i;
                    }
                }
                // Add to best group if compatibility is acceptable
                if (bestAvgCompatibility >= minCompatibilityScore * 0.8) {
                    entanglementGroups[bestGroupIndex].agentIds.push(remainingAgentId);
                    ungroupedAgentIds.delete(remainingAgentId);
                    // Update group entanglement strength
                    let totalStrength = 0;
                    let pairCount = 0;
                    for (let j = 0; j < entanglementGroups[bestGroupIndex].agentIds.length; j++) {
                        for (let k = j + 1; k < entanglementGroups[bestGroupIndex].agentIds.length; k++) {
                            const id1 = entanglementGroups[bestGroupIndex].agentIds[j];
                            const id2 = entanglementGroups[bestGroupIndex].agentIds[k];
                            const compatibility = compatibilityMatrix[id1]?.[id2];
                            if (compatibility) {
                                totalStrength += compatibility.compatibilityScore;
                                pairCount++;
                            }
                        }
                    }
                    if (pairCount > 0) {
                        entanglementGroups[bestGroupIndex].entanglementStrength = totalStrength / pairCount;
                        entanglementGroups[bestGroupIndex].coherenceMetrics.correlationStrength =
                            entanglementGroups[bestGroupIndex].entanglementStrength;
                    }
                }
                // If no acceptable group found, create a singleton group
                else {
                    const singletonAgent = agents.find(a => a.id === remainingAgentId);
                    entanglementGroups.push({
                        id: `singleton-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`,
                        agentIds: [remainingAgentId],
                        entanglementStrength: 0.5, // Default for singleton
                        entanglementType: 'direct',
                        createdAt: new Date(),
                        lastInteractionAt: new Date(),
                        interactionCount: 0,
                        sharedInsights: [],
                        coherenceMetrics: {
                            phaseAlignment: 0.5,
                            informationTransfer: 0.5,
                            correlationStrength: 0.5
                        }
                    });
                    ungroupedAgentIds.delete(remainingAgentId);
                }
            }
        }
        return entanglementGroups;
    }
    /**
     * Calculates coherence metrics for an entanglement group
     * @param group The entanglement group
     * @param insights Insights shared within the group
     * @returns Updated coherence metrics
     */
    calculateCoherenceMetrics(group, insights = []) {
        // Base metrics
        const metrics = {
            phaseAlignment: group.coherenceMetrics.phaseAlignment,
            informationTransfer: group.coherenceMetrics.informationTransfer,
            correlationStrength: group.coherenceMetrics.correlationStrength
        };
        // Adjust based on insights
        if (insights.length > 0) {
            // Analyze insight contribution patterns
            const contributorFrequency = {};
            let totalInsightQuality = 0;
            for (const insight of insights) {
                // Track contribution frequency
                for (const agentId of insight.contributingAgents) {
                    contributorFrequency[agentId] = (contributorFrequency[agentId] || 0) + 1;
                }
                // Sum insight quality
                totalInsightQuality += insight.confidenceScore;
            }
            // Calculate contribution balance (how evenly agents contribute)
            const groupAgentIds = new Set(group.agentIds);
            const contributingGroupAgents = Object.keys(contributorFrequency)
                .filter(id => groupAgentIds.has(id));
            if (contributingGroupAgents.length > 0) {
                // Phase alignment is improved when all agents contribute
                const contributionRatio = contributingGroupAgents.length / group.agentIds.length;
                metrics.phaseAlignment = 0.3 + (contributionRatio * 0.7);
                // Information transfer is based on insight quality and frequency
                const avgInsightQuality = totalInsightQuality / insights.length;
                metrics.informationTransfer = 0.2 + (avgInsightQuality * 0.6) + (Math.min(1, insights.length / 10) * 0.2);
                // Correlation strength factors in both alignment and transfer
                metrics.correlationStrength = (metrics.phaseAlignment * 0.5) + (metrics.informationTransfer * 0.5);
            }
        }
        else {
            // Without insights, use interaction count as a proxy
            const interactionFactor = Math.min(1.0, group.interactionCount / 20);
            metrics.informationTransfer = 0.2 + (interactionFactor * 0.4);
        }
        return metrics;
    }
    /**
     * Updates an entanglement group with a new insight
     * @param group The entanglement group to update
     * @param insight The new insight to add
     * @returns Updated entanglement group
     */
    updateGroupWithInsight(group, insight) {
        // Create a new copy of the group
        const updatedGroup = { ...group };
        // Add insight to shared insights
        updatedGroup.sharedInsights = [...group.sharedInsights, insight.id];
        updatedGroup.interactionCount += 1;
        updatedGroup.lastInteractionAt = new Date();
        // Increase entanglement strength based on insight quality
        updatedGroup.entanglementStrength = Math.min(1.0, group.entanglementStrength + (insight.confidenceScore * 0.05));
        // Update coherence metrics
        updatedGroup.coherenceMetrics.informationTransfer = Math.min(1.0, group.coherenceMetrics.informationTransfer + 0.1);
        updatedGroup.coherenceMetrics.correlationStrength = Math.min(1.0, group.coherenceMetrics.correlationStrength + 0.05);
        return updatedGroup;
    }
    /**
     * Optimizes existing entanglement groups based on performance
     * @param groups Current entanglement groups
     * @param agents All available agents
     * @param insights Insights generated by these groups
     * @returns Optimized entanglement groups
     */
    optimizeEntanglementGroups(groups, agents, insights) {
        // First, evaluate current group performance
        const groupPerformance = {};
        for (const group of groups) {
            // Find insights related to this group
            const groupInsights = insights.filter(insight => insight.contributingAgents.some(agentId => group.agentIds.includes(agentId)));
            // Calculate contribution stats
            const contributionCounts = {};
            let totalQuality = 0;
            for (const insight of groupInsights) {
                for (const agentId of insight.contributingAgents) {
                    if (group.agentIds.includes(agentId)) {
                        contributionCounts[agentId] = (contributionCounts[agentId] || 0) + 1;
                    }
                }
                totalQuality += insight.confidenceScore;
            }
            const contributingAgents = Object.keys(contributionCounts).length;
            const contributionBalance = contributingAgents / Math.max(1, group.agentIds.length);
            const avgInsightQuality = groupInsights.length > 0
                ? totalQuality / groupInsights.length
                : 0;
            // Calculate overall performance score
            const score = ((group.entanglementStrength * 0.3) +
                (avgInsightQuality * 0.3) +
                (contributionBalance * 0.2) +
                (Math.min(1, groupInsights.length / 5) * 0.2));
            groupPerformance[group.id] = {
                group,
                score,
                insightCount: groupInsights.length,
                avgInsightQuality,
                contributionBalance
            };
        }
        // Identify underperforming groups (lowest 20% by score)
        const sortedPerformance = Object.values(groupPerformance)
            .sort((a, b) => a.score - b.score);
        const underperformingCount = Math.max(1, Math.floor(groups.length * 0.2));
        const underperformingGroups = sortedPerformance.slice(0, underperformingCount);
        // Keep high-performing groups as is
        const keepGroups = groups.filter(group => !underperformingGroups.some(g => g.group.id === group.id));
        // Collect agents from underperforming groups for reorganization
        const agentsToReorganize = [];
        for (const { group } of underperformingGroups) {
            agentsToReorganize.push(...group.agentIds);
        }
        // Create new groups with these agents
        const agentsForNewGroups = agents.filter(agent => agentsToReorganize.includes(agent.id));
        // Create optimized groups for these agents
        const newGroups = this.createOptimalEntanglementGroups(agentsForNewGroups, {
            minCompatibilityScore: 0.5,
            preferComplementaryAgents: true,
            maxGroupSize: 3,
            enforceCrossInstanceDiversity: true
        });
        // Combine kept groups with new groups
        return [...keepGroups, ...newGroups];
    }
}
exports.EntanglementManager = EntanglementManager;
exports.default = EntanglementManager;
//# sourceMappingURL=entanglement.js.map