eis/eqpalg/utility/expression_engine.h

130 lines
3.7 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.h
#pragma once
#include <chrono>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <Eigen/Dense>
#include <eqpalg/utility/HoldTime.h>
#include <eqpalg/utility/StatExp.hpp>
#include <eqpalg/utility/VarsCache.hpp>
#include <mix_cc/ihyper_db.h>
#include <mix_cc/matheval/matheval.hpp>
#include <mix_cc/type/mix_time.h>
using MExp = mix_cc::matheval::Expression;
using TimePoint = std::chrono::system_clock::time_point;
/**
* @brief 统一表达式引擎
*
* 集中管理所有命名表达式的注册、求值、FunVars 状态函数、
* 变量刷新(共享内存/IHDB、hold 变量。
*
* 替代 ExpModule + ExpBase 的表达式管理,消除 is_exp_alg_ 补丁。
*/
class ExpressionEngine {
public:
/**
* @param mm_vars 变量映射(由 AlgBase 持有,此处引用)
* @param m_tags 数据 tag 点列表(由 AlgBase 持有,此处引用)
*/
ExpressionEngine(std::map<std::string, double>& mm_vars,
std::vector<std::string>& m_tags);
~ExpressionEngine() = default;
// 禁止拷贝/移动
ExpressionEngine(const ExpressionEngine&) = delete;
ExpressionEngine& operator=(const ExpressionEngine&) = delete;
// ========== 表达式注册 ==========
/**
* @brief 注册一个命名表达式(自动进行 FunVars 状态函数替换)
* @param name 表达式名称 ("act", "feedback", "result", "pre_result", ...)
* @param raw_exp_str 原始表达式字符串(可含 KeepC(tag1,1) 等状态函数)
* @return 0 成功,-1 失败
*/
int registerExpression(const std::string& name, const std::string& raw_exp_str);
/**
* @brief 注册不带 FunVars 替换的原始表达式
*/
int registerRawExpression(const std::string& name, const std::string& raw_exp_str);
/** 查询表达式是否已注册 */
bool hasExpression(const std::string& name) const { return exps_.count(name) > 0; }
// ========== 表达式求值 ==========
double evaluate(const std::string& name);
bool evaluateBool(const std::string& name);
/**
* @brief 获取变量 map 引用(供外部直接读写)
*/
std::map<std::string, double>& vars() { return mm_vars_; }
// ========== 每周期数据刷新 ==========
void refreshFromMemory(const TimePoint& now_time,
mix_cc::time_range_t& query_time_range);
void 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);
int firstFill(int data_source, TimePoint& now_time,
mix_cc::time_range_t& query_time_range);
// ========== FunVars 控制 ==========
void autoResetFunVars();
void markFunVarsNeedReset();
void forceResetFunVars();
// ========== hold 变量 ==========
void refreshHoldVars();
// ========== 调试 ==========
void printVars(const std::string& exp_str = "");
private:
std::map<std::string, double>& mm_vars_;
std::vector<std::string>& m_tags_;
StatExp::FunVars fun_vars_;
bool fun_vars_need_reset_ = false;
// 表达式注册表
struct ExpEntry {
std::string raw_str;
std::string processed_str;
std::unique_ptr<MExp> ptr;
};
std::map<std::string, ExpEntry> exps_;
// hold(n,T) 变量
std::map<std::string, std::unique_ptr<HoldTime>> hold_times_;
VarsCache var_cache_;
static constexpr size_t PV_NUM = 6;
static void ensureVarCache(VarsCache& vc, size_t tag_count) {
if (vc.tag_num == 0 && tag_count > 0) {
vc.init(tag_count, 6);
}
}
// 内部辅助
int initHoldExpStr(const std::string& exp_str);
};