#ifndef NMCALCULATIONAUTOFIT_H #define NMCALCULATIONAUTOFIT_H #include #include #include #include #include #include #include #include #include "nmCalculation_global.h" // 前向声明 class nmCalculationDllPebiSolverTask; class nmDataWellBase; class QTimer; class QProcess; // PSO粒子结构 // 这里的 position / velocity / bestPosition 只保存“用户勾选参与拟合的参数”, // 不是完整的 11 个储层/井筒参数。完整参数向量会在写 trace 或调用代理模型时 // 通过 buildTraceParameterVector() 重新组装。 // // surrogate* 和 screeningDecision 是 PSO 加速筛选的辅助字段。代理模型只决定 // “这一代哪些粒子需要继续跑真实求解器”,不会直接更新 pbest / gbest。 struct AutoFitParticle { QVector > currentLogLogData; QVector > bestLogLogData; QVector position; // 当前位置(参数值) QVector velocity; // 速度 QVector bestPosition; // 个体最优位置 double fitness; // 当前适应度 double bestFitness; // 个体最优适应度 bool evaluatedThisIteration; bool lastEvaluationSuccess; int lastEvaluationElapsedMs; double surrogateObjective; bool selectedForSolver; bool selectedByAudit; QString screeningDecision; AutoFitParticle() : fitness(1e10) , bestFitness(1e10) , evaluatedThisIteration(false) , lastEvaluationSuccess(false) , lastEvaluationElapsedMs(-1) , surrogateObjective(1e10) , selectedForSolver(true) , selectedByAudit(false) , screeningDecision("full_solver") {} }; // PSO停止原因。主循环每一代结束时会根据目标误差、收敛历史、粒子群多样性、 // 连续失败次数等状态给出一个停止判断。 enum StopReasonPSO { PSO_CONTINUE_OPTIMIZATION = 0, // 继续优化 PSO_TARGET_ACHIEVED = 1, // 达到目标精度 PSO_TRUE_CONVERGENCE = 2, // 真正收敛 PSO_LOCAL_OPTIMUM = 3, // 陷入局部最优 PSO_MAX_ITERATIONS = 4, // 达到最大迭代数 PSO_USER_STOPPED = 5, // 用户停止 PSO_CONSECUTIVE_FAILURES = 6, // 连续失败停止 PSO_OPTIMIZATION_FAILED = 7 // 优化失败 }; class NMCALCULATION_EXPORT nmCalculationAutoFitPSO : public QObject { Q_OBJECT public: // 构造函数和析构函数 explicit nmCalculationAutoFitPSO(QObject* parent = 0); ~nmCalculationAutoFitPSO(); // ===== 核心接口:完全数据驱动 ===== // // 这个类不直接读取自动拟合对话框控件。界面层 nmWxAutomaticFitting 会先把 // 用户选择的参数范围、迭代次数、误差容限、PSO acceleration 开关等保存到 // nmDataAnalyzeManager / nmDataAutomaticFitting,然后本类在 startAutoFitting() // 内部统一读取。 void setTargetLogLogData(const QVector >& targetData); bool startAutoFitting(); void stopFitting(); QVector getBestSolution() const; double getBestFitness() const; QString getLastError() const; bool isRunning() const; int getCurrentIteration() const; void resetOptimizer(); void setPSOTargetWellName(const QString& wellName); //QString getTargetWellName() const; public: // 模拟拟合模式 void setSimulationMode(bool enabled); bool isSimulationMode() const { return m_simulationMode; } void setSimulationTargetParams(const QVector& targetParams, double targetError); private slots: void onSimulationTimerTick(); signals: void progressUpdated(int iteration, double bestFitness); void fittingFinished(bool success, const QString& message); void bestCurveUpdated(QVector > targetData, QVector > bestData, int iteration, double fitness); signals: void logMessageGenerated(const QString& message); private: // 临时目录管理 void initializeTemporaryDirectory(); void cleanupTemporaryDirectory(); bool removeDirectoryRecursively(const QString& path); void cleanupOldTemporaryDirectories(); // ===== 数据加载方法 ===== bool loadAllConfigFromDataManager(); void loadOptimizationConfig(); void loadParameterBounds(); // ===== PSO核心算法 ===== // // 主流程: // 1. extractUserInitialValues(): 从当前项目数据中取用户已有初始解; // 2. initializeSwarm(): 根据初始解和上下界生成粒子群; // 3. updateParticle(): 对单个粒子跑真实求解器并计算误差; // 4. updateGlobalBest(): 只用真实求解器误差更新全局最优; // 5. updateVelocityAndPosition(): 按 PSO 公式推进下一代粒子。 void extractUserInitialValues(); void initializeSwarm(); void updateVelocityAndPosition(); double evaluateFitness(const QVector& parameters); void updateGlobalBest(); void updateParticle(int particleIndex); // ===== 参数应用方法 ===== // // 每次评价粒子前,都会把该粒子的参数临时写入 DataManager: // - 储层参数写入 nmDataReservoir; // - 井参数(skin / wellbore storage)写入目标井。 // 求解器随后基于 DataManager 的当前状态计算模拟曲线。 void applyParametersToDataManager(const QVector& parameters); void updateReservoirParameters(const QVector& parameters); void updateWellParameters(const QVector& parameters); void updateWellToDataManager(nmDataWellBase* pWell); // ===== 求解器相关 ===== QVector > runSolver(); QVector> runSolverDll(); QVector> runSolverExe(); // ===== 数据处理 ===== QVector interpolateData(const QVector& source, const QVector& targetX) const; // ===== 算法辅助 ===== void adaptiveParameterUpdate(int iteration); void saveOptimizationResult(); void validateAndProtectFinalResult(); // 收敛判断方法 StopReasonPSO analyzeOptimizationStatus(); bool checkTrueConvergence() const; bool checkLocalOptimumTrap() const; // 粒子群状态分析 double calculateSwarmDiversity() const; double calculateAverageVelocity() const; double calculateParticleStagnationRate() const; // 适应度稳定性分析 double calculateFitnessVariance(int windowSize) const; double calculateLongTermImprovement(int windowSize) const; // 工具方法 QString getStopReasonDescription(StopReasonPSO reason) const; void updateConvergenceMetrics(); // ===== 工具方法 ===== double random01() const; void clampToLimits(QVector& parameters) const; int getEnabledParameterCount() const; void logDebugInfo(const QString& message) const; // ===== Baseline trace ===== // // trace:记录每一代、每个粒子的参数、真实求解器误差、 // 代理模型误差、筛选决策、pbest 和 gbest。代理筛选质量、某个粒子为什么 // 没有跑真实求解器,都应该优先看 trace。 void initializeTraceFile(); void closeTraceFile(); void writeTraceHeader(); void writeTraceMetaFile(); void writeTraceRow(int generation, int particleIndex, const QString& phase, const QVector& parameters, double solverObjective, bool solverSuccess, int elapsedMs, double surrogateObjective, const QString& screeningDecision, const QVector& pbestPosition, double pbestObjective); void writeIterationTraceRows(); QVector buildTraceParameterVector(const QVector& selectedParameters) const; void resetRunSummary(); void captureSurrogateRunContextSummary(); void emitRunSummary(bool success, StopReasonPSO finalReason); // ===== Surrogate screening prototype ===== // // PSO acceleration 的核心逻辑。开启后,buildSurrogateEvaluationMask() 会: // 1. 判断当前工况是否在代理模型训练域内; // 2. 将当代粒子候选写成 CSV; // 3. 调用 Python 代理模型输出 surrogate_objective; // 4. 选择 top-k、随机审计、fallback 和最小真实求解比例对应的粒子; // 5. 返回 bool mask,true 表示该粒子继续跑真实求解器。 // // 代理模型只筛选候选,不直接决定最终最优参数。 bool isSurrogateScreeningEnabled() const; QString getMlRootPath() const; QString getPythonExecutablePath() const; QString getSurrogateTag() const; QString getSurrogateStage() const; double getSurrogateKeepFraction() const; double getSurrogateAuditFraction() const; double getSurrogateMinSolverFraction() const; int getSurrogateWarmupIterations() const; int getSurrogateFullSolverInterval() const; QVector buildSurrogateEvaluationMask(); bool writeSurrogateCandidateCsv(const QString& candidatePath) const; bool runSurrogateScoringProcess(const QString& candidatePath, const QString& scorePath, QString* failureReason = nullptr); bool runSurrogateScoringScriptOnce(const QString& candidatePath, const QString& scorePath, QString* failureReason = nullptr); bool ensureSurrogateScoringServer(QString* failureReason = nullptr); bool requestSurrogateScoresFromServer(const QString& candidatePath, const QString& scorePath, QString* failureReason = nullptr); void stopSurrogateScoringServer(); QVector readSurrogateScores(const QString& scorePath) const; bool forceSolverByFallbackGate(const QVector& selectedParameters) const; bool isStrongDecliningProductionSchedule(double* endStartRatio = nullptr) const; bool isSurrogateRunContextSupported(QString* reason) const; bool isSurrogateCandidateInDomain(const QVector& selectedParameters, QString* reason) const; // ===== 验证和处理方法 ===== bool validateParameters(const QVector& parameters) const; bool validateLogLogData(const QVector >& logLogData) const; bool validateInitialValues() const; // 验证初始值有效性 bool validateSolverResult(const QVector>& result) const; double calculateCurveError(const QVector& curve1, const QVector& curve2) const; double calculateLogLogCurveError(const QVector >& target, const QVector >& result) const; double calculateWeightedPointError(double target, double result, double timeWeight) const; private: // ===== 运行状态 ===== bool m_isRunning; // 当前是否有一次自动拟合正在运行。 bool m_shouldStop; // 用户停止标志;主循环和求解器等待循环会定期检查它。 bool m_isPaused; // 预留暂停标志;主循环中有暂停等待逻辑。 int m_currentIteration; // 当前 PSO 迭代序号,从 0 开始。 QString m_lastError; // 最近一次失败原因,供 UI 展示或日志排查。 // ===== PSO数据 ===== QVector m_initialValues; // 当前模型中提取的用户初始值,顺序与 m_enabledParamIndices 一致。 QVector m_swarm; // 粒子群,每个粒子只保存启用参数维度。 QVector m_globalBestPosition; // 全局最优参数,仍是启用参数向量。 double m_globalBestFitness; // 全局最优真实误差,越小越好。 double m_previousBestFitness; // 上一轮全局最优误差,用于自适应参数更新。 QVector > m_lastEvaluatedLogLogData; // 最近一次真实求解得到的 result log-log 曲线。 QVector > m_globalBestLogLogData; // 当前全局最优对应的 result log-log 曲线。 QVector > m_userInitialLogLogData; // 用户初始解对应的 result log-log 曲线,用于精英保护。 // ===== 优化配置 ===== // // 参数索引约定: // 0 k 渗透率;1 skin 表皮系数;2 wellboreC 井筒储集; // 3 phi 孔隙度;4 initialPressure 初始压力;5 h 储层厚度; // 6 Ct 综合压缩系数;7 Cf 岩石压缩系数; // 8 Soi 初始含油饱和度;9 Swi 初始含水饱和度;10 Sgi 初始含气饱和度。 // m_enabledParamIndices 保存被用户勾选的参数索引,粒子的 position 维度与它一致。 QVector m_parameterSelected; // 完整 11 个参数是否被用户勾选参与拟合。 QVector m_parameterLower; // 完整 11 个参数的搜索下界。 QVector m_parameterUpper; // 完整 11 个参数的搜索上界。 QVector m_enabledParamIndices; // 被勾选参数在完整 11 维体系中的索引。 QVector > m_targetLogLogData; // 目标井 history log-log 曲线:time/pressure/derivative。 QString m_targetWellName; // 目标井名称;读写井参数和读取模拟曲线都依赖它。 // ===== 算法配置 ===== int m_swarmSize; // 粒子数量,当前默认 20。 int m_maxIterations; // 最大迭代次数,来自自动拟合配置。 double m_targetError; // 目标误差,小于该值视为达到拟合目标。 double m_inertiaWeight; // 惯性权重,控制粒子保留上一轮速度的程度。 double m_cognitiveParam; // 个体学习因子,控制粒子靠近自身 pbest 的程度。 double m_socialParam; // 群体学习因子,控制粒子靠近全局 gbest 的程度。 // ===== 统计信息 ===== int m_totalEvaluations; // 已调用真实求解器评价的粒子总数。 int m_successfulEvaluations; // 真实求解器成功且误差有效的评价次数。 QVector m_convergenceHistory; // 每代全局最优误差历史,用于收敛判断。 // ===== 常量 ===== static const double MIN_FITNESS_IMPROVEMENT; // 判断误差是否有有效改善的最小阈值。 static const double VELOCITY_LIMIT_FACTOR; // 粒子速度上限占参数搜索区间的比例。 static const int CONVERGENCE_CHECK_INTERVAL; // 收敛检查的基础间隔。 // ===== 资源管理 ===== volatile int m_evaluationInProgress; // 并发控制 int m_consecutiveFailures; // 连续失败计数 // ===== 精英保护 ===== QVector m_userInitialSolution; // 用户初始解参数,若最终改进不足会恢复它。 double m_userInitialFitness; // 用户初始解真实误差。 double m_improvementThreshold; // 最终结果相对初始解至少需要达到的改进阈值。 bool m_hasValidUserSolution; // 初始解是否成功跑过真实求解器。 int m_consecutiveFailedIterations; // 连续失败迭代次数 int m_maxConsecutiveFailures; // 最大允许连续失败次数 // 收敛判断相关 double m_diversityThreshold; // 多样性阈值 QVector m_diversityHistory; // 粒子群多样性历史 QVector m_velocityHistory; // 平均速度历史 QVector m_particleStagnationHistory; // 粒子停滞率历史 // 收敛判断参数 double m_convergenceVarianceThreshold; // 收敛方差阈值 double m_velocityConvergenceThreshold; // 速度收敛阈值 int m_trueConvergenceWindow; // 真收敛观察窗口 int m_localOptimumWindow; // 局部最优观察窗口 // 质量评估参数 double m_nearTargetFactor; // 接近目标的倍数因子 double m_farTargetFactor; // 远离目标的倍数因子 // DLL求解器需要的临时目录。每个对象单独创建,析构或停止时递归清理。 QString m_tempDirectory; // ===== Trace 和代理筛选统计 ===== // // 这些字段只描述代理筛选和运行复盘,不参与 PSO 数学更新。 bool m_traceEnabled; // 是否写出 trace CSV/meta 文件。 QString m_traceRunId; // 本次运行 ID,作为 trace/candidate/score 文件名的一部分。 QString m_traceFilePath; // pso_baseline_trace_.csv 完整路径。 QString m_traceMetaFilePath; // pso_baseline_trace_.meta.json 完整路径。 QFile m_traceFile; // trace CSV 文件句柄。 bool m_surrogateScreeningEnabled; // 用户配置中的 PSO acceleration 开关。 unsigned int m_psoRandomSeed; // PSO 随机种子,也用于可复现 random audit。 QString m_surrogateRunContextSummary; // 本次运行代理工况 gate 的摘要。 int m_surrogateWarmupIterationCount; // warmup 全量真实评价代数。 int m_surrogatePeriodicAuditIterationCount; // 周期性全量审计代数。 int m_surrogateContextBlockedIterationCount; // 因工况不支持而全量真实评价的代数。 int m_surrogateActiveIterationCount; // 代理筛选真正参与的代数。 int m_surrogateSelectedParticleCount; // 被选中跑真实求解器的粒子累计数。 int m_surrogateScreenedParticleCount; // 被代理筛掉的粒子累计数。 int m_surrogateTopKParticleCount; // 因 surrogate top-k 被选中的粒子累计数。 int m_surrogateAuditParticleCount; // 因 random audit 被选中的粒子累计数。 int m_surrogateFallbackParticleCount; // 因 fallback gate 被选中的粒子累计数。 int m_surrogateDomainParticleCount; // 因训练域 gate 被选中的粒子累计数。 int m_surrogateMinFloorParticleCount; // 因最低真实求解比例被补选中的粒子累计数。 QProcess* m_surrogateScoringProcess; // 常驻 Python 代理评分 server 进程。 QString m_surrogateScoringServerKey; // 标识当前 server 对应的 python/script/meta/tag/stage。 private: // 模拟拟合相关成员 bool m_simulationMode; // 是否启用仿真模式;仿真模式不调用真实求解器。 QTimer* m_simulationTimer; // 仿真日志定时器,用于分步模拟长任务。 int m_simulationIteration; // 仿真当前迭代。 int m_simulationMaxIterations; // 仿真最大迭代。 QVector m_simulationTargetParams; // 仿真最终目标参数。 QVector m_simulationStartParams; // 仿真起始参数。 double m_simulationTargetError; // 仿真最终目标误差。 double m_simulationStartError; // 仿真起始误差。 double m_simulationCurrentError; // 仿真当前误差。 int m_simulationLogInterval; // 仿真日志输出间隔,单位秒。 QTime m_simulationStartTime; // 仿真开始时间,用于演示节奏统计。 // 用于逐粒子输出的状态 int m_simulationCurrentParticle; // 当前正在处理的粒子索引 int m_simulationSuccessCount; // 当前迭代成功的粒子数 int m_simulationFailCount; // 当前迭代失败的粒子数 bool m_simulationIterationStarted; // 当前迭代是否已开始 double m_simulationPreviousIterError; // 上一次迭代的误差 // 模拟拟合方法 void runSimulatedFitting(); void emitSimulationLog(int iteration); double calculateSimulatedError(int iteration); QVector calculateSimulatedParams(int iteration); private: void startNewSimulationIteration(); void emitParticleLog(int particleIndex); void finishCurrentIteration(); void finishSimulation(); QVector > buildSimulatedLogLogData(double progress) const; }; #endif // NMCALCULATIONAUTOFIT_H