#ifdef __CLING__
#endif
#include "encoder.hxx"
#include "core.hxx"
#include "decoder.hxx"
#include "output_transform.hxx"
double check_mem(std::string s = ""){
printf("%s - ",s.c_str());
printf(" Rmem = %8.3f MB, Vmem = %8.f3 MB \n",
);
}
template<class T>
size_t nrows = (shape.size() > 1) ? shape[0] : 1;
size_t ncols = (shape.size() > 1) ? t.
GetStrides()[0] : shape[0];
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
if (j==ncols-1) {
if (j>10) std::cout << "... ";
std::cout << *p << std::endl;
}
else if (j<10)
std::cout << *p << ", ";
p++;
}
}
std::cout << std::endl;
}
if (!txt.empty()) std::cout << std::endl << txt << std::endl;
std::cout <<
"node data:"; PrintTensor(
d.node_data);
std::cout <<
"edge data:"; PrintTensor(
d.edge_data);
std::cout <<
"global data:"; PrintTensor(
d.global_data);
std::cout <<
"edge index:"; PrintTensor(
d.edge_index);
}
struct SOFIE_GNN {
TMVA_SOFIE_encoder::Session encoder;
TMVA_SOFIE_core::Session core;
TMVA_SOFIE_decoder::Session decoder;
TMVA_SOFIE_output_transform::Session output_transform;
std::vector<GNN_Data> Infer(const GNN_Data & data, int nsteps) {
auto input_data =
Copy(data);
if (verbose)
Print(input_data,
"input_data");
encoder.infer(input_data);
auto latent0 =
Copy(input_data);
GNN_Data latent = input_data;
std::vector<GNN_Data> outputData;
for (int i = 0; i < nsteps; i++) {
if (verbose)
Print(latent0,
"input decoded data");
if (verbose)
Print(latent,
"latent data");
if (verbose)
Print(core_input,
"after concatenate");
core.infer(core_input);
if (verbose)
Print(core_input,
"after core inference");
latent =
Copy(core_input);
decoder.infer(core_input);
output_transform.infer(core_input);
outputData.push_back(
Copy(core_input));
}
return outputData;
}
};
const int num_max_nodes = 10;
const int num_max_edges = 30;
const int NODE_FEATURE_SIZE = 4;
const int EDGE_FEATURE_SIZE = 4;
const int GLOBAL_FEATURE_SIZE = 1;
std::vector<GNN_Data> GenerateData(int nevts, int seed) {
std::vector<GNN_Data> dataSet;
dataSet.reserve(nevts);
for (int i = 0; i < nevts; i++) {
size_t num_nodes =
r.Integer(num_max_nodes-2) + 2;
size_t num_edges =
r.Integer(num_max_edges-1) + 1;
auto genValue = [&]() {
return r.Rndm()*10 -5; };
auto genLink = [&] () {
return r.Integer(num_nodes);};
dataSet.emplace_back(gd);
}
return dataSet;
}
std::vector<GNN_Data> ReadData(std::string treename, std::string filename) {
int nevts = ndata.GetPtr()->
size();
std::vector<GNN_Data> dataSet;
dataSet.reserve(nevts);
for (int i = 0; i < nevts; i++) {
auto &
n = (*(ndata.GetPtr()))[i];
size_t num_nodes =
n.size()/NODE_FEATURE_SIZE;
auto &
e = (*(edata.GetPtr()))[i];
size_t num_edges =
e.size()/EDGE_FEATURE_SIZE;
auto &
g = (*(gdata.GetPtr()))[i];
auto &
r = (*(rdata.GetPtr()))[i];
auto & s = (*(sdata.GetPtr()))[i];
dataSet.emplace_back(
Copy(gd));
if (i < 1 && verbose)
Print(dataSet[i],
"Input for Event" + std::to_string(i));
}
return dataSet;
}
void TMVA_SOFIE_GNN_Application (bool verbose = false)
{
check_mem("Initial memory");
SOFIE_GNN gnn;
check_mem("After creating GNN");
const int seed = 111;
const int nproc_steps = 5;
int nevts;
std::cout << "reading data\n";
auto inputData = ReadData("gdata","graph_data.root");
nevts = inputData.size();
auto h1 =
new TH1D(
"h1",
"SOFIE Node data",40,1,0);
auto h2 =
new TH1D(
"h2",
"SOFIE Edge data",40,1,0);
auto h3 =
new TH1D(
"h3",
"SOFIE Global data",40,1,0);
std::cout << "doing inference...\n";
check_mem("Before evaluating");
for (int i = 0; i < nevts; i++) {
auto result = gnn.Infer(inputData[i], nproc_steps);
auto & lr = result.back();
if (i < 1 && verbose)
Print(lr,
"Output for Event" + std::to_string(i));
h2->Fill(
TMath::Mean(lr.edge_data.begin(), lr.edge_data.end()));
h3->Fill(
TMath::Mean(lr.global_data.begin(), lr.global_data.end()));
}
w.Stop();
w.Print();
check_mem("End evaluation");
auto c2 =
new TCanvas(
"c2",
"Reference Results");
auto o1 = file->Get("h1");
auto o2 = file->Get("h2");
auto o3 = file->Get("h3");
}
#define R__ADD_INCLUDE_PATH(PATH)
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...
A "std::vector"-like collection of values implementing handy operation to analyse them.
RTensor is a container with contiguous memory and shape information.
const Shape_t & GetStrides() const
std::size_t GetSize() const
Iterator begin() noexcept
const Shape_t & GetShape() const
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
1-D histogram with a double per channel (see TH1 documentation)
Random number generator class based on M.
RVec< Common_t > Concatenate(const RVec< T0 > &v0, const RVec< T1 > &v1)
Return the concatenation of two RVecs.
void Copy(void *source, void *dest)
void Print(std::ostream &os, const OptionType &opt)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
GNN_Data Copy(const GNN_Data &data)
Double_t Mean(Long64_t n, const T *a, const Double_t *w=nullptr)
Returns the weighted mean of an array a with length n.
RTensor< float > global_data
RTensor< float > edge_data
RTensor< int > edge_index
RTensor< float > node_data