移除15代之后误差小于目标两倍就停止的逻辑

feature/Model-20260625
lvjunjie 2 weeks ago
parent 4b539c9baf
commit 00d5cfdca1

@ -340,7 +340,6 @@ private:
int m_localOptimumWindow; // 局部最优观察窗口 int m_localOptimumWindow; // 局部最优观察窗口
// 质量评估参数 // 质量评估参数
double m_nearTargetFactor; // 接近目标的倍数因子
double m_farTargetFactor; // 远离目标的倍数因子 double m_farTargetFactor; // 远离目标的倍数因子
// DLL求解器需要的临时目录。每个对象单独创建析构或停止时递归清理。 // DLL求解器需要的临时目录。每个对象单独创建析构或停止时递归清理。

@ -367,7 +367,6 @@ nmCalculationAutoFitPSO::nmCalculationAutoFitPSO(QObject* parent)
, m_velocityConvergenceThreshold(0.01) , m_velocityConvergenceThreshold(0.01)
, m_trueConvergenceWindow(15) , m_trueConvergenceWindow(15)
, m_localOptimumWindow(8) , m_localOptimumWindow(8)
, m_nearTargetFactor(2.0)
, m_farTargetFactor(10.0) , m_farTargetFactor(10.0)
, m_targetWellName("") , m_targetWellName("")
, m_traceEnabled(true) , m_traceEnabled(true)
@ -5166,17 +5165,14 @@ StopReasonPSO nmCalculationAutoFitPSO::analyzeOptimizationStatus()
bool nmCalculationAutoFitPSO::checkTrueConvergence() const bool nmCalculationAutoFitPSO::checkTrueConvergence() const
{ {
// 真收敛判断:不是只看“最近没有改进”,而是同时看解质量、误差稳定性、 // 真收敛判断:不是只看“最近没有改进”,而是同时看误差稳定性、粒子群多样性、
// 粒子群多样性、平均速度、长期改进和粒子停滞率。 // 平均速度、长期改进和粒子停滞率。
// 这样可以减少把局部卡住误判成正常收敛的概率。 // 这样可以减少把局部卡住误判成正常收敛的概率。
if(m_convergenceHistory.size() < m_trueConvergenceWindow) { if(m_convergenceHistory.size() < m_trueConvergenceWindow) {
return false; return false;
} }
// 1. 检查解质量 - 如果已经接近目标,小改进可能是真收敛 // 1. 检查适应度稳定性 - 长期小幅波动
bool nearTarget = (m_globalBestFitness < m_targetError * m_nearTargetFactor);
// 2. 检查适应度稳定性 - 长期小幅波动
double recentVariance = calculateFitnessVariance(10); double recentVariance = calculateFitnessVariance(10);
double recentMean = 0.0; double recentMean = 0.0;
int windowSize = qMin(10, m_convergenceHistory.size()); int windowSize = qMin(10, m_convergenceHistory.size());
@ -5191,32 +5187,28 @@ bool nmCalculationAutoFitPSO::checkTrueConvergence() const
double relativeVariance = recentVariance / qMax(1e-10, recentMean * recentMean); double relativeVariance = recentVariance / qMax(1e-10, recentMean * recentMean);
bool stableError = (relativeVariance < m_convergenceVarianceThreshold); bool stableError = (relativeVariance < m_convergenceVarianceThreshold);
// 3. 检查粒子群多样性 - 应该收敛到同一区域 // 2. 检查粒子群多样性 - 应该收敛到同一区域
double currentDiversity = calculateSwarmDiversity(); double currentDiversity = calculateSwarmDiversity();
bool lowDiversity = (currentDiversity < m_diversityThreshold); bool lowDiversity = (currentDiversity < m_diversityThreshold);
// 4. 检查速度收敛 - 粒子应该几乎停止移动 // 3. 检查速度收敛 - 粒子应该几乎停止移动
double avgVelocity = calculateAverageVelocity(); double avgVelocity = calculateAverageVelocity();
bool velocityConverged = (avgVelocity < m_velocityConvergenceThreshold); bool velocityConverged = (avgVelocity < m_velocityConvergenceThreshold);
// 5. 检查长期改进趋势 // 4. 检查长期改进趋势
double longTermImprovement = calculateLongTermImprovement(m_trueConvergenceWindow); double longTermImprovement = calculateLongTermImprovement(m_trueConvergenceWindow);
bool minimalLongTermImprovement = (longTermImprovement < 1e-4); // 0.01% bool minimalLongTermImprovement = (longTermImprovement < 1e-4); // 0.01%
// 6. 检查粒子停滞情况 // 5. 检查粒子停滞情况
double stagnationRate = calculateParticleStagnationRate(); double stagnationRate = calculateParticleStagnationRate();
bool mostParticlesConverged = (stagnationRate > 0.8); // 80%以上粒子收敛 bool mostParticlesConverged = (stagnationRate > 0.8); // 80%以上粒子收敛
// 真收敛的判断条件 // 真收敛的判断条件
bool isConverged = nearTarget || bool isConverged = stableError && lowDiversity && velocityConverged &&
(stableError && lowDiversity && velocityConverged && minimalLongTermImprovement && mostParticlesConverged;
minimalLongTermImprovement && mostParticlesConverged);
if(isConverged) { if(isConverged) {
DEBUG_OUT("=== TRUE CONVERGENCE ANALYSIS ==="); DEBUG_OUT("=== TRUE CONVERGENCE ANALYSIS ===");
DEBUG_OUT(QString("nearTarget=%1 (error=%2, target*factor=%3)")
.arg(nearTarget).arg(m_globalBestFitness, 0, 'e', 4)
.arg(m_targetError * m_nearTargetFactor, 0, 'e', 4));
DEBUG_OUT(QString("stableError=%1 (relativeVariance=%2)") DEBUG_OUT(QString("stableError=%1 (relativeVariance=%2)")
.arg(stableError).arg(relativeVariance, 0, 'e', 6)); .arg(stableError).arg(relativeVariance, 0, 'e', 6));
DEBUG_OUT(QString("lowDiversity=%1 (diversity=%2, threshold=%3)") DEBUG_OUT(QString("lowDiversity=%1 (diversity=%2, threshold=%3)")

@ -4,7 +4,7 @@
nmDataReservoir::nmDataReservoir() { nmDataReservoir::nmDataReservoir() {
// 基础属性 // 基础属性
m_initialPressure = nmDataAttribute("Initial Pressure",40.0, "MPa", UNIT_TYPE_PRESSURE, QStringList(), QStringList() << "psia" << "Pa" << "kPa" << "atm" << "bara" << "kg/cm^2" << "m" << "psig" << "bar" << "MPa" << "kPag"); m_initialPressure = nmDataAttribute("Initial Pressure",40.0, "MPa", UNIT_TYPE_PRESSURE, QStringList(), QStringList() << "psia" << "Pa" << "kPa" << "atm" << "bara" << "kg/cm^2" << "m" << "psig" << "bar" << "MPa" << "kPag");
m_permeability = nmDataAttribute("Permeability", 0.001, "Darcy", UNIT_TYPE_PERMEABILITY, QStringList(), QStringList() << "md" << "Darcy" << "m^2" << "cm^2" << "um^2"); m_permeability = nmDataAttribute("Permeability", 0.025, "Darcy", UNIT_TYPE_PERMEABILITY, QStringList(), QStringList() << "md" << "Darcy" << "m^2" << "cm^2" << "um^2");
m_thickness = nmDataAttribute("Thickness", 10.0, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km"); m_thickness = nmDataAttribute("Thickness", 10.0, "m", UNIT_TYPE_LENGTH, QStringList(), QStringList() << "ft" << "m" << "cm" << "mm" << "in" << "0.1 in" << "mile" << "km");
m_porosity = nmDataAttribute("Porosity", 0.1, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); m_porosity = nmDataAttribute("Porosity", 0.1, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList());
m_kxKy = nmDataAttribute("Kx/Ky", 1.0, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList()); m_kxKy = nmDataAttribute("Kx/Ky", 1.0, "", UNIT_TYPE_DIMENSIONLESS, QStringList(), QStringList());

Loading…
Cancel
Save