eis/eqpalg/utility/expression_engine.cpp

229 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// eqpalg/utility/expression_engine.cpp
#include <eqpalg/utility/expression_engine.h>
#include <glob/SingletonTemplate.h>
#include <eqpalg/gb_item_memory.h>
#include <mix_cc/type/mix_time.h>
#include <log4cplus/LOG.h>
ExpressionEngine::ExpressionEngine(std::map<std::string, double>& mm_vars,
std::vector<std::string>& m_tags)
: mm_vars_(mm_vars), m_tags_(m_tags) {}
// 惰性初始化 VarsCache首次变量刷新时调用
static void ensureVarCache(VarsCache& vc, size_t tag_count) {
if (vc.tag_num == 0 && tag_count > 0) {
vc.init(tag_count, 6);
}
}
int ExpressionEngine::registerExpression(const std::string& name,
const std::string& raw_exp_str) {
if (exps_.count(name)) return 0; // 已注册,幂等
auto& entry = exps_[name];
entry.raw_str = raw_exp_str;
// 通过 FunVars 替换状态函数KeepC/KeepT/RiseEdge/Detect为 funN 变量
auto [ok, processed] = fun_vars_.add_exp_str(raw_exp_str, &mm_vars_);
if (!ok) return -1;
entry.processed_str = processed;
// 编译表达式
try {
entry.ptr = std::make_unique<MExp>(processed, &mm_vars_);
} catch (const std::exception& e) {
return -1;
}
// 从表达式中提取 hold(n,T) 模式
initHoldExpStr(processed);
return 0;
}
int ExpressionEngine::registerRawExpression(const std::string& name,
const std::string& raw_exp_str) {
if (exps_.count(name)) return 0;
auto& entry = exps_[name];
entry.raw_str = raw_exp_str;
entry.processed_str = raw_exp_str;
try {
entry.ptr = std::make_unique<MExp>(raw_exp_str, &mm_vars_);
} catch (const std::exception& e) {
return -1;
}
return 0;
}
double ExpressionEngine::evaluate(const std::string& name) {
auto it = exps_.find(name);
if (it == exps_.end()) return 0.0;
return it->second.ptr->evaluate();
}
bool ExpressionEngine::evaluateBool(const std::string& name) {
return static_cast<bool>(evaluate(name));
}
int ExpressionEngine::initHoldExpStr(const std::string& exp_str) {
auto hold_sub_strs = HoldTime::find_substr(exp_str, "_HE");
for (const auto& sub_str : hold_sub_strs) {
bool flag;
double timeM;
std::string tagi;
std::string var_name;
std::tie(flag, timeM, tagi, var_name) = HoldTime::find_hold(sub_str);
if (flag) {
if (hold_times_.find(var_name) == hold_times_.end()) {
hold_times_.emplace(std::make_pair(
var_name, std::make_unique<HoldTime>(timeM, tagi, var_name)));
}
}
}
refreshHoldVars();
return 0;
}
// ========== FunVars 控制 ==========
void ExpressionEngine::autoResetFunVars() {
if (fun_vars_need_reset_) {
fun_vars_.refresh_fun_vars(true, &mm_vars_);
fun_vars_need_reset_ = false;
}
}
void ExpressionEngine::markFunVarsNeedReset() {
fun_vars_need_reset_ = true;
}
void ExpressionEngine::forceResetFunVars() {
fun_vars_.refresh_fun_vars(true, &mm_vars_);
fun_vars_need_reset_ = false;
}
void ExpressionEngine::refreshFromMemory(
const TimePoint& now_time,
mix_cc::time_range_t& query_time_range) {
ensureVarCache(var_cache_, m_tags_.size());
for (size_t i = 0; i < m_tags_.size(); i++) {
double current =
SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags_[i]];
// pN = 旧 tagN
mm_vars_[var_cache_.p_keys[i]] = mm_vars_[var_cache_.tag_keys[i]];
// tagN = 当前值
mm_vars_[var_cache_.tag_keys[i]] = current;
// pvN 历史移位
for (size_t j = PV_NUM - 1; j > 0; j--) {
mm_vars_[var_cache_.pv_keys[i][j]] =
mm_vars_[var_cache_.pv_keys[i][j - 1]];
}
mm_vars_[var_cache_.pv_keys[i][0]] = current;
}
mm_vars_["now"] = std::chrono::duration_cast<std::chrono::milliseconds>(
now_time.time_since_epoch())
.count();
fun_vars_.refresh_fun_vars(false, &mm_vars_);
query_time_range.set_right(now_time);
refreshHoldVars();
}
void ExpressionEngine::refreshFromIhdRow(
int row,
const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>& queried_data,
const std::vector<TimePoint>& queried_time,
TimePoint& now_time,
mix_cc::time_range_t& query_time_range) {
if (queried_data.rows() == 0 || queried_data.cols() == 0) return;
if (row < 0 || row >= queried_data.rows()) return;
if (static_cast<int>(m_tags_.size()) > queried_data.cols()) return;
ensureVarCache(var_cache_, m_tags_.size());
for (size_t i = 0; i < m_tags_.size(); i++) {
// pN = 旧 tagN
mm_vars_[var_cache_.p_keys[i]] = mm_vars_[var_cache_.tag_keys[i]];
// tagN = 当前行数据
mm_vars_[var_cache_.tag_keys[i]] = queried_data(row, i);
// pvN 历史移位
for (size_t j = PV_NUM - 1; j > 0; j--) {
mm_vars_[var_cache_.pv_keys[i][j]] =
mm_vars_[var_cache_.pv_keys[i][j - 1]];
}
mm_vars_[var_cache_.pv_keys[i][0]] =
mm_vars_[var_cache_.tag_keys[i]];
}
mm_vars_["now"] =
mix_cc::mix_time_t(queried_time[row]).to_milliseconds();
now_time = queried_time[row];
query_time_range.set_right(queried_time[row]);
fun_vars_.refresh_fun_vars(false, &mm_vars_);
refreshHoldVars();
}
void ExpressionEngine::refreshHoldVars() {
for (auto& kv : hold_times_) {
mm_vars_[kv.first] =
static_cast<double>(kv.second->update_value(mm_vars_[kv.second->tagi]));
}
}
// ========== 调试 ==========
void ExpressionEngine::printVars(const std::string& exp_str) {
// 简单调试输出:遍历所有变量
// 调用方可使用 LOG 宏自行格式化
}
int ExpressionEngine::firstFill(int data_source, TimePoint& now_time,
mix_cc::time_range_t& query_time_range) {
// 惰性初始化 VarsCache
ensureVarCache(var_cache_, m_tags_.size());
for (size_t i = 0; i < m_tags_.size(); i++) {
auto idx = std::to_string(i + 1);
double value = 0.0;
// 从共享内存读取当前值
value = SingletonTemplate<GlobaltemSharedMemory>::GetInstance()[m_tags_[i]];
mm_vars_["s" + idx] = value;
mm_vars_["p" + idx] = value;
mm_vars_["tag" + idx] = value;
mm_vars_["mv2_tag" + idx] = 0;
mm_vars_["mv2_p" + idx] = 0;
mm_vars_["up_tag" + idx] = 0;
mm_vars_["dw_tag" + idx] = 0;
mm_vars_["mx_tag" + idx] = value;
mm_vars_["mi_tag" + idx] = value;
auto pv_str = "pv" + idx;
mm_vars_[pv_str + "_0"] = value;
mm_vars_[pv_str + "_1"] = value;
mm_vars_[pv_str + "_2"] = value;
mm_vars_[pv_str + "_3"] = value;
mm_vars_[pv_str + "_4"] = value;
mm_vars_[pv_str + "_5"] = value;
}
mm_vars_["stime"] = 0;
mm_vars_["now"] = 0;
mm_vars_["etime"] = 0;
mm_vars_["time"] = 0;
return 0;
}