Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_ArgMax.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_ARGMAX
2#define TMVA_SOFIE_ROPERATOR_ARGMAX
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <sstream>
9#include <stdexcept>
10#include <string>
11#include <vector>
12
13namespace TMVA {
14namespace Experimental {
15namespace SOFIE {
16
17class ROperator_ArgMax final : public ROperator {
18private:
19 /* Attributes */
20 int64_t fAttrAxis = 0;
21 int fKeepdims = 1;
23
24 /* Tensor names */
25 std::string fNX; // input
26 std::string fNY; // output
27
28 /* Tensor shapes */
29 std::vector<Dim> fShapeX;
30 std::vector<Dim> fShapeY;
31
32public:
34 ROperator_ArgMax(int64_t axis, int keepdims, int selectLastIndex, std::string nameX, std::string nameY)
35 : fAttrAxis(axis),
36 fKeepdims(keepdims),
37 fSelectLastIndex(selectLastIndex),
38 fNX(UTILITY::Clean_name(nameX)),
39 fNY(UTILITY::Clean_name(nameY))
40 {
43 }
44
45 void Initialize(RModel &model) override
46 {
47 if (!model.CheckIfTensorAlreadyExist(fNX)) {
48 throw std::runtime_error("TMVA SOFIE ArgMax Op Input Tensor " + fNX + " is not found in model");
49 }
50 fShapeX = model.GetDimTensorShape(fNX);
51 int64_t rank = static_cast<int64_t>(fShapeX.size());
52
53 // negative axis counts from the end (e.g. -1 is the last dimension)
54 if (fAttrAxis < 0) {
55 fAttrAxis += rank;
56 }
57 // valid range is [-rank, rank-1], i.e. [0, rank-1] after normalization
58 if (fAttrAxis < 0 || fAttrAxis >= rank) {
59 throw std::runtime_error("TMVA SOFIE ArgMax Op - invalid axis value " + std::to_string(fAttrAxis) +
60 " for input tensor " + fNX + " of rank " + std::to_string(rank));
61 }
62
63 // compute output shape: reduced axis becomes 1 (keepdims) or is removed
65 if (fKeepdims != 0) {
66 fShapeY[fAttrAxis] = Dim{1};
67 } else {
68 fShapeY.erase(fShapeY.begin() + fAttrAxis);
69 }
70 // output contains indices, so its type is always INT64 regardless of the input type
71 model.AddIntermediateTensor(fNY, ETensorType::INT64, fShapeY);
72 }
73
74 std::string Generate(std::string opName) override
75 {
76 // split the input shape around the axis: [outer..., axisDim, inner...]
77 std::string outer = ConvertDimShapeToLength(std::vector<Dim>(fShapeX.begin(), fShapeX.begin() + fAttrAxis));
78 std::string axisDim = fShapeX[fAttrAxis].GetVal();
79 std::string inner = ConvertDimShapeToLength(std::vector<Dim>(fShapeX.begin() + fAttrAxis + 1, fShapeX.end()));
80
81 // element (o, k, i) of the input is at o * axisDim * inner + k * inner + i
82 std::string stride = "(" + axisDim + ") * (" + inner + ")";
83 // with '>' ties keep the first index, with '>=' they move to the last one
84 std::string cmp = (fSelectLastIndex != 0) ? ">=" : ">";
85
86 std::stringstream out;
87 out << "\n//------ ArgMax " << opName << "\n";
88 out << SP << "for (size_t o = 0; o < " << outer << "; o++) {\n";
89 out << SP << SP << "for (size_t i = 0; i < " << inner << "; i++) {\n";
90 out << SP << SP << SP << "size_t base = o * " << stride << " + i;\n";
91 out << SP << SP << SP << "auto greatest = tensor_" << fNX << "[base];\n";
92 out << SP << SP << SP << "int64_t bestIndex = 0;\n";
93 out << SP << SP << SP << "for (size_t k = 1; k < " << axisDim << "; k++) {\n";
94 out << SP << SP << SP << SP << "auto value = tensor_" << fNX << "[base + k * (" << inner << ")];\n";
95 out << SP << SP << SP << SP << "if (value " << cmp << " greatest) {\n";
96 out << SP << SP << SP << SP << SP << "greatest = value;\n";
97 out << SP << SP << SP << SP << SP << "bestIndex = static_cast<int64_t>(k);\n";
98 out << SP << SP << SP << SP << "}\n";
99 out << SP << SP << SP << "}\n";
100 out << SP << SP << SP << "tensor_" << fNY << "[o * (" << inner << ") + i] = bestIndex;\n";
101 out << SP << SP << "}\n";
102 out << SP << "}\n";
103 return out.str();
104 }
105};
106
107} // namespace SOFIE
108} // namespace Experimental
109} // namespace TMVA
110
111#endif // TMVA_SOFIE_ROPERATOR_ARGMAX
std::string Generate(std::string opName) override
ROperator_ArgMax(int64_t axis, int keepdims, int selectLastIndex, std::string nameX, std::string nameY)
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:44
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:40
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:45
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
create variable transformations