KIDS  ver-0.0.1
KIDS : Kernel Integrated Dynamics Simulator
Loading...
Searching...
No Matches
RuleEvaluator.cpp
Go to the documentation of this file.
2
3#include <iostream>
4#include <regex>
5#include <string>
6#include <vector>
7
8#include "kids/Einsum.h"
9#include "kids/Expression.h"
10#include "kids/debug_utils.h"
11
12namespace PROJECT_NS {
13
20template <typename T, typename Tout>
22 Expression<T>& FP, //
23 const std::vector<void*>& data_inputs, //
24 const std::vector<kids_dtype>& data_idtype, //
25 Tout* data_output //
26) {
27 auto& einsum_dims = EH.einsum_dims;
28 auto& einsum_iposes = EH.einsum_iposes;
29 auto& ipos_inputs = EH.ipos_inputs;
30 // ipos_output
31 auto& dh_inputs = EH.dh_inputs;
32 auto& dh_output_mapldims = EH.dh_output.mapldims;
33
34 std::size_t total_loop = EH.total_loop;
35 std::size_t total_tensor = EH.total_tensor;
36 std::size_t total_esidx = EH.total_esidx;
37 std::size_t imax = EH.count3 - 1;
38 std::size_t imin = EH.count1;
39
40 std::vector<T> holder(total_tensor); // temporary vector
41
42 memset(einsum_iposes.data(), 0, total_esidx * sizeof(std::size_t));
43 memset(ipos_inputs.data(), 0, total_tensor * sizeof(std::size_t));
44 bool reset_zero = true;
45 for (std::size_t iloop = 0, ipos_output = 0; iloop < total_loop; ++iloop) {
46 if (reset_zero) data_output[ipos_output] = Tout(0);
47
48 for (int iten = 0; iten < total_tensor; ++iten) { //
49 switch (data_idtype[iten]) {
50 case kids_int_type:
51 holder[iten] = cast_at<T, kids_int>(data_inputs[iten], ipos_inputs[iten]);
52 break;
53 case kids_real_type:
54 holder[iten] = cast_at<T, kids_real>(data_inputs[iten], ipos_inputs[iten]);
55 break;
56 case kids_complex_type: {
57 holder[iten] = cast_at<T, kids_complex>(data_inputs[iten], ipos_inputs[iten]);
58 break;
59 }
60 }
61 }
62 data_output[ipos_output] += cast<Tout>(FP.evaluate(holder.data()));
63
64 std::size_t i = imax;
65 while (++einsum_iposes[i] == einsum_dims[i] && i > imin) { einsum_iposes[i--] = 0; }
66
67 for (int iten = 0; iten < total_tensor; ++iten) //
68 ipos_inputs[iten] += dh_inputs[iten].mapldims[i];
69 ipos_output += dh_output_mapldims[i];
70 }
71}
72
73RuleEvaluator::RuleEvaluator(const std::string& rule, std::shared_ptr<DataSet>& DS, //
74 const std::string& mode, const std::string& save, //
75 std::size_t totalFrameNumber)
76
77 : rule{rule}, mode{mode}, save{save}, totalFrameNumber{totalFrameNumber}, numCollects{0} {
78 // here "=" is the separator
79 auto ipos = rule.find("=");
80 std::string vars_str = (ipos == std::string::npos) ? rule : rule.substr(0, ipos);
81 expressionString = (ipos == std::string::npos) ? "" : rule.substr(ipos + 1, rule.size());
82 expressionString.erase(0, expressionString.find_first_not_of(" "));
83 expressionString.erase(expressionString.find_last_not_of(" ") + 1);
84
85 // here "(,)" are the separators
86 ipos = vars_str.find("(");
87 std::string res0_str = (ipos == std::string::npos) ? vars_str : vars_str.substr(0, ipos);
88 res0_str.erase(0, res0_str.find_first_not_of(" "));
89 res0_str.erase(res0_str.find_last_not_of(" ") + 1);
90 result = std::shared_ptr<VariableDescriptor>(new VariableDescriptor(res0_str));
91 result->field = "result";
92 collect = std::shared_ptr<VariableDescriptor>(new VariableDescriptor(res0_str));
93 collect->field = "collect";
94 reduced = std::shared_ptr<VariableDescriptor>(new VariableDescriptor(res0_str));
95 reduced->field = "reduced";
96
97 vars_str = (ipos == std::string::npos) ? vars_str : vars_str.substr(ipos + 1, vars_str.size());
98 char ch = 'a';
99 while ((ipos = vars_str.find(",")) != std::string::npos || //
100 (ipos = vars_str.find(")")) != std::string::npos) {
101 std::string item_str = vars_str.substr(0, ipos);
102 item_str.erase(0, item_str.find_first_not_of(" "));
103 item_str.erase(item_str.find_last_not_of(" ") + 1);
104 vars_str = vars_str.substr(ipos + 1, vars_str.size());
105 auto instance = VariableDescriptor(item_str);
106 instance.referIn(DS);
107 variables.push_back(std::move(instance));
108 }
109 if (variables.size() == 0) {
110 auto instance = VariableDescriptor(res0_str);
111 instance.referIn(DS);
112 variables.push_back(std::move(instance));
113 }
114
115 // built einsum information
116 einsumString = "";
117 for (int i = 0, shift = 0; i < variables.size(); ++i) {
118 if (i != 0) einsumString += ",";
119 if (variables[i].index == "") { // update index if necessary
120 for (int k = 0; k < variables[i].shape->rank(); ++k) { variables[i].index += (char) ((int) 'a' + shift++); }
121 }
122 einsumString += variables[i].index;
123 inputShapes.push_back(variables[i].shape->dims());
124 inputData.push_back(variables[i].dataPointer);
125 inputDataTypes.push_back(variables[i].dataType);
126 }
127 if (result->index != "") einsumString += utils::concat("->", result->index);
128 einsumHelper = std::shared_ptr<EinsumHelper>(new EinsumHelper(einsumString, inputShapes));
129
130 // define result in dataset
132 for (auto& v : variables) {
133 if (v.dataType != kids_int_type && v.dataType != kids_real_type && v.dataType != kids_complex_type)
134 throw kids_error("access bad type");
135 if (v.dataType > expressionType) expressionType = v.dataType;
136 }
137 kids_dtype res_type = (result->dataType == kids_void_type) ? expressionType : result->dataType;
138
139 std::vector<std::size_t> res_cxxshape;
140 res_cxxshape.push_back(totalFrameNumber);
141 totalTermNumber = 1;
142 for (auto& i : einsumHelper->dh_output.dims) {
143 totalTermNumber *= i;
144 res_cxxshape.push_back(i);
145 }
146
147 result->defineIn(DS, res_type, res_cxxshape);
148 collect->defineIn(DS, res_type, res_cxxshape);
149 reduced->defineIn(DS, res_type, res_cxxshape);
150
151 // built expression
152 if (expressionString == "") { // check if expression is trivial
153 expressionCheck = (variables.size() == 1) ? -1 : -2;
154 for (int i = 0; i < variables.size(); ++i) { //
155 expressionString += (i == 0) ? utils::concat("_", i) : utils::concat(" * _", i);
156 }
157 } else {
158 expressionCheck = 0;
159 }
160 // anyway, we define a corresponding expression (even if it is trivial)
161 std::vector<std::string> varslist;
162 for (int i = 0; i < variables.size(); ++i) varslist.push_back(utils::concat("_", i));
163 switch (expressionType) {
164 case kids_real_type: {
166 break;
167 }
168 case kids_complex_type: {
170 break;
171 }
172 }
173
174#ifdef LOCAL_DEBUG
175 std::cout //
176 << LOC() << "RuleEvaluator Data:\n" //
177 << ".totalTermNumber = " << totalTermNumber << "\n"
178 << ".totalFrameNumber = " << totalFrameNumber << "\n"
179 << ".rule = " << rule << "\n"
180 << ".mode = " << mode << "\n"
181 << ".path = " << path << "\n"
182 << ".save = " << save << "\n"
183 << ".result = " << result
184 << "\n"
185 // << ".variables = " << variables << "\n" /**< Variables in the expression. */
186 // << ".inputShapes = " << inputShapes << "\n" /**< Shapes of input data. */
187 // << ".inputData = " << inputData << "\n" /**< Input data. */
188 // << ".inputDataTypes = " << inputDataTypes << "\n" /**< Data types of input data. */
189 << ".expressionString" << expressionString
190 << "\n"
191 // << ".einsumHelper = " << einsumHelper << "\n" /**< Shared pointer to EinsumHelper. */
192 << ".einsumString = " << einsumString << "\n"
193 << ".expressionType = " << expressionType << "\n"
194 << ".expressionId = " << expressionId << "\n";
196 for (int i = 0; i < inputDataTypes.size(); ++i) std::cout << inputDataTypes[i] << ",";
197 std::cout << result->shape->size() << "\n";
198
199#endif // LOCAL_DEBUG
200}
201
202void RuleEvaluator::calculateResult(int sampleIndex) {
203 sampleIndex = sampleIndex % totalFrameNumber;
204 size_t initialIndex = sampleIndex * totalTermNumber;
205
206 // fast calculation for the special case: only copy data
207 if (expressionCheck == -1) {
208 if (result->dataType == kids_real_type) {
209 kids_real* resdata = (kids_real*) (result->dataPointer) + initialIndex;
210 kids_real* vardata = (kids_real*) (variables[0].dataPointer);
211 for (int i = 0; i < totalTermNumber; ++i) resdata[i] = vardata[i];
212 }
213 if (result->dataType == kids_complex_type) {
214 kids_complex* resdata = (kids_complex*) (result->dataPointer) + initialIndex;
215 kids_complex* vardata = (kids_complex*) (variables[0].dataPointer);
216 for (int i = 0; i < totalTermNumber; ++i) resdata[i] = vardata[i];
217 }
218 return;
219 }
220
221 // fast calculation for the special case: only use usual einsum
222 if (expressionCheck == -2 && false) { // not safe of reinterpret_cast!
223 if (result->dataType == kids_real_type) {
224 kids_real* resdata = (kids_real*) (result->dataPointer) + initialIndex;
225 std::vector<kids_real*> inputDataR;
226 for (int i = 0; i < inputData.size(); ++i) inputDataR.push_back((kids_real*) inputData[i]);
227 einsum<kids_real>(*einsumHelper, inputDataR, resdata);
228 }
229 if (result->dataType == kids_complex_type) {
230 kids_complex* resdata = (kids_complex*) (result->dataPointer) + initialIndex;
231 std::vector<kids_complex*> inputDataC;
232 for (int i = 0; i < inputData.size(); ++i) inputDataC.push_back((kids_complex*) inputData[i]);
233 einsum<kids_complex>(*einsumHelper, inputDataC, resdata);
234 }
235 return;
236 }
237
238 switch (expressionType) {
239 case kids_real_type: {
241 if (result->dataType == kids_real_type) {
242 kids_real* resdata = (kids_real*) (result->dataPointer) + initialIndex;
244 }
245 if (result->dataType == kids_complex_type) {
246 kids_complex* resdata = (kids_complex*) (result->dataPointer) + initialIndex;
248 }
249 break;
250 }
251 case kids_complex_type: {
253 if (result->dataType == kids_real_type) {
254 kids_real* resdata = (kids_real*) (result->dataPointer) + initialIndex;
256 }
257 if (result->dataType == kids_complex_type) {
258 kids_complex* resdata = (kids_complex*) (result->dataPointer) + initialIndex;
260 }
261 break;
262 }
263 }
264}
265
267 switch (result->dataType) {
268 case kids_real_type: {
269 kids_real* fromdata = (kids_real*) result->dataPointer;
270 kids_real* todata = (kids_real*) collect->dataPointer;
271 if (mode == "copy" || numCollects == 0) {
272 for (int i = 0; i < result->shape->size(); ++i) todata[i] = fromdata[i];
273 } else if (mode == "sum") {
274 for (int i = 0; i < result->shape->size(); ++i) todata[i] += fromdata[i];
275 } else if (mode == "average") {
277 kids_real k2 = 1.0e0 - k1;
278 for (int i = 0; i < result->shape->size(); ++i) todata[i] = k1 * todata[i] + k2 * fromdata[i];
279 }
280 break;
281 }
282 case kids_complex_type: {
283 kids_complex* fromdata = (kids_complex*) result->dataPointer;
284 kids_complex* todata = (kids_complex*) collect->dataPointer;
285 if (mode == "copy" || numCollects == 0) {
286 for (int i = 0; i < result->shape->size(); ++i) todata[i] = fromdata[i];
287 } else if (mode == "sum") {
288 for (int i = 0; i < result->shape->size(); ++i) todata[i] += fromdata[i];
289 } else if (mode == "average") {
291 kids_real k2 = 1.0e0 - k1;
292 for (int i = 0; i < result->shape->size(); ++i) todata[i] = k1 * todata[i] + k2 * fromdata[i];
293 }
294 break;
295 }
296 }
297 numCollects++;
298}
299
300void RuleEvaluator::writeTo(std::ofstream& ofs, void* data, int sampleIndex) {
301 switch (result->dataType) {
302 case kids_real_type: {
303 kids_real* resdata = (kids_real*) (data) + sampleIndex * totalTermNumber;
304 for (int i = 0; i < totalTermNumber; ++i) ofs << FMT(8) << resdata[i];
305 break;
306 }
307 case kids_complex_type: {
308 kids_complex* resdata = (kids_complex*) (data) + sampleIndex * totalTermNumber;
309 for (int i = 0; i < totalTermNumber; ++i) ofs << FMT(8) << real(resdata[i]) << FMT(8) << imag(resdata[i]);
310 break;
311 }
312 }
313}
314
315}; // namespace PROJECT_NS
this file provides einsum operation
this file provide expression & parser
provide RuleEvaluator class
std::vector< DimenHelper > dh_inputs
DimenHelper for input tensors.
Definition Einsum.h:190
std::vector< std::size_t > einsum_dims
each dimension of EinsumIdx System
Definition Einsum.h:183
DimenHelper dh_output
DimenHelper for ouput tensor.
Definition Einsum.h:191
std::vector< std::size_t > einsum_iposes
idx placeholder for EinsumIdx System
Definition Einsum.h:193
std::size_t total_esidx
total number of EinsumIdx in EinsumIdx System
Definition Einsum.h:179
std::size_t total_tensor
total number of tensor in einsum rule
Definition Einsum.h:180
std::vector< std::size_t > ipos_inputs
idx placeholder for input tensors
Definition Einsum.h:194
A class representing a mathematical expression.
Definition Expression.h:50
static int registerExpression(const std::string &expression, const std::vector< std::string > &variables)
Register a new mathematical expression.
Definition Expression.h:69
static std::vector< Expression< T > > & getExpressions()
Get the list of registered expressions.
Definition Expression.h:57
T evaluate(T *data)
Evaluate the expression with given variable values.
Definition Expression.h:85
provide utils for debugging the code
#define LOC()
show the location information for debug
Definition fmt.h:49
#define FMT(X)
Definition fmt.h:40
< http://warp.povusers.org/FunctionParser/fparser.html
Definition Context.h:39
@ kids_real_type
Represents real number type.
Definition Types.h:47
@ kids_complex_type
Represents complex number type.
Definition Types.h:48
@ kids_int_type
Represents integer type.
Definition Types.h:46
@ kids_void_type
Represents void type.
Definition Types.h:44
double kids_real
Alias for real number type.
Definition Types.h:59
std::complex< double > kids_complex
Alias for complex number type.
Definition Types.h:60
void einsum_fun(EinsumHelper &EH, Expression< T > &FP, const std::vector< void * > &data_inputs, const std::vector< kids_dtype > &data_idtype, Tout *data_output)
custumized einsum-like function operation
std::basic_string< CharT > concat(const separator_t< CharT > &sep, Args &&... seq)
Definition concat.h:242
std::vector< std::size_t > mapldims
utils for sum of several leading dimensions as the shift step
Definition Einsum.h:164
std::shared_ptr< VariableDescriptor > result
Result of the expression.
void writeTo(std::ofstream &ofs, void *data, int sampleIndex)
Writes the results to a file stream.
std::string rule
The expression rule.
std::vector< kids_dtype > inputDataTypes
Data types of input data.
std::string mode
The mode of evaluation.
std::shared_ptr< EinsumHelper > einsumHelper
Shared pointer to EinsumHelper.
std::vector< void * > inputData
Input data.
std::string expressionString
String representation of the expression.
std::vector< std::vector< std::size_t > > inputShapes
Shapes of input data.
void calculateResult(int sampleIndex=0)
Calculates the expression at a particular time slice.
std::size_t totalTermNumber
Number of terms.
std::shared_ptr< VariableDescriptor > reduced
collect of Result
std::shared_ptr< VariableDescriptor > collect
collect of Result
std::string save
File name to save results.
std::size_t numCollects
Number of Collects.
std::vector< VariableDescriptor > variables
Variables in the expression.
kids_dtype expressionType
Type of the expression.
RuleEvaluator(const std::string &rule, std::shared_ptr< DataSet > &DS, const std::string &mode, const std::string &save, std::size_t totalFrameNumber)
Constructs an RuleEvaluator object.
size_t expressionId
ID of the expression.
std::string einsumString
String representation of expression type.
int expressionCheck
ID of the expression.
std::size_t totalFrameNumber
Number of samples.
Represents a variable token in an expression rule.