using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NPP.SmartSchedue.Api.Contracts.Domain.Work;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Internal;
using NPP.SmartSchedue.Api.Contracts.Services.Integration.Output;
using NPP.SmartSchedue.Api.Services.Integration.Algorithms;
namespace NPP.SmartSchedue.Api.Services.Integration.Algorithms
{
///
/// 全局优化引擎 - 专门负责遗传算法优化和结果处理
/// 设计原则:高内聚、低耦合、单一职责、易维护
/// 核心价值:为智能调度提供高性能的全局优化能力
///
public class GlobalOptimizationEngine
{
#region 私有字段
private readonly GeneticAlgorithmEngine _geneticEngine;
private readonly LinearProgrammingEngine _linearProgrammingEngine;
private readonly ILogger _logger;
// 人员名称缓存
private readonly Dictionary _personnelNameCache = new();
#endregion
#region 构造函数
///
/// 构造函数 - 依赖注入模式
///
public GlobalOptimizationEngine(
GeneticAlgorithmEngine geneticEngine,
LinearProgrammingEngine linearProgrammingEngine,
ILogger logger)
{
_geneticEngine = geneticEngine ?? throw new ArgumentNullException(nameof(geneticEngine));
_linearProgrammingEngine = linearProgrammingEngine ?? throw new ArgumentNullException(nameof(linearProgrammingEngine));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
#endregion
#region 公共方法
///
/// 执行全局优化算法 - 主入口方法
/// 业务流程:预筛选验证 → 遗传算法优化 → 公平性分析 → 智能协商 → 业务规则验证 → 结果构建
/// 核心流程:遗传算法优化 → 基尼系数计算 → 智能协商 → 结果封装
/// 性能目标:通过精英策略和收敛检测控制计算复杂度
///
/// 全局分配上下文,包含任务、人员、配置等所有必需信息
/// 优化后的分配结果,包含成功匹配、失败项、性能指标
public async Task ExecuteOptimizationAsync(GlobalAllocationContext context)
{
var result = new GlobalAllocationResult();
var metrics = new GlobalOptimizationMetrics();
var executionStopwatch = Stopwatch.StartNew();
try
{
_logger.LogInformation("🧬 开始全局优化执行");
// 第一步:验证预筛选结果
if (!ValidatePrefilterResults(context, result))
{
return result;
}
LogPrefilterStatistics(context);
// 第二步:智能选择优化算法
GlobalOptimizedSolution optimizedSolution;
var taskCount = context.Tasks.Count;
var personnelCount = context.AvailablePersonnel.Count;
// 根据问题规模选择最优算法:小规模用线性规划,大规模用遗传算法
_logger.LogInformation("🎯 第2步:执行线性规划优化 - 任务数:{TaskCount},人员数:{PersonnelCount}",
taskCount, personnelCount);
optimizedSolution = await _linearProgrammingEngine.OptimizeAsync(context);
executionStopwatch.Stop();
LogOptimizationResults(optimizedSolution, executionStopwatch.ElapsedMilliseconds, context,
taskCount <= 20 && personnelCount <= 10);
// 第三步:执行后续处理流程
await ExecutePostOptimizationProcessingAsync(optimizedSolution, context, result);
// 第四步:构建最终结果
BuildFinalResult(optimizedSolution, result, metrics, executionStopwatch.ElapsedMilliseconds);
return result;
}
catch (Exception ex)
{
executionStopwatch.Stop();
_logger.LogError(ex, "💥 全局优化执行异常,耗时:{ElapsedMs}ms", executionStopwatch.ElapsedMilliseconds);
return CreateErrorResult(ex.Message);
}
}
#endregion
#region 验证和统计方法
///
/// 验证预筛选结果的有效性
///
private bool ValidatePrefilterResults(GlobalAllocationContext context, GlobalAllocationResult result)
{
if (!context.PrefilterResults.Any())
{
_logger.LogError("❌ 无预筛选结果!无法进行遗传算法优化");
result.IsSuccess = false;
result.AllocationSummary = "预筛选阶段未找到可行的任务-人员组合";
return false;
}
return true;
}
///
/// 记录预筛选统计信息
///
private void LogPrefilterStatistics(GlobalAllocationContext context)
{
var totalCombinations = context.Tasks.Count * context.AvailablePersonnel.Count;
var feasibleCount = context.PrefilterResults.Count(p => p.Value.IsFeasible);
var feasibilityRate = feasibleCount / (double)Math.Max(context.PrefilterResults.Count, 1);
_logger.LogInformation("📊 预筛选统计 - 总组合:{TotalCombinations},可行组合:{FeasibleCount},可行率:{FeasibilityRate:P2}",
totalCombinations, feasibleCount, feasibilityRate);
}
///
/// 记录优化结果统计
///
private void LogOptimizationResults(GlobalOptimizedSolution optimizedSolution, long elapsedMs, GlobalAllocationContext context, bool isLinearProgramming = false)
{
if (isLinearProgramming)
{
_logger.LogInformation("🎯 线性规划完成 - 耗时:{ElapsedMs}ms,目标函数值:{BestFitness:F2},约束满足率:{ConstraintRate:P2}",
elapsedMs, optimizedSolution.BestFitness, optimizedSolution.ConstraintSatisfactionRate);
}
else
{
_logger.LogInformation("🎯 遗传算法完成 - 耗时:{ElapsedMs}ms,执行代数:{ActualGens}/{MaxGens},最佳适应度:{BestFitness:F2},约束满足率:{ConstraintRate:P2}",
elapsedMs, optimizedSolution.ActualGenerations, context.Config.MaxGenerations,
optimizedSolution.BestFitness, optimizedSolution.ConstraintSatisfactionRate);
}
}
#endregion
#region 后续处理流程
///
/// 执行优化后的处理流程
/// 包括:公平性分析 → 智能协商 → 业务规则验证
///
private async Task ExecutePostOptimizationProcessingAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
GlobalAllocationResult result)
{
// 公平性分析
await ExecuteFairnessAnalysisAsync(optimizedSolution, result);
// 智能协商
//await ExecuteIntelligentNegotiationAsync(optimizedSolution, context, result);
// 最终业务规则验证
//await ExecuteFinalValidationAsync(optimizedSolution, context, result);
}
///
/// 执行公平性分析
///
private async Task ExecuteFairnessAnalysisAsync(GlobalOptimizedSolution optimizedSolution, GlobalAllocationResult result)
{
await Task.CompletedTask; // 保持异步接口
_logger.LogInformation("📈 第3步:计算公平性分析");
var fairnessAnalysis = CalculateWorkloadFairness(optimizedSolution);
_logger.LogInformation("📊 公平性分析完成 - 基尼系数:{GiniCoeff:F3}", fairnessAnalysis.GiniCoefficient);
result.FairnessAnalysis = fairnessAnalysis;
}
///
/// 执行智能协商 - 完整的冲突检测与解决方案引擎
/// 【业务价值】:通过智能冲突检测和多策略协商,确保遗传算法结果符合业务规则
/// 【核心逻辑】:分层优先级处理、多维度冲突检测、智能决策选择最优解决方案
/// 【深度思考】:协商成功率直接影响最终分配质量,必须兼顾效率和准确性
/// 【技术特色】:利用预加载数据、并行检测、缓存优化实现高性能智能协商
///
/// 遗传算法优化后的解决方案
/// 全局分配上下文,包含所有必要的缓存数据
/// 最终分配结果,用于存储协商操作和冲突检测信息
/// 异步任务
private async Task ExecuteIntelligentNegotiationAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
GlobalAllocationResult result)
{
var negotiationStartTime = DateTime.Now;
var negotiationActions = new List();
var conflictDetections = new List();
try
{
_logger.LogInformation("🤝 第4步:执行智能协商处理冲突 - 分析{TaskCount}个任务分配",
optimizedSolution.BestSolution?.Count ?? 0);
// 【前置验证】检查输入数据有效性
if (optimizedSolution?.BestSolution == null || !optimizedSolution.BestSolution.Any())
{
_logger.LogWarning("⚠️ 智能协商跳过 - 无有效的遗传算法分配方案");
await CompleteNegotiationWithEmptyResult(result, negotiationActions, conflictDetections);
return;
}
// 【第一阶段】全面冲突检测 - 识别所有类型的约束冲突
_logger.LogInformation("🔍 阶段1:全面冲突检测");
await ExecuteComprehensiveConflictDetectionAsync(optimizedSolution, context, conflictDetections);
// 【第二阶段】冲突分析与优先级排序
_logger.LogInformation("📊 阶段2:冲突分析与优先级排序");
var prioritizedConflicts = AnalyzeAndPrioritizeConflicts(conflictDetections);
// 【第三阶段】智能解决方案生成与执行
_logger.LogInformation("💡 阶段3:智能解决方案生成");
await ExecuteIntelligentResolutionStrategiesAsync(
prioritizedConflicts, optimizedSolution, context, negotiationActions, conflictDetections);
// 【第四阶段】协商结果验证与优化
_logger.LogInformation("✅ 阶段4:协商结果验证");
await ValidateNegotiationResultsAsync(optimizedSolution, context, negotiationActions, conflictDetections);
// 【结果统计与性能分析】
var negotiationDuration = DateTime.Now - negotiationStartTime;
LogNegotiationResults(negotiationActions, conflictDetections, negotiationDuration);
// 【最终结果封装】
await CompleteNegotiationWithResults(result, negotiationActions, conflictDetections);
}
catch (Exception ex)
{
var negotiationDuration = DateTime.Now - negotiationStartTime;
_logger.LogError(ex, "💥 智能协商异常 - 执行时间:{Duration}ms", negotiationDuration.TotalMilliseconds);
// 【异常处理】创建异常信息记录,确保系统稳定性
var errorConflict = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.LoadImbalance, // 使用通用冲突类型
TaskId = 0,
PersonnelId = 0,
Severity = GlobalConflictSeverity.High,
Description = $"智能协商执行异常: {ex.Message}",
IsResolved = false
};
conflictDetections.Add(errorConflict);
await CompleteNegotiationWithResults(result, negotiationActions, conflictDetections);
}
}
///
/// 执行全面冲突检测 - 多维度并行检测所有潜在冲突
/// 【业务逻辑】:整合班次规则、资质匹配、时间约束、负载均衡等多个维度进行全面检测
/// 【性能优化】:利用预加载缓存和并行检测提升检测效率
/// 【深度思考】:每种冲突类型都有其业务优先级,必须确保检测的完整性和准确性
///
/// 遗传算法优化解决方案
/// 全局分配上下文
/// 冲突检测结果列表
private async Task ExecuteComprehensiveConflictDetectionAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
var detectionTasks = new List();
// 【并行检测1】班次规则冲突检测 - 最重要的约束检测
detectionTasks.Add(DetectShiftRuleConflictsAsync(optimizedSolution, context, conflictDetections));
// 【并行检测2】资质匹配冲突检测 - 确保人员技能符合任务要求
detectionTasks.Add(DetectQualificationMismatchesAsync(optimizedSolution, context, conflictDetections));
// 【并行检测3】时间不可用冲突检测 - 人员请假、不可用时间冲突
detectionTasks.Add(DetectTimeUnavailabilityConflictsAsync(optimizedSolution, context, conflictDetections));
// 【并行检测4】工作负载超限检测 - 防止人员工作量过载
detectionTasks.Add(DetectWorkLimitExceededConflictsAsync(optimizedSolution, context, conflictDetections));
// 【并行检测5】负载不均衡检测 - 基于公平性分析的负载平衡检查
detectionTasks.Add(DetectLoadImbalanceConflictsAsync(optimizedSolution, context, conflictDetections));
// 【等待所有检测完成】确保所有维度的冲突都被识别
await Task.WhenAll(detectionTasks);
_logger.LogInformation("🔍 全面冲突检测完成 - 共发现{ConflictCount}个冲突", conflictDetections.Count);
}
///
/// 检测班次规则冲突 - 利用ShiftRuleValidationEngine进行深度验证
/// 【业务关键】:班次规则是最重要的硬约束,违反会导致排班不可执行
/// 【深度整合】:调用现有的ShiftRuleValidationEngine,确保验证逻辑的一致性
///
private async Task DetectShiftRuleConflictsAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
try
{
_logger.LogDebug("🔍 开始班次规则冲突检测");
// 【创建班次规则验证引擎】使用现有的成熟验证逻辑
// 注意:由于Logger类型不匹配,这里先注释掉实际的引擎调用
// var shiftRuleEngine = new ShiftRuleValidationEngine(_logger, null, context);
var shiftRuleConflictCount = 0;
// 【逐个任务验证】对每个分配的任务进行班次规则验证
foreach (var allocation in optimizedSolution.BestSolution)
{
var taskId = allocation.Key;
var personnelId = allocation.Value;
// 【获取任务信息】从上下文中获取任务详情
var currentTask = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (currentTask == null)
{
_logger.LogWarning("⚠️ 任务{TaskId}信息不存在,跳过班次规则检测", taskId);
continue;
}
// 【构建批次上下文】创建其他相关任务的上下文(排除当前任务)
var batchContext = optimizedSolution.BestSolution
.Where(kvp => kvp.Value == personnelId && kvp.Key != taskId)
.Select(kvp => context.Tasks.FirstOrDefault(t => t.Id == kvp.Key))
.Where(t => t != null)
.ToList();
// 【执行班次规则验证】调用成熟的验证引擎
try
{
// 注意:这里简化处理,实际应该传入IShiftService实例
// var ruleViolations = await shiftRuleEngine.ValidateShiftRulesWithEnhancedBatchContextAsync(
// personnelId, currentTask, batchContext);
// 【临时实现】创建模拟的规则冲突检测,后续需要完整整合
var ruleViolations = await SimulateShiftRuleValidation(personnelId, currentTask, batchContext, context);
// 【转换冲突格式】将规则违规转换为标准冲突检测格式
foreach (var violation in ruleViolations)
{
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = DetermineConflictTypeFromViolation(violation),
TaskId = taskId,
PersonnelId = personnelId,
Severity = DetermineConflictSeverity(violation),
Description = $"班次规则冲突: {violation}",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
shiftRuleConflictCount++;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "⚠️ 任务{TaskId}人员{PersonnelId}班次规则检测异常", taskId, personnelId);
// 【异常处理】创建异常冲突记录
var errorConflict = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.NextDayRestViolation,
TaskId = taskId,
PersonnelId = personnelId,
Severity = GlobalConflictSeverity.Medium,
Description = $"班次规则验证异常: {ex.Message}",
IsResolved = false
};
conflictDetections.Add(errorConflict);
}
}
_logger.LogInformation("🔍 班次规则冲突检测完成 - 发现{ConflictCount}个冲突", shiftRuleConflictCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 班次规则冲突检测整体异常");
}
}
///
/// 模拟班次规则验证 - 临时实现,后续需要完整整合ShiftRuleValidationEngine
/// 【临时方案】:由于依赖注入的复杂性,先提供基础的规则检测逻辑
/// 【TODO】:完整整合ShiftRuleValidationEngine的依赖注入
///
private async Task> SimulateShiftRuleValidation(
long personnelId,
WorkOrderEntity currentTask,
List batchContext,
GlobalAllocationContext context)
{
var violations = new List();
await Task.CompletedTask; // 保持异步接口
try
{
// 【基础检查】班次ID有效性
if (!currentTask.ShiftId.HasValue)
{
violations.Add($"任务{currentTask.WorkOrderCode}缺少班次ID");
return violations;
}
var currentDate = currentTask.WorkOrderDate.Date;
var currentShiftId = currentTask.ShiftId.Value;
// 【简化的班次规则检查】检查同一天是否有冲突的班次安排
var sameDayTasks = batchContext
.Where(t => t.WorkOrderDate.Date == currentDate)
.Where(t => t.ShiftId.HasValue)
.ToList();
if (sameDayTasks.Any())
{
// 【模拟冲突】假设存在班次冲突的情况
var conflictTasks = sameDayTasks.Where(t => t.ShiftId != currentShiftId).ToList();
foreach (var conflictTask in conflictTasks)
{
violations.Add($"同日班次冲突: 任务{currentTask.WorkOrderCode}与{conflictTask.WorkOrderCode}存在班次安排冲突");
}
}
// 【连续工作天数检查】简化版本的连续天数计算
var personnelTasks = batchContext
.Where(t => Math.Abs((t.WorkOrderDate.Date - currentDate).Days) <= 7)
.OrderBy(t => t.WorkOrderDate)
.ToList();
if (personnelTasks.Count >= 7)
{
violations.Add($"连续工作天数超限: 人员{personnelId}在7天内安排了{personnelTasks.Count + 1}个任务");
}
return violations;
}
catch (Exception ex)
{
_logger.LogError(ex, "模拟班次规则验证异常");
return new List { $"班次规则验证异常: {ex.Message}" };
}
}
///
/// 检测资质匹配冲突 - 确保人员技能符合任务要求
/// 【业务逻辑】:利用预加载的人员资质缓存,快速验证技能匹配度
///
private async Task DetectQualificationMismatchesAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
await Task.CompletedTask; // 保持异步接口
try
{
_logger.LogDebug("🔍 开始资质匹配冲突检测");
var qualificationConflictCount = 0;
foreach (var allocation in optimizedSolution.BestSolution)
{
var taskId = allocation.Key;
var personnelId = allocation.Value;
// 【获取任务资质要求】从上下文获取任务信息
var currentTask = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (currentTask == null) continue;
// 【获取人员资质】从缓存获取人员资质信息
if (context.PersonnelQualificationsCache.TryGetValue(personnelId, out var personnelQualifications))
{
// 【资质匹配检查】检查人员是否具备任务所需的基本资质
var hasRequiredQualifications = ValidatePersonnelQualifications(
personnelQualifications, currentTask);
if (!hasRequiredQualifications)
{
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.QualificationMismatch,
TaskId = taskId,
PersonnelId = personnelId,
Severity = GlobalConflictSeverity.Critical, // 资质不匹配是严重问题
Description = $"人员资质不匹配: 人员{personnelId}不具备任务{currentTask.WorkOrderCode}所需的基本资质",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
qualificationConflictCount++;
}
}
else
{
// 【缓存未命中】记录为资质信息缺失
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.QualificationMismatch,
TaskId = taskId,
PersonnelId = personnelId,
Severity = GlobalConflictSeverity.High,
Description = $"人员资质信息缺失: 无法验证人员{personnelId}的资质情况",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
qualificationConflictCount++;
}
}
_logger.LogInformation("🔍 资质匹配冲突检测完成 - 发现{ConflictCount}个冲突", qualificationConflictCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 资质匹配冲突检测异常");
}
}
///
/// 检测时间不可用冲突 - 人员请假、培训等不可用时间冲突
/// 【业务逻辑】:利用班次不可用性缓存,快速识别时间冲突
///
private async Task DetectTimeUnavailabilityConflictsAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
await Task.CompletedTask; // 保持异步接口
try
{
_logger.LogDebug("🔍 开始时间不可用冲突检测");
var timeConflictCount = 0;
foreach (var allocation in optimizedSolution.BestSolution)
{
var taskId = allocation.Key;
var personnelId = allocation.Value;
var currentTask = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (currentTask?.ShiftId == null) continue;
// 【构建不可用性检查键】
var dateShiftKey = $"{currentTask.WorkOrderDate:yyyy-MM-dd}_{currentTask.ShiftId}";
// 【检查不可用性缓存】
if (context.DateShiftUnavailablePersonnel.TryGetValue(dateShiftKey, out var unavailablePersonnel))
{
if (unavailablePersonnel.Contains(personnelId))
{
// 【获取详细不可用信息】
var detailKey = $"{currentTask.WorkOrderDate:yyyy-MM-dd}_{currentTask.ShiftId}_{personnelId}";
var unavailabilityReason = "时间不可用";
if (context.UnavailabilityDetails.TryGetValue(detailKey, out var detailInfo))
{
unavailabilityReason = GetUnavailabilityReasonText(detailInfo.ReasonType);
}
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.TimeUnavailable,
TaskId = taskId,
PersonnelId = personnelId,
Severity = DetermineUnavailabilitySeverity(detailInfo?.ReasonType ?? 1),
Description = $"时间不可用冲突: 人员{personnelId}在{currentTask.WorkOrderDate:yyyy-MM-dd}班次{currentTask.ShiftId}不可用({unavailabilityReason})",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
timeConflictCount++;
}
}
}
_logger.LogInformation("🔍 时间不可用冲突检测完成 - 发现{ConflictCount}个冲突", timeConflictCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 时间不可用冲突检测异常");
}
}
///
/// 检测工作限制超出冲突 - 人员工作量、连续工作天数等限制
///
private async Task DetectWorkLimitExceededConflictsAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
await Task.CompletedTask; // 保持异步接口
try
{
_logger.LogDebug("🔍 开始工作限制超出冲突检测");
var workLimitConflictCount = 0;
// 【按人员分组检查】统计每个人员的工作安排
var personnelWorkloads = optimizedSolution.BestSolution.GroupBy(kvp => kvp.Value);
foreach (var personnelGroup in personnelWorkloads)
{
var personnelId = personnelGroup.Key;
var assignedTasks = personnelGroup.Select(g => g.Key).ToList();
// 【获取人员工作限制】
if (context.PersonnelWorkLimitsRuleCache.TryGetValue(personnelId, out var workLimit))
{
// 【检查周任务限制】
if (workLimit.MaxShiftsPerWeek.HasValue &&
assignedTasks.Count > workLimit.MaxShiftsPerWeek.Value)
{
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.WorkLimitExceeded,
TaskId = assignedTasks.First(), // 使用第一个任务ID作为代表
PersonnelId = personnelId,
Severity = GlobalConflictSeverity.High,
Description = $"周任务限制超出: 人员{personnelId}分配了{assignedTasks.Count}个任务,超过限制{workLimit.MaxShiftsPerWeek}个",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
workLimitConflictCount++;
}
}
}
_logger.LogInformation("🔍 工作限制超出冲突检测完成 - 发现{ConflictCount}个冲突", workLimitConflictCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 工作限制超出冲突检测异常");
}
}
///
/// 检测负载不均衡冲突 - 基于公平性分析识别负载分配问题
///
private async Task DetectLoadImbalanceConflictsAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List conflictDetections)
{
await Task.CompletedTask; // 保持异步接口
try
{
_logger.LogDebug("🔍 开始负载不均衡冲突检测");
// 【利用公平性分析】从现有的公平性分析结果判断负载均衡情况
var fairnessAnalysis = CalculateWorkloadFairness(optimizedSolution);
// 【不均衡阈值检查】基尼系数过高表示负载不均衡
if (fairnessAnalysis.GiniCoefficient > 0.4) // 0.4以上认为不够公平
{
// 【识别负载最高和最低的人员】
var workloads = fairnessAnalysis.PersonnelWorkloads.Values.ToList();
if (workloads.Any())
{
var maxWorkload = workloads.OrderByDescending(w => w.EstimatedTotalHours).First();
var minWorkload = workloads.OrderBy(w => w.EstimatedTotalHours).First();
// 【创建负载不均衡冲突记录】
var conflictInfo = new GlobalConflictDetectionInfo
{
ConflictType = GlobalConflictType.LoadImbalance,
TaskId = maxWorkload.AssignedTaskIds.FirstOrDefault(),
PersonnelId = maxWorkload.PersonnelId,
Severity = fairnessAnalysis.GiniCoefficient > 0.5 ?
GlobalConflictSeverity.High : GlobalConflictSeverity.Medium,
Description = $"负载不均衡: 基尼系数{fairnessAnalysis.GiniCoefficient:F3},最高负载{maxWorkload.EstimatedTotalHours}h,最低负载{minWorkload.EstimatedTotalHours}h",
IsResolved = false
};
conflictDetections.Add(conflictInfo);
_logger.LogInformation("🔍 检测到负载不均衡 - 基尼系数:{Gini:F3}", fairnessAnalysis.GiniCoefficient);
}
}
_logger.LogInformation("🔍 负载不均衡冲突检测完成");
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 负载不均衡冲突检测异常");
}
}
///
/// 业务规则验证
///
private async Task ExecuteFinalValidationAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
GlobalAllocationResult result)
{
_logger.LogInformation("✅ 第5步:执行最终业务规则验证");
// 这里应该调用实际的验证逻辑
// 为了保持代码整洁,这里创建一个默认通过的结果
var finalValidationResult = new FinalValidationResult
{
IsValid = true,
ErrorMessage = null,
Violations = new List()
};
if (!finalValidationResult.IsValid)
{
await HandleValidationFailureAsync(finalValidationResult, result);
}
else
{
_logger.LogInformation("✅ 最终业务规则验证通过");
}
}
///
/// 处理验证失败的情况
///
private async Task HandleValidationFailureAsync(FinalValidationResult validationResult, GlobalAllocationResult result)
{
await Task.CompletedTask; // 保持异步接口
_logger.LogError("❌ 最终业务规则验证失败:{ErrorMessage}", validationResult.ErrorMessage);
_logger.LogError("🚨 验证失败详情 - 违规项数:{ViolationCount}", validationResult.Violations?.Count ?? 0);
var criticalViolations = validationResult.Violations?
.Where(v => v.Severity == GlobalConflictSeverity.Critical).ToList() ?? new List();
if (criticalViolations.Count > 0)
{
_logger.LogError("🚨 发现{CriticalCount}个严重违规,标记为失败", criticalViolations.Count);
result.IsSuccess = false;
result.AllocationSummary = $"分配结果存在严重业务规则违规:{validationResult.ErrorMessage}";
}
else
{
_logger.LogWarning("⚠️ 发现非严重违规,继续处理并记录警告");
}
if (result.ConflictDetections == null)
result.ConflictDetections = new List();
result.ConflictDetections.AddRange(validationResult.Violations);
}
#endregion
#region 结果构建方法
///
/// 构建最终分配结果
///
private void BuildFinalResult(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationResult result,
GlobalOptimizationMetrics metrics,
long elapsedMs)
{
_logger.LogInformation("🏗️ 第6步:构建最终分配结果");
// 评估整体成功性
var hasCriticalViolations = result.ConflictDetections?.Any(v => v.Severity == GlobalConflictSeverity.Critical) ?? false;
var hasValidSolution = optimizedSolution?.BestSolution?.Any() ?? false;
result.IsSuccess = optimizedSolution.IsValid && hasValidSolution && !hasCriticalViolations;
_logger.LogInformation("📊 分配结果评估 - 算法有效:{AlgorithmValid}, 方案存在:{HasSolution}, 严重违规:{HasCritical}, 最终成功:{FinalSuccess}",
optimizedSolution.IsValid, hasValidSolution, hasCriticalViolations, result.IsSuccess);
// 转换解决方案
result.SuccessfulMatches = ConvertToTaskPersonnelMatches(optimizedSolution.BestSolution);
result.FailedAllocations = ConvertToFailedAllocations(optimizedSolution.FailedTasks);
_logger.LogInformation("🎉 分配结果构建完成 - 成功:{IsSuccess},匹配数:{MatchCount}",
result.IsSuccess, result.SuccessfulMatches?.Count ?? 0);
// 设置性能指标
SetPerformanceMetrics(result, metrics, optimizedSolution, elapsedMs);
}
///
/// 设置性能指标
///
private void SetPerformanceMetrics(
GlobalAllocationResult result,
GlobalOptimizationMetrics metrics,
GlobalOptimizedSolution optimizedSolution,
long elapsedMs)
{
metrics.ExecutionTimeMs = elapsedMs;
metrics.ActualGenerations = optimizedSolution.ActualGenerations;
metrics.BestFitnessScore = optimizedSolution.BestFitness;
metrics.ConstraintSatisfactionRate = optimizedSolution.ConstraintSatisfactionRate;
result.OptimizationMetrics = metrics;
// 生成分配摘要
result.AllocationSummary = result.IsSuccess
? GenerateSuccessfulAllocationSummary(result, metrics)
: GenerateFailedAllocationSummary(result);
}
#endregion
#region 工具方法
///
/// 计算工作负载公平性 - 基尼系数计算
/// 业务逻辑深度思考:
/// 1. 公平性是智能调度的核心目标之一,必须确保没有个别人员承担过重或过轻的工作负载
/// 2. 基尼系数是衡量分配不均匀程度的标准经济学指标,值越接近0表示分配越均匀
/// 3. 需要综合考虑任务数量、预估工时、任务复杂度等多个维度的负载分布
/// 4. 边界情况处理:无分配方案、单一人员、所有人员负载相同等场景
/// 5. 业务场景覆盖:不同技能等级人员的负载能力差异、特殊时段的工作强度调整
///
/// 遗传算法优化后的解决方案,包含任务-人员分配映射和人员负载分布
/// 完整的工作负载公平性分析结果,包括基尼系数、人员负载详情、公平性等级
private GlobalWorkloadFairnessAnalysis CalculateWorkloadFairness(GlobalOptimizedSolution optimizedSolution)
{
try
{
_logger.LogDebug("📊 开始计算工作负载公平性分析");
// 边界情况检查:无有效分配方案
if (optimizedSolution?.BestSolution == null || !optimizedSolution.BestSolution.Any())
{
_logger.LogWarning("⚠️ 无有效分配方案,返回默认公平性分析");
return CreateDefaultFairnessAnalysis("无有效分配方案");
}
// 第一步:构建人员工作负载分布数据
var personnelWorkloads = BuildPersonnelWorkloadDistribution(optimizedSolution);
// 边界情况检查:无人员负载数据
if (!personnelWorkloads.Any())
{
_logger.LogWarning("⚠️ 无人员负载数据,返回默认公平性分析");
return CreateDefaultFairnessAnalysis("无人员负载数据");
}
// 第二步:提取工作负载值用于统计计算
var workloadValues = ExtractWorkloadValues(personnelWorkloads);
// 第三步:计算基尼系数 - 核心公平性指标
var giniCoefficient = CalculateGiniCoefficient(workloadValues);
// 第四步:计算其他统计指标
var statistics = CalculateWorkloadStatistics(workloadValues);
// 第五步:确定公平性等级
var fairnessLevel = DetermineFairnessLevel(giniCoefficient);
// 第六步:构建完整的公平性分析结果
var result = new GlobalWorkloadFairnessAnalysis
{
GiniCoefficient = giniCoefficient,
PersonnelWorkloads = personnelWorkloads,
FairnessLevel = fairnessLevel,
WorkloadStandardDeviation = statistics.StandardDeviation,
MaxWorkloadDifference = statistics.MaxDifference
};
// 记录详细的计算结果用于业务分析
LogFairnessAnalysisResults(result, personnelWorkloads.Count, workloadValues);
_logger.LogDebug("✅ 工作负载公平性分析计算完成");
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, "💥 计算工作负载公平性时发生异常");
return CreateDefaultFairnessAnalysis($"计算异常:{ex.Message}");
}
}
///
/// 构建人员工作负载分布数据
/// 业务思考:需要综合考虑任务数量、工时、复杂度等多维度因素
///
private Dictionary BuildPersonnelWorkloadDistribution(
GlobalOptimizedSolution optimizedSolution)
{
var personnelWorkloads = new Dictionary();
// 方案一:优先使用遗传算法已计算的负载分布(性能最优)
if (optimizedSolution.PersonnelWorkloadDistribution?.Any() == true)
{
_logger.LogDebug("📈 使用遗传算法预计算的负载分布数据");
foreach (var kvp in optimizedSolution.PersonnelWorkloadDistribution)
{
var personnelId = kvp.Key;
var totalWorkload = kvp.Value;
// 获取该人员分配的任务ID列表
var assignedTasks = optimizedSolution.BestSolution
.Where(s => s.Value == personnelId)
.Select(s => s.Key)
.ToList();
personnelWorkloads[personnelId] = new GlobalPersonnelWorkloadInfo
{
PersonnelId = personnelId,
PersonnelName = GetPersonnelName(personnelId),
AssignedTaskCount = assignedTasks.Count,
EstimatedTotalHours = totalWorkload,
AssignedTaskIds = assignedTasks,
// 工作负载百分比将在后续统一计算
WorkloadPercentage = 0
};
}
}
else
{
// 方案二:基于任务分配重新计算负载(fallback方案)
_logger.LogDebug("🔄 基于任务分配重新计算人员负载分布");
var personnelTaskGroups = optimizedSolution.BestSolution.GroupBy(kvp => kvp.Value);
foreach (var group in personnelTaskGroups)
{
var personnelId = group.Key;
var assignedTasks = group.Select(g => g.Key).ToList();
// 使用默认工时估算(实际项目中应该从任务实体获取)
var estimatedHours = assignedTasks.Count * 8.0m; // 假设每个任务8小时
personnelWorkloads[personnelId] = new GlobalPersonnelWorkloadInfo
{
PersonnelId = personnelId,
PersonnelName = GetPersonnelName(personnelId),
AssignedTaskCount = assignedTasks.Count,
EstimatedTotalHours = estimatedHours,
AssignedTaskIds = assignedTasks,
WorkloadPercentage = 0 // 将在后续计算
};
}
}
// 计算工作负载百分比(相对于最大负载的比例)
if (personnelWorkloads.Any())
{
var maxWorkload = personnelWorkloads.Values.Max(p => p.EstimatedTotalHours);
if (maxWorkload > 0)
{
foreach (var workload in personnelWorkloads.Values)
{
workload.WorkloadPercentage = (double)(workload.EstimatedTotalHours / maxWorkload) * 100;
}
}
}
_logger.LogDebug("📋 人员负载分布构建完成,共{Count}个人员", personnelWorkloads.Count);
return personnelWorkloads;
}
///
/// 提取工作负载数值用于统计计算
///
private List ExtractWorkloadValues(Dictionary personnelWorkloads)
{
return personnelWorkloads.Values
.Select(p => p.EstimatedTotalHours)
.OrderBy(x => x)
.ToList();
}
///
/// 计算基尼系数 - 标准经济学算法实现
/// 数学原理:基尼系数 = (2 * Σ(i * Xi)) / (n * Σ(Xi)) - (n+1) / n
/// 其中 Xi 为排序后的第i个数值,i为排序位置,n为总数量
/// 业务意义:0表示完全均匀分配,1表示完全不均匀分配(所有负载集中在一个人)
///
private double CalculateGiniCoefficient(List workloadValues)
{
if (!workloadValues.Any())
{
_logger.LogWarning("⚠️ 工作负载数据为空,基尼系数设为0");
return 0;
}
// 边界情况:只有一个人员
if (workloadValues.Count == 1)
{
_logger.LogDebug("📌 只有一个人员,基尼系数设为0(完全公平)");
return 0;
}
var n = workloadValues.Count;
var sortedValues = workloadValues.OrderBy(x => x).ToArray();
// 边界情况:所有负载值相同
if (sortedValues.All(x => x == sortedValues[0]))
{
_logger.LogDebug("📌 所有人员负载相同,基尼系数为0(完全公平)");
return 0;
}
// 标准基尼系数计算公式
double numerator = 0;
for (int i = 0; i < n; i++)
{
// 公式中的 (2*i + 1 - n) * Xi 部分
numerator += (2 * (i + 1) - n - 1) * (double)sortedValues[i];
}
var mean = sortedValues.Average(x => (double)x);
if (mean == 0)
{
_logger.LogWarning("⚠️ 平均负载为0,基尼系数设为0");
return 0;
}
var giniCoefficient = numerator / (n * n * mean);
// 确保基尼系数在有效范围内 [0, 1]
giniCoefficient = Math.Max(0, Math.Min(1, giniCoefficient));
_logger.LogDebug("🧮 基尼系数计算完成:{Gini:F4},样本数:{Count},平均值:{Mean:F2}",
giniCoefficient, n, mean);
return giniCoefficient;
}
///
/// 计算工作负载统计指标
///
private (double StandardDeviation, decimal MaxDifference) CalculateWorkloadStatistics(List workloadValues)
{
if (!workloadValues.Any())
{
return (0, 0);
}
// 计算标准差
var mean = workloadValues.Average(x => (double)x);
var variance = workloadValues.Average(x => Math.Pow((double)x - mean, 2));
var standardDeviation = Math.Sqrt(variance);
// 计算最大差异
var maxWorkload = workloadValues.Max();
var minWorkload = workloadValues.Min();
var maxDifference = maxWorkload - minWorkload;
_logger.LogDebug("📊 统计指标 - 标准差:{StdDev:F2},最大差异:{MaxDiff:F2}",
standardDeviation, maxDifference);
return (standardDeviation, maxDifference);
}
///
/// 根据基尼系数确定公平性等级
/// 业务规则:基于经济学中收入分配不平等程度的标准划分
///
private GlobalFairnessLevel DetermineFairnessLevel(double giniCoefficient)
{
// 使用标准的基尼系数分级标准
return giniCoefficient switch
{
< 0.2 => GlobalFairnessLevel.VeryFair, // 非常公平
< 0.3 => GlobalFairnessLevel.Fair, // 相对公平
< 0.4 => GlobalFairnessLevel.Moderate, // 一般公平
< 0.5 => GlobalFairnessLevel.Unfair, // 不够公平
_ => GlobalFairnessLevel.VeryUnfair // 很不公平
};
}
///
/// 创建默认公平性分析结果(用于异常情况)
///
private GlobalWorkloadFairnessAnalysis CreateDefaultFairnessAnalysis(string reason)
{
_logger.LogWarning("🔄 创建默认公平性分析,原因:{Reason}", reason);
return new GlobalWorkloadFairnessAnalysis
{
GiniCoefficient = 0.0, // 默认为完全公平
PersonnelWorkloads = new Dictionary(),
FairnessLevel = GlobalFairnessLevel.VeryFair,
WorkloadStandardDeviation = 0.0,
MaxWorkloadDifference = 0.0m
};
}
///
/// 记录公平性分析结果的详细日志
///
private void LogFairnessAnalysisResults(
GlobalWorkloadFairnessAnalysis result,
int personnelCount,
List workloadValues)
{
var avgWorkload = workloadValues.Any() ? workloadValues.Average() : 0;
var minWorkload = workloadValues.Any() ? workloadValues.Min() : 0;
var maxWorkload = workloadValues.Any() ? workloadValues.Max() : 0;
_logger.LogInformation(
"📈 公平性分析详情 - 基尼系数:{Gini:F4},公平性:{Level},人员数:{Count}," +
"平均负载:{Avg:F1}h,负载范围:{Min:F1}h~{Max:F1}h,标准差:{StdDev:F2}",
result.GiniCoefficient,
result.FairnessLevel,
personnelCount,
avgWorkload,
minWorkload,
maxWorkload,
result.WorkloadStandardDeviation
);
// 如果公平性较差,记录警告信息供业务分析
if (result.FairnessLevel >= GlobalFairnessLevel.Unfair)
{
_logger.LogWarning("⚠️ 工作负载分配不够公平,建议调整分配策略或增加人员资源");
}
}
///
/// 转换为任务人员匹配列表 - 基于字典格式的解决方案
///
private List ConvertToTaskPersonnelMatches(Dictionary solution)
{
if (solution == null) return new List();
return solution.Select(kvp => new GlobalTaskPersonnelMatch
{
TaskId = kvp.Key,
PersonnelId = kvp.Value,
MatchScore = 85, // 默认匹配分数
PersonnelName = GetPersonnelName(kvp.Value),
MatchReason = "遗传算法全局优化结果"
}).ToList();
}
///
/// 转换为失败分配列表 - 基于任务ID列表
///
private List ConvertToFailedAllocations(List failedTaskIds)
{
if (failedTaskIds == null) return new List();
return failedTaskIds.Select(taskId => new GlobalFailedAllocation
{
TaskId = taskId,
TaskCode = $"WO_{taskId}",
FailureReason = "遗传算法无法找到合适的人员分配",
ConflictDetails = new List
{
"检查人员资质匹配度",
"验证任务时间冲突",
"考虑增加人员池",
"调整任务优先级"
}
}).ToList();
}
///
/// 转换为失败分配列表 - 基于工作任务实体列表
///
private List ConvertToFailedAllocations(List failedTasks)
{
if (failedTasks == null) return new List();
return failedTasks.Select(task => new GlobalFailedAllocation
{
TaskId = task.Id,
TaskCode = task.ProjectNumber ?? $"WO_{task.Id}",
FailureReason = "无法找到合适的人员分配",
ConflictDetails = new List { "检查人员资质要求", "考虑调整任务时间" }
}).ToList();
}
///
/// 获取人员姓名 - 带缓存的人员姓名获取
///
private string GetPersonnelName(long personnelId)
{
if (_personnelNameCache.TryGetValue(personnelId, out var cachedName))
{
return cachedName;
}
// 如果缓存中没有,返回默认格式
var defaultName = $"人员_{personnelId}";
_personnelNameCache[personnelId] = defaultName;
return defaultName;
}
///
/// 设置人员名称缓存
///
public void SetPersonnelNameCache(Dictionary nameMapping)
{
if (nameMapping != null)
{
foreach (var kvp in nameMapping)
{
_personnelNameCache[kvp.Key] = kvp.Value;
}
}
}
///
/// 生成成功分配摘要
///
private string GenerateSuccessfulAllocationSummary(GlobalAllocationResult result, GlobalOptimizationMetrics metrics)
{
var successCount = result.SuccessfulMatches?.Count ?? 0;
var failCount = result.FailedAllocations?.Count ?? 0;
return $"全局优化分配成功完成!成功分配:{successCount}个任务,失败:{failCount}个任务," +
$"执行代数:{metrics.ActualGenerations},最佳适应度:{metrics.BestFitnessScore:F2}," +
$"约束满足率:{metrics.ConstraintSatisfactionRate:P2}";
}
///
/// 生成失败分配摘要
///
private string GenerateFailedAllocationSummary(GlobalAllocationResult result)
{
return result.AllocationSummary ?? "全局优化分配未能成功完成,请检查任务和人员配置";
}
///
/// 创建错误结果
///
private GlobalAllocationResult CreateErrorResult(string errorMessage)
{
return new GlobalAllocationResult
{
IsSuccess = false,
AllocationSummary = $"系统异常:{errorMessage}",
SuccessfulMatches = new List(),
FailedAllocations = new List(),
ConflictDetections = new List()
};
}
#region 智能协商辅助方法
///
/// 分析和优先级排序冲突 - 基于业务影响程度对冲突进行分类排序
/// 【业务逻辑】:将检测到的冲突按照严重程度和业务影响进行分层处理
/// 【深度思考】:不同冲突类型有不同的解决优先级,合理排序有助于提高协商成功率
///
/// 原始冲突检测列表
/// 按优先级排序的冲突分组
private Dictionary> AnalyzeAndPrioritizeConflicts(
List conflictDetections)
{
try
{
_logger.LogDebug("📊 开始冲突分析与优先级排序");
// 【分层分组】按严重程度分组冲突
var prioritizedConflicts = conflictDetections
.GroupBy(c => c.Severity)
.ToDictionary(g => g.Key, g => g.OrderBy(c => GetConflictTypeOrder(c.ConflictType)).ToList());
// 【统计分析】记录各类冲突的分布情况
foreach (var group in prioritizedConflicts)
{
_logger.LogInformation("📊 {Severity}级冲突:{Count}个", group.Key, group.Value.Count);
// 【详细分类统计】按冲突类型进一步统计
var typeGroups = group.Value.GroupBy(c => c.ConflictType);
foreach (var typeGroup in typeGroups)
{
_logger.LogDebug(" └─ {ConflictType}:{Count}个", typeGroup.Key, typeGroup.Count());
}
}
return prioritizedConflicts;
}
catch (Exception ex)
{
_logger.LogError(ex, "冲突分析与优先级排序异常");
return new Dictionary>();
}
}
///
/// 执行智能解决方案策略 - 多策略并行尝试解决冲突
/// 【核心算法】:基于冲突类型和严重程度选择最合适的解决策略
/// 【智能决策】:从人员替换、任务重分配、时间调整等策略中选择最优方案
///
private async Task ExecuteIntelligentResolutionStrategiesAsync(
Dictionary> prioritizedConflicts,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions,
List conflictDetections)
{
try
{
_logger.LogDebug("💡 开始执行智能解决方案策略");
var resolvedConflictCount = 0;
var totalConflictCount = prioritizedConflicts.Values.SelectMany(v => v).Count();
// 【优先处理严重冲突】按严重程度从高到低处理
var severityOrder = new[]
{
GlobalConflictSeverity.Critical,
GlobalConflictSeverity.High,
GlobalConflictSeverity.Medium,
GlobalConflictSeverity.Low,
GlobalConflictSeverity.Warning
};
foreach (var severity in severityOrder)
{
if (!prioritizedConflicts.TryGetValue(severity, out var conflicts) || !conflicts.Any())
continue;
_logger.LogInformation("🔧 处理{Severity}级冲突:{Count}个", severity, conflicts.Count);
// 【逐个冲突处理】为每个冲突尝试找到解决方案
foreach (var conflict in conflicts)
{
var resolutionSuccess = await AttemptConflictResolutionAsync(
conflict, optimizedSolution, context, negotiationActions);
if (resolutionSuccess)
{
conflict.IsResolved = true;
resolvedConflictCount++;
_logger.LogDebug("✅ 冲突已解决:{Description}", conflict.Description);
}
else
{
_logger.LogWarning("❌ 冲突无法自动解决:{Description}", conflict.Description);
// 【人工介入标记】无法自动解决的冲突标记为需要人工介入
var manualAction = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.ManualIntervention,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
Reason = $"自动协商失败,需要人工处理:{conflict.Description}",
IsSuccessful = false
};
negotiationActions.Add(manualAction);
}
}
}
_logger.LogInformation("💡 智能解决方案执行完成 - 解决{ResolvedCount}/{TotalCount}个冲突",
resolvedConflictCount, totalConflictCount);
}
catch (Exception ex)
{
_logger.LogError(ex, "智能解决方案策略执行异常");
}
}
///
/// 尝试解决单个冲突 - 核心的冲突解决逻辑
/// 【策略选择】:根据冲突类型智能选择最适合的解决策略
/// 【深度思考】:每种冲突类型都有其特定的最优解决方案,需要针对性处理
///
private async Task AttemptConflictResolutionAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
try
{
_logger.LogDebug("🔧 尝试解决冲突:{ConflictType} - {Description}", conflict.ConflictType, conflict.Description);
// 【策略选择】基于冲突类型选择解决策略
return conflict.ConflictType switch
{
GlobalConflictType.NextDayRestViolation =>
await ResolveRestViolationConflictAsync(conflict, optimizedSolution, context, negotiationActions),
GlobalConflictType.SameDayShiftContinuity =>
await ResolveShiftContinuityConflictAsync(conflict, optimizedSolution, context, negotiationActions),
GlobalConflictType.QualificationMismatch =>
await ResolveQualificationMismatchAsync(conflict, optimizedSolution, context, negotiationActions),
GlobalConflictType.TimeUnavailable =>
await ResolveTimeUnavailableConflictAsync(conflict, optimizedSolution, context, negotiationActions),
GlobalConflictType.WorkLimitExceeded =>
await ResolveWorkLimitExceededAsync(conflict, optimizedSolution, context, negotiationActions),
GlobalConflictType.LoadImbalance =>
await ResolveLoadImbalanceAsync(conflict, optimizedSolution, context, negotiationActions),
_ => await ResolveGenericConflictAsync(conflict, optimizedSolution, context, negotiationActions)
};
}
catch (Exception ex)
{
_logger.LogError(ex, "冲突解决尝试异常:{ConflictType}", conflict.ConflictType);
return false;
}
}
///
/// 解决休息规则冲突 - 次日休息规则的专门处理策略
///
private async Task ResolveRestViolationConflictAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask; // 保持异步接口
// 【策略1】尝试找到替代人员
var alternativePersonnel = FindAlternativePersonnelForTask(
conflict.TaskId, conflict.PersonnelId, optimizedSolution, context);
if (alternativePersonnel.HasValue)
{
// 【执行人员替换】
optimizedSolution.BestSolution[conflict.TaskId] = alternativePersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.PersonnelReplacement,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = alternativePersonnel.Value,
Reason = "解决次日休息规则冲突",
IsSuccessful = true
};
negotiationActions.Add(action);
_logger.LogInformation("🔄 次日休息冲突已通过人员替换解决:任务{TaskId}从人员{OldPersonnel}替换为{NewPersonnel}",
conflict.TaskId, conflict.PersonnelId, alternativePersonnel.Value);
return true;
}
return false; // 无法找到合适的替代方案
}
///
/// 解决班次连续性冲突 - 同天班次冲突的处理策略
///
private async Task ResolveShiftContinuityConflictAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【策略1】尝试人员替换
var alternativePersonnel = FindAlternativePersonnelForTask(
conflict.TaskId, conflict.PersonnelId, optimizedSolution, context);
if (alternativePersonnel.HasValue)
{
optimizedSolution.BestSolution[conflict.TaskId] = alternativePersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.PersonnelReplacement,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = alternativePersonnel.Value,
Reason = "解决同天班次连续性冲突",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 解决资质不匹配冲突 - 找到具备合适资质的人员
///
private async Task ResolveQualificationMismatchAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【查找有资质的人员】基于任务要求找到合适的人员
var qualifiedPersonnel = FindQualifiedPersonnelForTask(conflict.TaskId, context);
if (qualifiedPersonnel.HasValue)
{
optimizedSolution.BestSolution[conflict.TaskId] = qualifiedPersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.PersonnelReplacement,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = qualifiedPersonnel.Value,
Reason = "解决资质不匹配冲突",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 解决时间不可用冲突 - 找到该时间段可用的人员
///
private async Task ResolveTimeUnavailableConflictAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【查找时间可用的人员】
var availablePersonnel = FindTimeAvailablePersonnelForTask(conflict.TaskId, context);
if (availablePersonnel.HasValue)
{
optimizedSolution.BestSolution[conflict.TaskId] = availablePersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.PersonnelReplacement,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = availablePersonnel.Value,
Reason = "解决时间不可用冲突",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 解决工作限制超出冲突 - 重新分配任务以满足工作量限制
///
private async Task ResolveWorkLimitExceededAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【工作量重分配策略】将部分任务转移给工作量较少的人员
var lightWorkloadPersonnel = FindLightWorkloadPersonnel(optimizedSolution, context);
if (lightWorkloadPersonnel.HasValue)
{
// 【任务转移】将当前冲突任务转移给工作量较少的人员
optimizedSolution.BestSolution[conflict.TaskId] = lightWorkloadPersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.TaskReallocation,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = lightWorkloadPersonnel.Value,
Reason = "解决工作限制超出冲突,均衡工作负载",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 解决负载不均衡冲突 - 通过任务重分配实现负载平衡
///
private async Task ResolveLoadImbalanceAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【负载平衡策略】尝试重新分配部分任务以实现更好的负载平衡
var balancedAllocation = AttemptLoadBalancing(optimizedSolution, context);
if (balancedAllocation)
{
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.TaskReallocation,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
Reason = "通过任务重分配优化负载平衡",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 解决通用冲突 - 其他类型冲突的通用处理策略
///
private async Task ResolveGenericConflictAsync(
GlobalConflictDetectionInfo conflict,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions)
{
await Task.CompletedTask;
// 【通用策略】尝试最基本的人员替换
var alternativePersonnel = FindAlternativePersonnelForTask(
conflict.TaskId, conflict.PersonnelId, optimizedSolution, context);
if (alternativePersonnel.HasValue)
{
optimizedSolution.BestSolution[conflict.TaskId] = alternativePersonnel.Value;
var action = new GlobalNegotiationAction
{
ActionType = GlobalNegotiationActionType.PersonnelReplacement,
TaskId = conflict.TaskId,
OriginalPersonnelId = conflict.PersonnelId,
NewPersonnelId = alternativePersonnel.Value,
Reason = "通用冲突解决策略",
IsSuccessful = true
};
negotiationActions.Add(action);
return true;
}
return false;
}
///
/// 验证协商结果 - 确保协商后的方案仍然满足基本约束
///
private async Task ValidateNegotiationResultsAsync(
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context,
List negotiationActions,
List conflictDetections)
{
await Task.CompletedTask;
try
{
_logger.LogDebug("✅ 开始验证协商结果");
// 【基本一致性检查】确保所有任务都有人员分配
var unassignedTasks = optimizedSolution.BestSolution
.Where(kvp => kvp.Value <= 0)
.Select(kvp => kvp.Key)
.ToList();
if (unassignedTasks.Any())
{
_logger.LogWarning("⚠️ 协商后发现{Count}个未分配任务", unassignedTasks.Count);
}
// 【协商效果评估】计算协商前后的改进情况
var resolvedConflicts = conflictDetections.Count(c => c.IsResolved);
var totalConflicts = conflictDetections.Count;
var resolutionRate = totalConflicts > 0 ? (double)resolvedConflicts / totalConflicts : 0.0;
_logger.LogInformation("✅ 协商结果验证完成 - 解决率:{Rate:P2}({Resolved}/{Total})",
resolutionRate, resolvedConflicts, totalConflicts);
}
catch (Exception ex)
{
_logger.LogError(ex, "协商结果验证异常");
}
}
///
/// 记录协商结果日志 - 详细的协商过程和效果统计
///
private void LogNegotiationResults(
List negotiationActions,
List conflictDetections,
TimeSpan negotiationDuration)
{
try
{
var successfulActions = negotiationActions.Count(a => a.IsSuccessful);
var totalActions = negotiationActions.Count;
var resolvedConflicts = conflictDetections.Count(c => c.IsResolved);
var totalConflicts = conflictDetections.Count;
_logger.LogInformation("🎯 智能协商执行完成统计:");
_logger.LogInformation(" ⏱️ 执行时间:{Duration}ms", negotiationDuration.TotalMilliseconds);
_logger.LogInformation(" 🔧 协商操作:成功{Success}/{Total}个", successfulActions, totalActions);
_logger.LogInformation(" ✅ 冲突解决:{Resolved}/{Total}个(解决率:{Rate:P2})",
resolvedConflicts, totalConflicts, totalConflicts > 0 ? (double)resolvedConflicts / totalConflicts : 0.0);
// 【操作类型统计】
var actionTypeGroups = negotiationActions.GroupBy(a => a.ActionType);
foreach (var group in actionTypeGroups)
{
var successful = group.Count(a => a.IsSuccessful);
var total = group.Count();
_logger.LogInformation(" └─ {ActionType}:{Success}/{Total}个", group.Key, successful, total);
}
// 【冲突类型解决统计】
var conflictTypeGroups = conflictDetections.GroupBy(c => c.ConflictType);
foreach (var group in conflictTypeGroups)
{
var resolved = group.Count(c => c.IsResolved);
var total = group.Count();
_logger.LogInformation(" └─ {ConflictType}冲突:解决{Resolved}/{Total}个", group.Key, resolved, total);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "协商结果日志记录异常");
}
}
///
/// 完成协商并设置空结果 - 无冲突或无有效方案时的处理
///
private async Task CompleteNegotiationWithEmptyResult(
GlobalAllocationResult result,
List negotiationActions,
List conflictDetections)
{
await Task.CompletedTask;
result.NegotiationActions = negotiationActions;
if (result.ConflictDetections == null)
result.ConflictDetections = new List();
result.ConflictDetections.AddRange(conflictDetections);
_logger.LogInformation("🔧 智能协商完成 - 空结果处理");
}
///
/// 完成协商并设置结果 - 正常协商流程完成后的结果设置
///
private async Task CompleteNegotiationWithResults(
GlobalAllocationResult result,
List negotiationActions,
List conflictDetections)
{
await Task.CompletedTask;
result.NegotiationActions = negotiationActions;
if (result.ConflictDetections == null)
result.ConflictDetections = new List();
result.ConflictDetections.AddRange(conflictDetections);
_logger.LogInformation("🔧 智能协商完成 - 执行操作:{ActionCount}个,冲突检测:{ConflictCount}个",
negotiationActions?.Count ?? 0, conflictDetections?.Count ?? 0);
}
#endregion
#region 智能协商辅助工具方法
///
/// 根据违规信息确定冲突类型
///
private GlobalConflictType DetermineConflictTypeFromViolation(string violation)
{
if (violation.Contains("次日休息") || violation.Contains("班后一天"))
return GlobalConflictType.NextDayRestViolation;
if (violation.Contains("同日班次") || violation.Contains("连续"))
return GlobalConflictType.SameDayShiftContinuity;
if (violation.Contains("连续工作天数"))
return GlobalConflictType.WeeklyTaskLimit;
if (violation.Contains("周末") || violation.Contains("跨周"))
return GlobalConflictType.CrossWeekendContinuity;
// 默认返回班次连续性冲突
return GlobalConflictType.SameDayShiftContinuity;
}
///
/// 根据违规信息确定冲突严重程度
///
private GlobalConflictSeverity DetermineConflictSeverity(string violation)
{
if (violation.Contains("异常"))
return GlobalConflictSeverity.High;
if (violation.Contains("超限"))
return GlobalConflictSeverity.Critical;
if (violation.Contains("冲突"))
return GlobalConflictSeverity.High;
return GlobalConflictSeverity.Medium;
}
///
/// 验证人员资质是否满足任务要求
///
private bool ValidatePersonnelQualifications(
List personnelQualifications,
WorkOrderEntity task)
{
// 【简化实现】基础资质验证,实际应根据具体业务需求实现
if (!personnelQualifications.Any())
return false;
// 检查是否有有效的资质(未过期且激活)
var validQualifications = personnelQualifications
.Where(q => q.IsActive)
.Where(q => !q.ExpiryDate.HasValue || q.ExpiryDate.Value > DateTime.Now)
.ToList();
return validQualifications.Any();
}
///
/// 获取不可用性原因文本描述
///
private string GetUnavailabilityReasonText(int reasonType)
{
return reasonType switch
{
1 => "个人意愿",
2 => "培训任务",
3 => "会议任务",
4 => "设备维护",
7 => "临时请假",
8 => "计划请假",
9 => "医疗原因",
10 => "家庭事务",
11 => "轮岗安排",
12 => "技能认证",
_ => "其他原因"
};
}
///
/// 根据不可用原因确定冲突严重程度
///
private GlobalConflictSeverity DetermineUnavailabilitySeverity(int reasonType)
{
return reasonType switch
{
7 or 8 or 9 => GlobalConflictSeverity.Critical, // 请假和医疗是硬约束
4 => GlobalConflictSeverity.High, // 设备维护重要性高
3 or 12 => GlobalConflictSeverity.Medium, // 会议和认证中等重要
_ => GlobalConflictSeverity.Low // 其他较低重要性
};
}
///
/// 获取冲突类型的处理优先级顺序
///
private int GetConflictTypeOrder(GlobalConflictType conflictType)
{
return conflictType switch
{
GlobalConflictType.QualificationMismatch => 1, // 资质问题优先级最高
GlobalConflictType.TimeUnavailable => 2, // 时间不可用次之
GlobalConflictType.NextDayRestViolation => 3, // 休息规则重要
GlobalConflictType.SameDayShiftContinuity => 4, // 班次连续性
GlobalConflictType.WorkLimitExceeded => 5, // 工作限制
GlobalConflictType.WeeklyTaskLimit => 6, // 周限制
GlobalConflictType.CrossWeekendContinuity => 7, // 跨周末连续性
GlobalConflictType.LoadImbalance => 8, // 负载均衡优先级最低
_ => 9 // 其他未知类型
};
}
///
/// 查找任务的替代人员 - 核心的人员替换算法
/// 【业务逻辑】:在可用人员池中找到能够胜任该任务且无冲突的人员
///
private long? FindAlternativePersonnelForTask(
long taskId,
long currentPersonnelId,
GlobalOptimizedSolution optimizedSolution,
GlobalAllocationContext context)
{
try
{
// 【获取任务信息】
var task = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (task == null) return null;
// 【候选人员筛选】从可用人员中排除当前人员
var candidatePersonnel = context.AvailablePersonnel
.Where(p => p.Id != currentPersonnelId && p.IsActive)
.ToList();
// 【逐个检查候选人员】找到第一个无冲突的人员
foreach (var candidate in candidatePersonnel)
{
// 【基础可行性检查】检查预筛选结果
var prefilterKey = $"{taskId}_{candidate.Id}";
if (context.PrefilterResults.TryGetValue(prefilterKey, out var prefilterResult))
{
if (prefilterResult.IsFeasible && prefilterResult.PrefilterScore > 60) // 60分以上才考虑
{
// 【简化冲突检查】检查基本的时间和资质可用性
if (IsPersonnelAvailableForTask(candidate.Id, task, context))
{
return candidate.Id;
}
}
}
}
return null; // 未找到合适的替代人员
}
catch (Exception ex)
{
_logger.LogError(ex, "查找替代人员异常:任务{TaskId}", taskId);
return null;
}
}
///
/// 查找具备资质的人员 - 基于资质匹配的人员查找
///
private long? FindQualifiedPersonnelForTask(long taskId, GlobalAllocationContext context)
{
try
{
var task = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (task == null) return null;
// 【资质匹配查找】在人员资质缓存中查找合适人员
foreach (var personnelQual in context.PersonnelQualificationsCache)
{
var personnelId = personnelQual.Key;
var qualifications = personnelQual.Value;
// 【资质验证】检查是否满足任务资质要求
if (ValidatePersonnelQualifications(qualifications, task))
{
// 【可用性检查】确保人员在该时间段可用
if (IsPersonnelAvailableForTask(personnelId, task, context))
{
return personnelId;
}
}
}
return null;
}
catch (Exception ex)
{
_logger.LogError(ex, "查找有资质人员异常:任务{TaskId}", taskId);
return null;
}
}
///
/// 查找时间可用的人员 - 基于时间可用性的人员查找
///
private long? FindTimeAvailablePersonnelForTask(long taskId, GlobalAllocationContext context)
{
try
{
var task = context.Tasks.FirstOrDefault(t => t.Id == taskId);
if (task?.ShiftId == null) return null;
// 【时间可用性检查】查找在该时间班次可用的人员
var dateShiftKey = $"{task.WorkOrderDate:yyyy-MM-dd}_{task.ShiftId}";
// 【排除不可用人员】获取该时间段不可用的人员列表
var unavailablePersonnel = context.DateShiftUnavailablePersonnel.GetValueOrDefault(dateShiftKey, new HashSet());
// 【查找可用人员】从全部人员中排除不可用的人员
var availablePersonnel = context.AvailablePersonnel
.Where(p => p.IsActive && !unavailablePersonnel.Contains(p.Id))
.FirstOrDefault();
return availablePersonnel?.Id;
}
catch (Exception ex)
{
_logger.LogError(ex, "查找时间可用人员异常:任务{TaskId}", taskId);
return null;
}
}
///
/// 查找工作负载较轻的人员 - 用于负载均衡
///
private long? FindLightWorkloadPersonnel(GlobalOptimizedSolution optimizedSolution, GlobalAllocationContext context)
{
try
{
// 【计算各人员工作负载】
var personnelWorkloads = optimizedSolution.BestSolution
.GroupBy(kvp => kvp.Value)
.ToDictionary(g => g.Key, g => g.Count());
// 【查找最少工作量人员】
var lightestWorkload = personnelWorkloads.Values.Min();
var lightWorkloadPersonnel = personnelWorkloads
.Where(kvp => kvp.Value == lightestWorkload)
.Select(kvp => kvp.Key)
.FirstOrDefault();
return lightWorkloadPersonnel > 0 ? lightWorkloadPersonnel : null;
}
catch (Exception ex)
{
_logger.LogError(ex, "查找轻负载人员异常");
return null;
}
}
///
/// 尝试负载均衡 - 通过任务重分配优化负载分布
///
private bool AttemptLoadBalancing(GlobalOptimizedSolution optimizedSolution, GlobalAllocationContext context)
{
try
{
// 【简化实现】基础的负载均衡逻辑
// 实际项目中需要复杂的负载重分配算法
var personnelWorkloads = optimizedSolution.BestSolution
.GroupBy(kvp => kvp.Value)
.ToDictionary(g => g.Key, g => g.Select(x => x.Key).ToList());
var maxWorkload = personnelWorkloads.Values.Max(tasks => tasks.Count);
var minWorkload = personnelWorkloads.Values.Min(tasks => tasks.Count);
// 【负载差异检查】如果差异过大,尝试重分配
if (maxWorkload - minWorkload > 2)
{
// 找到负载最重和最轻的人员
var heaviestPersonnel = personnelWorkloads.First(kvp => kvp.Value.Count == maxWorkload);
var lightestPersonnel = personnelWorkloads.First(kvp => kvp.Value.Count == minWorkload);
// 【任务转移】将一个任务从重负载人员转移到轻负载人员
var taskToTransfer = heaviestPersonnel.Value.First();
optimizedSolution.BestSolution[taskToTransfer] = lightestPersonnel.Key;
_logger.LogDebug("🔄 负载均衡:将任务{TaskId}从人员{Heavy}转移到人员{Light}",
taskToTransfer, heaviestPersonnel.Key, lightestPersonnel.Key);
return true;
}
return false;
}
catch (Exception ex)
{
_logger.LogError(ex, "负载均衡尝试异常");
return false;
}
}
///
/// 检查人员是否可用于特定任务 - 综合可用性检查
///
private bool IsPersonnelAvailableForTask(long personnelId, WorkOrderEntity task, GlobalAllocationContext context)
{
try
{
// 【时间可用性检查】
if (task.ShiftId.HasValue)
{
var dateShiftKey = $"{task.WorkOrderDate:yyyy-MM-dd}_{task.ShiftId}";
if (context.DateShiftUnavailablePersonnel.TryGetValue(dateShiftKey, out var unavailablePersonnel))
{
if (unavailablePersonnel.Contains(personnelId))
{
return false; // 该时间段不可用
}
}
}
// 【资质检查】
if (context.PersonnelQualificationsCache.TryGetValue(personnelId, out var qualifications))
{
if (!ValidatePersonnelQualifications(qualifications, task))
{
return false; // 资质不符合
}
}
// 【工作限制检查】
if (context.PersonnelWorkLimitsRuleCache.TryGetValue(personnelId, out var workLimits))
{
// 简化检查:这里应该检查周工作量等限制
// 实际实现时需要更复杂的逻辑
}
return true; // 通过所有检查
}
catch (Exception ex)
{
_logger.LogError(ex, "人员可用性检查异常:人员{PersonnelId}任务{TaskId}", personnelId, task.Id);
return false;
}
}
#endregion
#endregion
}
}