|
|
|
|
@ -1,4 +1,6 @@
|
|
|
|
|
#include "nmDataSensitive.h"
|
|
|
|
|
#include <cmath>
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
|
|
nmDataSensitive::VariableSampling::VariableSampling()
|
|
|
|
|
: m_varGroup("")
|
|
|
|
|
@ -204,10 +206,33 @@ void nmDataSensitive::VariableSampling::setValues(const QVector<double>& vals)
|
|
|
|
|
m_values = vals;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<double> nmDataSensitive::VariableSampling::samplingValues() const
|
|
|
|
|
{
|
|
|
|
|
// 表格显示精度不参与采样,包含零或负数的对数范围按线性处理。
|
|
|
|
|
if (m_mode == MODE_MANUAL) return m_values;
|
|
|
|
|
QVector<double> 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()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
@ -224,6 +249,7 @@ 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;
|
|
|
|
|
@ -238,6 +264,8 @@ 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",
|
|
|
|
|
@ -262,6 +290,8 @@ rapidjson::Value nmDataSensitive::ToJsonValue(
|
|
|
|
|
// 从 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)
|
|
|
|
|
@ -270,8 +300,8 @@ void nmDataSensitive::FromJsonValue(const rapidjson::Value& jsonValue)
|
|
|
|
|
m_calcType = CALC_DETERMINISTIC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (jsonValue.HasMember("TotalModelCount") && jsonValue["TotalModelCount"].IsInt()) {
|
|
|
|
|
m_totalModelCount = jsonValue["TotalModelCount"].GetInt();
|
|
|
|
|
if (jsonValue.HasMember("TotalModelCount") && jsonValue["TotalModelCount"].IsUint64()) {
|
|
|
|
|
m_totalModelCount = jsonValue["TotalModelCount"].GetUint64();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_variables.clear();
|
|
|
|
|
@ -300,16 +330,87 @@ void nmDataSensitive::setCalculationType(CalculationType type)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// === 总模型数 ===
|
|
|
|
|
int nmDataSensitive::getTotalModelCount() const
|
|
|
|
|
quint64 nmDataSensitive::getTotalModelCount() const
|
|
|
|
|
{
|
|
|
|
|
return m_totalModelCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmDataSensitive::setTotalModelCount(int count)
|
|
|
|
|
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<quint64>::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<double>& 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<double> 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 {
|
|
|
|
|
for (int i = m_variables.size() - 1; i >= 0; --i) {
|
|
|
|
|
const VariableSampling& variable = m_variables[i];
|
|
|
|
|
if (!variable.m_enabled) continue;
|
|
|
|
|
const QVector<double> 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::VariableSampling>& nmDataSensitive::getVariables()
|
|
|
|
|
{
|
|
|
|
|
|