1 #ifndef BARRY_DEFM_MOTIF_FORMULA_HPP
2 #define BARRY_DEFM_MOTIF_FORMULA_HPP
48 std::vector< size_t > & locations,
49 std::vector< bool > & signs,
52 std::string & covar_name,
60 std::regex pattern_intercept(
61 std::string(
"\\{\\s*[01]?y[0-9]+(_[0-9]+)?(\\s*,\\s*[01]?y[0-9]+(_[0-9]+)?)*\\s*\\}") +
62 std::string(
"(\\s*x\\s*[^\\s]+([(].+[)])?\\s*)?")
64 std::regex pattern_transition(
65 std::string(
"\\{\\s*[01]?y[0-9]+(_[0-9]+)?(\\s*,\\s*[01]?y[0-9]+(_[0-9]+)?)*\\}\\s*(>)\\s*") +
66 std::string(
"\\{\\s*[01]?y[0-9]+(_[0-9]+)?(\\s*,\\s*[01]?y[0-9]+(_[0-9]+)?)*\\s*\\}") +
67 std::string(
"(\\s*x\\s*[^\\s]+([(].+[)])?\\s*)?")
70 auto empty = std::sregex_iterator();
74 std::vector< bool > selected((m_order + 1) * y_ncol,
false);
77 std::regex_match(formula, match, pattern_transition);
82 throw std::logic_error(
"Transition effects are only valid when the data is a markov process.");
85 std::regex pattern_conditional(
".+[}]\\s+x\\s+([^(]+)([(][^)]+[)])?\\s*$");
86 std::smatch condmatch;
87 std::regex_match(formula, condmatch, pattern_conditional);
89 if (!condmatch.empty())
91 covar_name = condmatch[1].str();
92 vname = condmatch[2].str();
96 vname = vname.substr(1, vname.size() - 2);
101 size_t arrow_position = match.position(4u);
104 std::regex pattern(
"(0?)y([0-9]+)(_([0-9]+))?");
106 auto iter = std::sregex_iterator(formula.begin(), formula.end(), pattern);
108 for (
auto i = iter;
i != empty; ++
i)
112 size_t current_location =
i->position(0u);
115 bool is_positive =
true;
116 if (
i->operator[](1u).str() ==
"0")
120 size_t y_col = std::stoul(
i->operator[](2u).str());
122 throw std::logic_error(
"The proposed column is out of range.");
126 std::string tmp_str =
i->operator[](4u).str();
133 if (current_location > arrow_position)
136 throw std::logic_error(
"LHS of transition must specify time when m_order > 1");
139 y_row = std::stoul(tmp_str);
142 throw std::logic_error(
"The proposed row is out of range.");
149 y_row = std::stoul(tmp_str);
151 y_row = (current_location < arrow_position ? 0u: 1u);
155 if (selected[y_col * (m_order + 1) + y_row])
156 throw std::logic_error(
157 "The term " +
i->str() +
" shows more than once in the formula.");
161 if ((current_location > arrow_position) && (y_row != m_order))
162 throw std::logic_error(
163 "Only the row " + std::to_string(m_order) +
164 " can be specified at the RHS of the motif."
167 selected[y_col * (m_order + 1) + y_row] =
true;
169 locations.push_back(y_col * (m_order + 1) + y_row);
170 signs.push_back(is_positive);
179 std::regex_match(formula, match, pattern_intercept);
184 std::regex pattern_conditional(
".+[}]\\s+x\\s+([^(]+)([(][^)]+[)])?\\s*$");
185 std::smatch condmatch;
186 std::regex_match(formula, condmatch, pattern_conditional);
188 if (!condmatch.empty())
190 covar_name = condmatch[1].str();
191 vname = condmatch[2].str();
195 vname = vname.substr(1, vname.size() - 2);
199 std::regex pattern(
"(0?)y([0-9]+)(_([0-9]+))?");
201 auto iter = std::sregex_iterator(formula.begin(), formula.end(), pattern);
203 for (
auto i = iter;
i != empty; ++
i)
207 bool is_positive =
true;
208 if (
i->operator[](1u).str() ==
"0")
212 size_t y_col = std::stoul(
i->operator[](2u).str());
214 throw std::logic_error(
"The proposed column is out of range.");
218 if (
i->operator[](4u).str() ==
"")
222 y_row = std::stoul(
i->operator[](4u).str());
224 if (y_row != m_order)
225 throw std::logic_error(
226 std::string(
"Intercept motifs cannot feature past events. ") +
227 std::string(
"Only transition motifs can: {...} > {...}.")
232 if (selected[y_col * (m_order + 1) + y_row])
233 throw std::logic_error(
234 "The term " +
i->str() +
" shows more than once in the formula.");
236 selected[y_col * (m_order + 1) + y_row] =
true;
238 locations.push_back(y_col * (m_order + 1) + y_row);
239 signs.push_back(is_positive);
248 throw std::logic_error(
249 "The motif specified in the formula: " + formula +
250 " has the wrong syntax."