#include "nmDataSensitive.h" #include #include nmDataSensitive::VariableSampling::VariableSampling() : m_varGroup("") , m_varName("") , m_enabled(false) , m_mode(MODE_AUTOMATIC) , m_log(false) , m_number(0) { m_modelValue = nmDataAttribute("Model value", "", ""); m_minValue = nmDataAttribute("Minimum", "", ""); m_maxValue = nmDataAttribute("Maximum", "", ""); m_values.clear(); } // 序列化 VariableSampling 为 RapidJSON Value rapidjson::Value nmDataSensitive::VariableSampling::ToJsonValue( rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value obj(rapidjson::kObjectType); // 字符串字段 obj.AddMember("VarGroup", rapidjson::Value(m_varGroup.toStdString().c_str(), allocator).Move(), allocator); obj.AddMember("VarName", rapidjson::Value(m_varName.toStdString().c_str(), allocator).Move(), allocator); // 简单类型 obj.AddMember("Enabled", m_enabled, allocator); obj.AddMember("Mode", static_cast(m_mode), allocator); obj.AddMember("Log", m_log, allocator); obj.AddMember("Number", m_number, allocator); // nmDataAttribute 成员 obj.AddMember("ModelValue", m_modelValue.ToJsonValue(allocator), allocator); obj.AddMember("Minimum", m_minValue.ToJsonValue(allocator), allocator); obj.AddMember("Maximum", m_maxValue.ToJsonValue(allocator), allocator); // values 数组 rapidjson::Value arr(rapidjson::kArrayType); for (int i = 0; i < m_values.size(); ++i) { arr.PushBack(m_values.at(i), allocator); } obj.AddMember("Values", arr, allocator); return obj; } // 从 RapidJSON Value 反序列化到 VariableSampling void nmDataSensitive::VariableSampling::FromJsonValue(const rapidjson::Value& jsonValue) { if (jsonValue.HasMember("VarGroup") && jsonValue["VarGroup"].IsString()) { m_varGroup = QString::fromUtf8(jsonValue["VarGroup"].GetString()); } if (jsonValue.HasMember("VarName") && jsonValue["VarName"].IsString()) { m_varName = QString::fromUtf8(jsonValue["VarName"].GetString()); } if (jsonValue.HasMember("Enabled") && jsonValue["Enabled"].IsBool()) { m_enabled = jsonValue["Enabled"].GetBool(); } if (jsonValue.HasMember("Mode") && jsonValue["Mode"].IsInt()) { int m = jsonValue["Mode"].GetInt(); m_mode = (m == MODE_MANUAL) ? MODE_MANUAL : MODE_AUTOMATIC; } if (jsonValue.HasMember("Log") && jsonValue["Log"].IsBool()) { m_log = jsonValue["Log"].GetBool(); } if (jsonValue.HasMember("Number") && jsonValue["Number"].IsInt()) { m_number = jsonValue["Number"].GetInt(); } if (jsonValue.HasMember("ModelValue") && jsonValue["ModelValue"].IsObject()) { m_modelValue.FromJsonValue(jsonValue["ModelValue"]); } if (jsonValue.HasMember("Minimum") && jsonValue["Minimum"].IsObject()) { m_minValue.FromJsonValue(jsonValue["Minimum"]); } if (jsonValue.HasMember("Maximum") && jsonValue["Maximum"].IsObject()) { m_maxValue.FromJsonValue(jsonValue["Maximum"]); } m_values.clear(); if (jsonValue.HasMember("Values") && jsonValue["Values"].IsArray()) { const rapidjson::Value& arr = jsonValue["Values"]; for (rapidjson::SizeType i = 0; i < arr.Size(); ++i) { if (arr[i].IsNumber()) { m_values.append(arr[i].GetDouble()); } } } } // varGroup QString nmDataSensitive::VariableSampling::getVarGroup() const { return m_varGroup; } void nmDataSensitive::VariableSampling::setVarGroup(const QString& group) { m_varGroup = group; } // varName QString nmDataSensitive::VariableSampling::getVarName() const { return m_varName; } void nmDataSensitive::VariableSampling::setVarName(const QString& name) { m_varName = name; } // enabled bool nmDataSensitive::VariableSampling::getEnabled() const { return m_enabled; } void nmDataSensitive::VariableSampling::setEnabled(bool e) { m_enabled = e; } // mode nmDataSensitive::VariableSampling::Mode nmDataSensitive::VariableSampling::getMode() const { return m_mode; } void nmDataSensitive::VariableSampling::setMode(Mode m) { m_mode = m; } // log bool nmDataSensitive::VariableSampling::getLog() const { return m_log; } void nmDataSensitive::VariableSampling::setLog(bool l) { m_log = l; } // number int nmDataSensitive::VariableSampling::getNumber() const { return m_number; } void nmDataSensitive::VariableSampling::setNumber(int n) { m_number = n; } // modelValue nmDataAttribute& nmDataSensitive::VariableSampling::getModelValue() { return m_modelValue; } void nmDataSensitive::VariableSampling::setModelValue(const nmDataAttribute& attr) { m_modelValue = attr; } // minValue nmDataAttribute& nmDataSensitive::VariableSampling::getMinValue() { return m_minValue; } void nmDataSensitive::VariableSampling::setMinValue(const nmDataAttribute& attr) { m_minValue = attr; } // maxValue nmDataAttribute& nmDataSensitive::VariableSampling::getMaxValue() { return m_maxValue; } void nmDataSensitive::VariableSampling::setMaxValue(const nmDataAttribute& attr) { m_maxValue = attr; } // values QVector& nmDataSensitive::VariableSampling::getValues() { return m_values; } void nmDataSensitive::VariableSampling::setValues(const QVector& vals) { m_values = vals; } QVector nmDataSensitive::VariableSampling::samplingValues() const { // 表格显示精度不参与采样,包含零或负数的对数范围按线性处理。 if (m_mode == MODE_MANUAL) return m_values; QVector values; if (m_number <= 0) return values; const double minimum = m_minValue.getValue().toDouble(); const double maximum = m_maxValue.getValue().toDouble(); const bool logarithmic = m_log && minimum > 0.0 && maximum > 0.0; for (int i = 0; i < m_number; ++i) { const double t = m_number == 1 ? 0.0 : double(i) / (m_number - 1); double value = logarithmic ? std::exp((1.0 - t) * std::log(minimum) + t * std::log(maximum)) : (1.0 - t) * minimum + t * maximum; if (m_number == 1) value = m_modelValue.getValue().toDouble(); else if (i == 0) value = minimum; else if (i == m_number - 1) value = maximum; values.append(value); } return values; } nmDataSensitive::nmDataSensitive() : m_calcType(CALC_DETERMINISTIC) , m_totalModelCount(0) , m_usesBaseUnits(false) , m_variables() { } // 拷贝构造 nmDataSensitive::nmDataSensitive(const nmDataSensitive& other) { *this = other; } // 赋值运算符 nmDataSensitive& nmDataSensitive::operator=(const nmDataSensitive& other) { if (this != &other) { m_calcType = other.m_calcType; m_totalModelCount = other.m_totalModelCount; m_usesBaseUnits = other.m_usesBaseUnits; m_variables = other.m_variables; } return *this; } nmDataSensitive::~nmDataSensitive() { } // 序列化 nmDataSensitive 为 RapidJSON Value rapidjson::Value nmDataSensitive::ToJsonValue( rapidjson::Document::AllocatorType& allocator) const { rapidjson::Value root(rapidjson::kObjectType); // 旧配置中的采样值是显示单位,新配置统一保存业务基准单位。 root.AddMember("UsesBaseUnits", m_usesBaseUnits, allocator); // 顶部 Calculation type root.AddMember("CalculationType", static_cast(m_calcType), allocator); // 总模型数 root.AddMember("TotalModelCount", m_totalModelCount, allocator); // 变量数组 rapidjson::Value arr(rapidjson::kArrayType); for (int i = 0; i < m_variables.size(); ++i) { arr.PushBack(m_variables.at(i).ToJsonValue(allocator), allocator); } root.AddMember("Variables", arr, allocator); return root; } // 从 RapidJSON Value 反序列化数据到 nmDataSensitive void nmDataSensitive::FromJsonValue(const rapidjson::Value& jsonValue) { m_usesBaseUnits = jsonValue.HasMember("UsesBaseUnits") && jsonValue["UsesBaseUnits"].IsBool() && jsonValue["UsesBaseUnits"].GetBool(); if (jsonValue.HasMember("CalculationType") && jsonValue["CalculationType"].IsInt()) { int t = jsonValue["CalculationType"].GetInt(); if (t == CALC_DETERMINISTIC_MULTIVARIATE) m_calcType = CALC_DETERMINISTIC_MULTIVARIATE; else m_calcType = CALC_DETERMINISTIC; } if (jsonValue.HasMember("TotalModelCount") && jsonValue["TotalModelCount"].IsUint64()) { m_totalModelCount = jsonValue["TotalModelCount"].GetUint64(); } m_variables.clear(); if (jsonValue.HasMember("Variables") && jsonValue["Variables"].IsArray()) { const rapidjson::Value& arr = jsonValue["Variables"]; for (rapidjson::SizeType i = 0; i < arr.Size(); ++i) { if (!arr[i].IsObject()) continue; VariableSampling vs; vs.FromJsonValue(arr[i]); m_variables.append(vs); } } } // === Calculation type === nmDataSensitive::CalculationType nmDataSensitive::getCalculationType() const { return m_calcType; } void nmDataSensitive::setCalculationType(CalculationType type) { m_calcType = type; } // === 总模型数 === quint64 nmDataSensitive::getTotalModelCount() const { return m_totalModelCount; } void nmDataSensitive::setTotalModelCount(quint64 count) { m_totalModelCount = count; } quint64 nmDataSensitive::calculateModelCount(bool* overflow) const { // 未选择变量时为零;两种确定性方法分别累计和、积。 if (overflow) *overflow = false; quint64 count = 0; bool selected = false; for (int i = 0; i < m_variables.size(); ++i) { const VariableSampling& variable = m_variables[i]; if (!variable.m_enabled) continue; const quint64 number = variable.m_number > 0 ? variable.m_number : 0; if (!number) return 0; const quint64 limit = (std::numeric_limits::max)(); if (m_calcType == CALC_DETERMINISTIC) { if (count > limit - number) { if (overflow) *overflow = true; return 0; } count += number; } else { if (!selected) count = 1; if (count > limit / number) { if (overflow) *overflow = true; return 0; } count *= number; } selected = true; } return count; } bool nmDataSensitive::getRunValues(quint64 runIndex, QVector& values) const { // 按编号解码组合,不预先展开笛卡尔积,也不删除重复的基准组合。 bool overflow = false; const quint64 count = calculateModelCount(&overflow); if (overflow || runIndex >= count) return false; values.clear(); for (int i = 0; i < m_variables.size(); ++i) values.append(m_variables[i].m_modelValue.getValue().toDouble()); if (m_calcType == CALC_DETERMINISTIC) { for (int i = 0; i < m_variables.size(); ++i) { const VariableSampling& variable = m_variables[i]; if (!variable.m_enabled) continue; const QVector samples = variable.samplingValues(); if (samples.size() != variable.m_number) return false; if (runIndex < quint64(samples.size())) { values[i] = samples[int(runIndex)]; return true; } runIndex -= samples.size(); } } else { // Saphir 按第一个选中参数最快变化的顺序列出多变量组合。 for (int i = 0; i < m_variables.size(); ++i) { const VariableSampling& variable = m_variables[i]; if (!variable.m_enabled) continue; const QVector samples = variable.samplingValues(); if (samples.isEmpty() || samples.size() != variable.m_number) return false; values[i] = samples[int(runIndex % samples.size())]; runIndex /= samples.size(); } return true; } return false; } bool nmDataSensitive::usesBaseUnits() const { return m_usesBaseUnits; } void nmDataSensitive::setUsesBaseUnits(bool enabled) { // 单位标记随配置保存,避免再次打开时重复转换。 m_usesBaseUnits = enabled; } // === 变量列表 === QList& nmDataSensitive::getVariables() { return m_variables; } const QList& nmDataSensitive::getVariables() const { // 求解任务只读取采样配置,不取得可写参数列表。 return m_variables; } void nmDataSensitive::setVariables(const QList& vars) { m_variables = vars; } int nmDataSensitive::getVariableCount() const { return m_variables.size(); } nmDataSensitive::VariableSampling& nmDataSensitive::getVariable(int index) { return m_variables[index]; }