IVector ode_solver::extract_invariants() { map<Enode*, pair<double, double>> inv_map; for (auto inv : m_invs) { Enode * p = inv->getCdr()->getCdr()->getCdr()->getCdr()->getCar(); Enode * op = p->getCar(); bool pos = true; // Handle Negation if (op->getId() == ENODE_ID_NOT) { p = p->getCdr()->getCar(); op = p->getCar(); pos = false; } switch (op->getId()) { case ENODE_ID_GEQ: case ENODE_ID_GT: // Handle >= & > pos = !pos; case ENODE_ID_LEQ: case ENODE_ID_LT: { // Handle <= & < Enode * lhs = pos ? p->getCdr()->getCar() : p->getCdr()->getCdr()->getCar(); Enode * rhs = pos ? p->getCdr()->getCdr()->getCar() : p->getCdr()->getCar(); if (lhs->isVar() && rhs->isConstant()) { if (inv_map.find(lhs) != inv_map.end()) { inv_map[lhs].second = rhs->getValue(); } else { inv_map.emplace(lhs, make_pair(lhs->getLowerBound(), rhs->getValue())); } } else if (lhs->isConstant() && rhs->isVar()) { if (inv_map.find(rhs) != inv_map.end()) { inv_map[rhs].first = lhs->getValue(); } else { inv_map.emplace(rhs, make_pair(lhs->getValue(), rhs->getUpperBound())); } } else { cerr << "ode_solver::extract_invariant: error:" << p << endl; } } break; default: cerr << "ode_solver::extract_invariant: error" << p << endl; } } IVector ret (m_t_vars.size()); unsigned i = 0; for (auto const & m_t_var : m_t_vars) { if (inv_map.find(m_t_var) != inv_map.end()) { auto inv = interval(inv_map[m_t_var].first, inv_map[m_t_var].second); DREAL_LOG_INFO << "Invariant extracted from " << m_t_var << " = " << inv; ret[i++] = inv; } else { auto inv = interval(m_t_var->getLowerBound(), m_t_var->getUpperBound()); DREAL_LOG_INFO << "Default Invariant set for " << m_t_var << " = " << inv; ret[i++] = inv; } } return ret; }
dreal_expr dreal_get_value(dreal_context c, dreal_expr v) { assert(c); assert(v); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; assert(context.getStatus() == l_True); Enode * var = static_cast<Enode *>(v); const Real & value = var->getValue(); Enode * res = context.mkNum(value); return static_cast<void *>(res); }
ode_solver::ode_solver(SMTConfig& c, Egraph & e, Enode * l_int, vector<Enode*> invs, unordered_map<Enode*, int>& enode_to_rp_id) : m_config(c), m_egraph(e), m_int(l_int), m_invs(invs), m_enode_to_rp_id(enode_to_rp_id), m_stepControl(c.nra_ODE_step), m_time(nullptr) { // Pick the right flow_map (var |-> ODE) using current mode m_mode = l_int->getCdr()->getCar()->getValue(); map<string, Enode *> & flow_map = m_egraph.flow_maps[string("flow_") + to_string(m_mode)]; m_time = l_int->getCdr()->getCdr()->getCdr()->getCar(); string time_str = m_time->getCar()->getName(); // i.e. "time_1" m_step = stoi(time_str.substr(time_str.find_last_of("_") + 1)); // i.e. 1 Enode * var_list = l_int->getCdr()->getCdr()->getCdr()->getCdr(); // Collect _0, _t variables from variable list in integral literal while (!var_list->isEnil()) { string name = var_list->getCar()->getCar()->getName(); size_t second_ = name.find_last_of("_"); size_t first_ = name.find_last_of("_", second_ - 1); string name_prefix, name_postfix; if (first_ == string::npos) { name_prefix = name.substr(0, second_); name_postfix = name.substr(second_); } else { name_prefix = name.substr(0, first_); name_postfix = name.substr(first_); } if (flow_map.find(name_prefix) == flow_map.end()) { cerr << name_prefix << " is not found in flow_map." << endl; assert(flow_map.find(name_prefix) != flow_map.end()); } Enode * rhs = flow_map[name_prefix]; stringstream ss; rhs->print_infix(ss, true, name_postfix); if (rhs->isConstant() && rhs->getValue() == 0.0) { // If RHS of ODE == 0.0, we treat it as a parameter in CAPD m_pars.push_back(var_list->getCar()); m_par_list.push_back(name); } else { // Otherwise, we treat it as an ODE variable. m_0_vars.push_back(var_list->getCar()); m_t_vars.push_back(var_list->getCdr()->getCar()); m_var_list.push_back(name); m_ode_list.push_back(ss.str()); } var_list = var_list->getCdr()->getCdr(); } // join var_list to make diff_var, ode_list to diff_fun_forward string diff_var = ""; if (!m_var_list.empty()) { diff_var = "var:" + join(m_var_list, ", ") + ";"; } string diff_fun_forward = ""; string diff_fun_backward = ""; if (!m_ode_list.empty()) { diff_fun_forward = "fun:" + join(m_ode_list, ", ") + ";"; diff_fun_backward = "fun: -" + join(m_ode_list, ", -") + ";"; } // construct diff_sys_forward (string to CAPD) string diff_par; if (m_par_list.size() > 0) { diff_par = "par:" + join(m_par_list, ", ") + ";"; m_diff_sys_forward = diff_par; m_diff_sys_backward = diff_par; } m_diff_sys_forward += diff_var + diff_fun_forward; m_diff_sys_backward += diff_var + diff_fun_backward; DREAL_LOG_INFO << "diff_par : " << diff_par; DREAL_LOG_INFO << "diff_var : " << diff_var; DREAL_LOG_INFO << "diff_fun_forward : " << diff_fun_forward; DREAL_LOG_INFO << "diff_fun_backward : " << diff_fun_backward; DREAL_LOG_INFO << "diff_sys_forward : " << m_diff_sys_forward; DREAL_LOG_INFO << "diff_sys_backward : " << m_diff_sys_backward; for (auto ode_str : m_ode_list) { string const func_str = diff_par + diff_var + "fun:" + ode_str + ";"; m_funcs.push_back(IFunction(func_str)); }; m_inv = extract_invariants(); }