Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Comparision.hxx
Go to the documentation of this file.
1
2#ifndef TMVA_SOFIE_ROperator_Comparision
3#define TMVA_SOFIE_ROperator_Comparision
4
6#include "TMVA/ROperator.hxx"
7#include "TMVA/RModel.hxx"
8
9#include <sstream>
10
11namespace TMVA{
12namespace Experimental{
13namespace SOFIE{
14
16
17template <typename T, EComparisionOperator Op1>
19
20template <typename T>
21struct ComparisionTrait<T, Eq> {
22 static const std::string Name() { return "Equal"; }
23 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " == " + t2; }
24 static bool Result(T v1, T v2) { return v1 == v2;}
25};
26
27template <typename T>
29 static const std::string Name() { return "Less"; }
30 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " < " + t2; }
31 static bool Result(T v1, T v2) { return v1 < v2;}
32};
33
34template <typename T>
36 static const std::string Name() { return "LessOrEqual"; }
37 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " <= " + t2; }
38 static bool Result(T v1, T v2) { return v1 <= v2;}
39};
40
41template <typename T>
43 static const std::string Name() { return "Greater"; }
44 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " > " + t2; }
45 static bool Result(T v1, T v2) { return v1 > v2;}
46};
47
48template <typename T>
50 static const std::string Name() { return "GreaterOrEqual"; }
51 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " >= " + t2 ; }
52 static bool Result(T v1, T v2) { return v1 >= v2;}
53};
54
55template<typename T, EComparisionOperator Op>
57private:
58
59 bool fIsModelOutput = false;
60 std::string fNX1;
61 std::string fNX2;
62 std::string fNY;
63 std::vector<size_t> fShapeX1;
64 std::vector<size_t> fShapeX2;
65 std::vector<Dim> fDimShapeX1;
66 std::vector<Dim> fDimShapeX2;
67 std::vector<size_t> fShapeY;
68 std::string fNBroadcastedX1;
69 std::string fNBroadcastedX2;
72 bool fBroadcast = false;
73
74
75public:
77 ROperator_Comparision(const std::string & nameX1, const std::string & nameX2, const std::string & nameY):
78 fNX1(UTILITY::Clean_name(nameX1)), fNX2(UTILITY::Clean_name(nameX2)), fNY(UTILITY::Clean_name(nameY)){
80
81 // output will be a boolean vector so should not be considered for memory optimized pool
83 }
84
85 // type of output given input
86 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input) override {
87 return input;
88 }
89
90 // shape of output tensors given input tensors
91 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input) override {
92 auto ret = input; // return vector size 1 with first input
93 return ret;
94 }
95
96 void Initialize(RModel& model) override {
97 // input must be a graph input, or already initialized intermediate tensor
99 throw std::runtime_error(std::string("TMVA SOFIE Comparision Op Input Tensor ") + fNX1 + "is not found in model");
100 }
101 if (!model.CheckIfTensorAlreadyExist(fNX2)) {
102 throw std::runtime_error(std::string("TMVA SOFIE Comparision Op Input Tensor ") + fNX2 + "is not found in model");
103 }
104 if (model.IsDynamicTensor(fNX1))
106 else {
109 }
110 if (model.IsDynamicTensor(fNX2))
112 else {
115 }
119 if (broadcast) {
120 // Y is the common shape of A and B
124 // Broadcast A to Y
125 if (broadcastX1) {
126 if (model.IsInitializedTensor(fNX1)) {
127 auto data = model.GetInitializedTensorData(fNX1);
128 std::shared_ptr<void> broadcastedData(
129 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeX1, fShapeY),
130 std::default_delete<T[]>());
131 // Update the data and the shape of A
134 } else {
135 // Add an intermediate tensor for broadcasting A
136 fNBroadcastedX1 = "Broadcasted" + fNX1;
138 }
139 }
140 // Broadcast B to Y
141 if (broadcastX2) {
142 if (model.IsInitializedTensor(fNX2)) {
143 auto data = model.GetInitializedTensorData(fNX2);
144 std::shared_ptr<void> broadcastedData(
145 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeX2, fShapeY),
146 std::default_delete<T[]>());
147 // Update the data and the shape of B
150 } else {
151 // Add an intermediate tensor for broadcasting B
152 fNBroadcastedX2 = "Broadcasted" + fNX2;
154 }
155 }
156 } else {
158 }
159 // case of constant tensors
160 T * data1 = nullptr;
161 T * data2 = nullptr;
162 std::vector<Dim> shapeData1;
163 std::vector<Dim> shapeData2;
165 bool * outData = new bool[length];
166 if (model.IsInitializedTensor(fNX1)) {
167 data1 = static_cast<T *>(model.GetInitializedTensorData(fNX1).get());
168 } else if (model.IsShapeTensor(fNX1)) {
170 }
171 if (model.IsInitializedTensor(fNX2)) {
172 data2 = static_cast<T *>(model.GetInitializedTensorData(fNX2).get());
173 } else if (model.IsShapeTensor(fNX2)) {
175 }
176 if (data1 && data2) {
177 fIsOutputConstant = true;
178 for (size_t i = 0; i < length; i++)
181 if (model.Verbose())
182 std::cout << ComparisionTrait<T,Op>::Name() << " op ---> " << fNY << " " << ConvertShapeToString(fShapeY) << " : "
183 << ConvertValuesToString(length,outData) << std::endl;
184 } else if ((data1 || !shapeData1.empty()) && (data2 || !shapeData2.empty())) {
185 fIsOutputConstant = true;
186 if (data1 && !data2) {
187 // data 1 is constant and data2 is shape
188 for (size_t i = 0; i < length; i++) {
189 if (shapeData2[i].isParam) {
190 if (shapeData2[i].dim == size_t(-1) || data1[i] > 0) {
191 fIsOutputConstant = false;
192 break;
193 } else {
194 // assume a comparison is done with .dim = 0
195 shapeData2[i].dim = 0;
196 }
197 }
198 outData[i] = ComparisionTrait<T,Op>::Result(data1[i], static_cast<T>(shapeData2[i].dim));
199 }
200 } else if (!data1 && data2) {
201 // data 1 is shape and dat2 is constant
202 for (size_t i = 0; i < length; i++) {
203 if (shapeData1[i].isParam) {
204 if (shapeData1[i].dim == size_t(-1) || data2[i] > 0) {
205 fIsOutputConstant = false;
206 break;
207 } else {
208 // assume a comparison is done with .dim = 0
209 shapeData1[i].dim = 0;
210 }
211 }
212 outData[i] = ComparisionTrait<T,Op>::Result(static_cast<T>(shapeData1[i].dim), data2[i]);
213 }
214 } else if (!shapeData1.empty() && !shapeData2.empty() ) {
215 // both data1 and data2 are shape tensors
216 for (size_t i = 0; i < length; i++) {
217 if (!shapeData1[i].isParam && !shapeData2[i].isParam) {
219 }
220 else if (shapeData1[i].isParam && shapeData2[i].isParam) {
221 if (shapeData1[i].param == shapeData2[i].param)
222 outData[i] = ComparisionTrait<int,Op>::Result(1,1); // comparison of two equal value
223 else {
224 fIsOutputConstant = false;
225 break;
226 }
227 }
228 else {
229 fIsOutputConstant = false;
230 break;
231 }
232 }
233 }
234 if (fIsOutputConstant) {
236 if (model.Verbose())
237 std::cout << ComparisionTrait<T,Op>::Name() << " op ---> " << fNY << " " << ConvertShapeToString(fShapeY) << " : "
238 << ConvertValuesToString(length,outData) << " (constant) " << std::endl;
239
240 }
241 }
242 delete [] outData;
243 if (!fIsOutputConstant) {
245 if (model.Verbose())
246 std::cout << ComparisionTrait<T,Op>::Name() << " op ---> " << fNY << " " << ConvertShapeToString(fShapeY) << std::endl;
247 }
248
249 // check if this is not output operators to add a specific line for definining the tensor_xxx variable
250 const auto & outputTensorNames = model.GetOutputTensorNames();
251 fIsModelOutput = false;
253 fIsModelOutput = true;
254 }
255
256 std::string Generate(std::string opName) override {
257 if (fIsOutputConstant) return "";
258 opName = "op_" + opName;
259
260 if (fShapeY.empty()) {
261 throw std::runtime_error("TMVA SOFIE Comparision Op called to Generate without being initialized first");
262 }
263 std::stringstream out;
264 out << SP << "\n//------ " << ComparisionTrait<T,Op>::Name() << " " << opName
265 << " --> " << ConvertShapeToString(fShapeY) << "\n";
267 // Broadcast A if it's uninitialized
268 if (!fNBroadcastedX1.empty()) {
270 out << SP << "// Broadcasting uninitialized tensor " << fNX1 << "\n";
271 out << SP << "{\n";
272 out << SP << SP << type1 << "* data = TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << type1 << ">(tensor_" << fNX1 << ", " << ConvertShapeToString(fShapeX1) << ", " << ConvertShapeToString(fShapeY) << ");\n";
273 out << SP << SP << "std::copy(data, data + " << length << ", tensor_" << fNBroadcastedX1 << ");\n";
274 out << SP << SP << "delete[] data;\n";
275 out << SP << "}\n";
276 }
277 // Broadcast B if it's uninitialized
278 if (!fNBroadcastedX2.empty()) {
280 out << SP << "// Broadcasting uninitialized tensor " << fNX2 << "\n";
281 out << SP << "{\n";
282 out << SP << SP << type2 << "* data = TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << type2 << ">(tensor_" << fNX2 << ", " << ConvertShapeToString(fShapeX2) << ", " << ConvertShapeToString(fShapeY) << ");\n";
283 out << SP << SP << "std::copy(data, data + " << length << ", tensor_" << fNBroadcastedX2 << ");\n";
284 out << SP << SP << "delete[] data;\n";
285 out << SP << "}\n";
286 }
287 const std::string& nameX1 = fNBroadcastedX1.empty()? fNX1 : fNBroadcastedX1;
288 const std::string& nameX2 = fNBroadcastedX2.empty()? fNX2 : fNBroadcastedX2;
289
290 out << SP << "for (size_t id = 0; id < " << length << " ; id++){\n";
291 out << SP << SP << "fTensor_" << fNY << "[id] = " << ComparisionTrait<T,Op>::Op( "tensor_" + nameX1 + "[id]" , "tensor_" + nameX2 + "[id]") << " ;\n";
292 out << SP << "}\n";
293 // since output is a boolean need to add the tensor_xxx variable since it is not defined as a pointer to a boolean std::vector
294 if (!fIsModelOutput)
295 out << SP << "const std::vector<std::uint8_t> & tensor_" << fNY << " = fTensor_" << fNY << ";\n";
296
297 return out.str();
298 }
299
300};
301
302}//SOFIE
303}//Experimental
304}//TMVA
305
306
307#endif //TMVA_SOFIE_ROperator_Comparision
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
const_iterator begin() const
const_iterator end() const
std::vector< size_t > GetTensorShape(const std::string &name) const
Definition RModel.cxx:29
bool IsDynamicTensor(const std::string &name) const
Definition RModel.cxx:232
const std::vector< std::string > & GetOutputTensorNames() const
Definition RModel.hxx:202
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:247
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:122
void AddConstantTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:193
bool IsShapeTensor(const std::string &name) const
check if a tensor is a shape tensor
Definition RModel.cxx:211
bool IsInitializedTensor(const std::string &name) const
Definition RModel.cxx:220
std::vector< Dim > GetDynamicTensorShape(const std::string &name) const
Definition RModel.cxx:76
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:312
ETensorType GetTensorType(std::string name) const
Definition RModel.cxx:90
void UpdateInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:303
const std::vector< Dim > & GetShapeTensorValues(const std::string &tensor_name) const
Definition RModel.cxx:215
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input) override
std::string Generate(std::string opName) override
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input) override
ROperator_Comparision(const std::string &nameX1, const std::string &nameX2, const std::string &nameY)
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:47
bool fIsOutputConstant
flag to identify if operator has a constant output (no need to generate code)
Definition ROperator.hxx:44
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:42
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:48
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
std::vector< size_t > UnidirectionalBroadcastShape(std::vector< size_t > &, std::vector< size_t > &)
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
std::vector< Dim > ConvertShapeToDim(const std::vector< size_t > &shape)
Convert shape from integer format to dynamic one (based on Dim)
std::string ConvertValuesToString(size_t n, const T *data)
std::string ConvertTypeToString(ETensorType type)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
auto * t1
Definition textangle.C:20