Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Where.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROperator_Where
2#define TMVA_SOFIE_ROperator_Where
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <sstream>
9
10namespace TMVA{
11namespace Experimental{
12namespace SOFIE{
13
14
15
16template<typename T>
18private:
19
20 bool fIsInputBoolTensor = false;
21
22
23 std::string fNA;
24 std::string fNB;
25 std::string fNC;
26 std::string fNBroadcastedA;
27 std::string fNBroadcastedB;
28 std::string fNBroadcastedC;
29 std::string fNY;
30
31
32 std::vector<size_t> fShapeA;
33 std::vector<size_t> fShapeB;
34 std::vector<size_t> fShapeC;
35 std::vector<size_t> fShapeY;
36
37
38public:
40 ROperator_Where(const std::string & nameA, const std::string & nameB, const std::string & nameC, const std::string & nameY):
41 fNA(UTILITY::Clean_name(nameA)), fNB(UTILITY::Clean_name(nameB)), fNC(UTILITY::Clean_name(nameC)), fNY(UTILITY::Clean_name(nameY)){
44 }
45
46 // type of output given input
47 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input) override {
48 return input;
49 }
50
51 // shape of output tensors given input tensors
52 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input) override {
53 // assume now inputs have same shape (no broadcasting)
54 auto ret = std::vector<std::vector<size_t>>(1, input[0]); // return vector size 1 with first input
55 return ret;
56 }
57
58 void Initialize(RModel& model) override {
59 // input must be a graph input, or already initialized intermediate tensor
60 if (!model.CheckIfTensorAlreadyExist(fNA)){
61 throw std::runtime_error(std::string("TMVA SOFIE Where Op Input Tensor ") + fNA + "is not found in model");
62 }
63 if (!model.CheckIfTensorAlreadyExist(fNB)) {
64 throw std::runtime_error(std::string("TMVA SOFIE Where Op Input Tensor ") + fNB + "is not found in model");
65 }
66 if (!model.CheckIfTensorAlreadyExist(fNC)) {
67 throw std::runtime_error(std::string("TMVA SOFIE Where Op Input Tensor ") + fNC + "is not found in model");
68 }
69 // check if fNC input tensor is boolean
70 if (model.IsReadyInputTensor(fNC))
71 fIsInputBoolTensor = true;
72 // check broadcast for A, B and C
73 fShapeA = model.GetTensorShape(fNA);
74 fShapeB = model.GetTensorShape(fNB);
75 fShapeC = model.GetTensorShape(fNC);
77 if (broadcast) {
78 // find shape to broadcast between A,B,C looking for max length
82 bool broadcastA = false, broadcastB = false, broadcastC = false;
83 if (lengthA >= lengthB && lengthA >= lengthC) {
85 //broadcast B and C if different than A
88 }
89 else if (lengthB >= lengthA && lengthB >= lengthC) {
91 //broadcast A and C if different than B
94 }
95 else if (lengthC >= lengthA && lengthC >= lengthB) {
97 //broadcast A and B if different than C
100 }
101
102 // Broadcast A to Y
103 if (broadcastA) {
104 fNBroadcastedA = "BC_" + fNA + "_to_" + fNY;
105 if (model.IsInitializedTensor(fNA)) {
106 auto data = model.GetInitializedTensorData(fNA);
107 std::shared_ptr<void> broadcastedData(
108 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeA, fShapeY),
109 std::default_delete<T[]>());
110 // Update the data and the shape of A
113 } else {
114 // Add an intermediate tensor for broadcasting A
116 }
117 }
118 // Broadcast B to Y
119 if (broadcastB) {
120 fNBroadcastedB = "BC_" + fNB + "_to_" + fNY;
121 if (model.IsInitializedTensor(fNB)) {
122 auto data = model.GetInitializedTensorData(fNB);
123 std::shared_ptr<void> broadcastedData(
124 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeB, fShapeY),
125 std::default_delete<T[]>());
126 // do not update tensor B but add broadcasted one (since it can be input to some other operators)
129 } else {
130 // Add an intermediate tensor for broadcasting B
132 }
133 }
134 // Broadcast C to Y
135 if (broadcastC) {
136 fNBroadcastedC = "BC_" + fNC + "_to_" + fNY;
137 if (model.IsInitializedTensor(fNC)) {
138 auto data = model.GetInitializedTensorData(fNC);
139 std::shared_ptr<void> broadcastedData(
140 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeC, fShapeY),
141 std::default_delete<T[]>());
142 // do not update tensor C but add broadcasted one (since it can be input to some other operators)
145 } else {
146 // Add an intermediate tensor for broadcasting B
148 }
149 }
150 } else {
152 }
153 // check case of constant output (if all inputs are defined)
154 if (model.IsInitializedTensor(fNA) && model.IsInitializedTensor(fNB) && model.IsInitializedTensor(fNC)) {
155 std::string nameA = fNBroadcastedA.empty()? fNA : fNBroadcastedA;
156 std::string nameB = fNBroadcastedB.empty()? fNB : fNBroadcastedB;
157 std::string nameC = fNBroadcastedC.empty()? fNC : fNBroadcastedC;
158 auto dataA = static_cast<T *>(model.GetInitializedTensorData(nameA).get());
159 auto dataB = static_cast<T *>(model.GetInitializedTensorData(nameB).get());
160 auto dataC = static_cast<bool *>(model.GetInitializedTensorData(nameC).get());
161 std::vector<T> dataY(ConvertShapeToLength(fShapeY));
162 for (size_t i = 0; i < dataY.size(); i++)
163 dataY[i] = (dataC[i]) ? dataA[i] : dataB[i];
164 model.AddConstantTensor<T>(fNY, fShapeY, dataY.data());
165 // flag tensors to not be written in a file
169
170 fIsOutputConstant = true;
171 if (model.Verbose())
172 std::cout << "Where op ---> " << fNY << " " << ConvertShapeToString(fShapeY) << " : "
173 << ConvertValuesToString(dataY) << std::endl;
174
175 // output is a constant tensor
176 fOutputTensorNames.pop_back();
177 }
178 else {
180 }
181 }
182
183 std::string GenerateInitCode() override {
184 std::stringstream out;
185 return out.str();
186 }
187
188 std::string Generate(std::string OpName) override {
189
190 if (fIsOutputConstant) return "";
191
192 OpName = "op_" + OpName;
193
194 if (fShapeY.empty()) {
195 throw std::runtime_error("TMVA SOFIE Where Op called to Generate without being initialized first");
196 }
197 std::stringstream out;
198 out << SP << "\n//-------- Where \n";
200 std::string typeName = TensorType<T>::Name();
201 // Broadcast A if it's uninitialized
202 if (fShapeA != fShapeY) {
203 out << SP << "// Broadcasting uninitialized tensor " << fNA << "\n";
204 //out << SP << "{\n";
205 out << SP << "TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << typeName << ">(tensor_" << fNA << ", " << ConvertShapeToString(fShapeA) << ", " << ConvertShapeToString(fShapeY)
206 << ", fTensor_" << fNBroadcastedA << ");\n";
207 }
208 // Broadcast B if it's uninitialized
209 if (fShapeB != fShapeY) {
210 out << SP << "// Broadcasting uninitialized tensor " << fNB << "\n";
211 //out << SP << "{\n";
212 out << SP << "TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << typeName << ">(tensor_" << fNB << ", " << ConvertShapeToString(fShapeB) << ", " << ConvertShapeToString(fShapeY)
213 << ", fTensor_" << fNBroadcastedB << ");\n";
214 }
215 // Broadcast C if it's uninitialized
216 if (fShapeC != fShapeY) {
217 // special case if C is an input tensor
218 if (fIsInputBoolTensor) {
220 out << SP << "std::vector<bool> fTensor_" << fNC << "(tensor_" << fNC << ", tensor_" << fNC << " + " << inputLength << ");\n";
221 }
222 out << SP << "// Broadcasting uninitialized tensor " << fNC << "\n";
223 //out << SP << "{\n";
224 // for boolean we need to pass vector<bool> and use the non-template version of the function
225 out << SP << "TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast(fTensor_" << fNC << ", " << ConvertShapeToString(fShapeC) << ", " << ConvertShapeToString(fShapeY)
226 << ", fTensor_" << fNBroadcastedC << ");\n";
227 }
228 std::string nameA = fNBroadcastedA.empty()? fNA : fNBroadcastedA;
229 std::string nameB = fNBroadcastedB.empty()? fNB : fNBroadcastedB;
230 std::string nameC = fNBroadcastedC.empty()? fNC : fNBroadcastedC;
231 out << SP << "for (size_t id = 0; id < " << length << " ; id++){\n";
232 // get output tensor applying condition (note we need to use directly the vector<bool> since v.data(), i.e the data pointer, does not exist)
233 out << SP << SP << "tensor_" << fNY << "[id] = " << "(fTensor_" << nameC << "[id]) ? tensor_"
234 << nameA << "[id] : tensor_" + nameB + "[id];\n";
235 out << SP << "}\n";
236 return out.str();
237 }
238
239};
240
241}//SOFIE
242}//Experimental
243}//TMVA
244
245
246#endif //TMVA_SOFIE_ROperator_Where
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
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:200
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:95
void AddConstantTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:165
const ETensorType & GetTensorType(std::string name) const
Definition RModel.cxx:67
bool IsInitializedTensor(const std::string &name) const
Definition RModel.cxx:175
const std::vector< size_t > & GetTensorShape(std::string name) const
Definition RModel.cxx:29
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:261
void SetNotWritableInitializedTensor(const std::string &tensor_name)
Definition RModel.cxx:270
bool IsReadyInputTensor(const std::string &name) const
Definition RModel.cxx:194
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input) override
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input) override
std::string Generate(std::string OpName) override
ROperator_Where(const std::string &nameA, const std::string &nameB, const std::string &nameC, const std::string &nameY)
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:46
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:47
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
std::string ConvertValuesToString(size_t n, const T *data)
std::string ConvertShapeToString(std::vector< size_t > shape)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations