5 #include "ExaTrkXUtils.hpp" 
    8 #include <boost/graph/adjacency_list.hpp> 
    9 #include <boost/graph/topological_sort.hpp> 
   10 #include <boost/graph/connected_components.hpp> 
   11 #include <boost/graph/graphviz.hpp> 
   12 #include <boost/property_map/property_map.hpp> 
   13 #include <boost/graph/graph_utility.hpp> 
   14 #include <boost/graph/graph_traits.hpp> 
   19     const std::vector<float>& embedFeatures,
 
   20     std::vector<int64_t>& senders,
 
   21     std::vector<int64_t>& receivers,
 
   22     int64_t numSpacepoints,
 
   37     auto squaredDistance = [&](int64_t 
i, int64_t j) {
 
   39         for (
int d = 0; 
d < embeddingDim; ++
d) {
 
   40             float diff = embedFeatures[
i * embeddingDim + 
d] - embedFeatures[j * embeddingDim + 
d];
 
   49     for (int64_t 
i = 0; 
i < numSpacepoints; 
i++) {
 
   51         std::priority_queue<std::pair<float, int64_t>> nearestNeighbors;
 
   53         for (int64_t j = 
i + 1; j < numSpacepoints; j++) {
 
   55             float distSquared = squaredDistance(
i, j);
 
   56             if (distSquared <= radiusSquared) {
 
   57                 nearestNeighbors.push({distSquared, j});
 
   59                 if (nearestNeighbors.size() > (
unsigned long) kVal) {
 
   60                     nearestNeighbors.pop();
 
   65         while (!nearestNeighbors.empty()) {
 
   67             receivers.push_back(nearestNeighbors.top().second);
 
   68             nearestNeighbors.pop();
 
   74     vertex_t numSpacepoints,
 
   75     const std::vector<int64_t>& rowIndices,
 
   76     const std::vector<int64_t>& colIndices,
 
   77     const std::vector<weight_t>& edgeWeights,
 
   78     std::vector<std::vector<uint32_t> >& tracks,
 
   79     float ccCut, 
float walkMin, 
float walkMax
 
   82     std::map<vertex_t, bool> used_hits;
 
   84     for (vertex_t 
i = 0; 
i < numSpacepoints; 
i++) {
 
   88     for(
size_t idx=0; 
idx < rowIndices.size(); ++
idx) {
 
   89         add_edge(rowIndices[
idx], colIndices[
idx], edgeWeights[
idx], 
G);
 
   95     UndirectedGraph ugraph;
 
   97     for (
auto v : boost::make_iterator_range(vertices(newG))) {
 
   99         add_vertex(
name, ugraph);
 
  102     auto [edge_b, edge_e] = boost::edges(newG);
 
  103     for (
auto it = edge_b; 
it != edge_e; ++
it) {
 
  109     std::vector<std::vector<vertex_t>> sub_graphs = 
getSimplePath(ugraph);
 
  111     for (
const auto& 
track : sub_graphs) {
 
  112         for (
auto hit_id : 
track) {
 
  113             used_hits[hit_id] = 
true;
 
  117     std::vector<Vertex> topo_order;
 
  118     boost::topological_sort(newG, std::back_inserter(topo_order));
 
  121     auto next_node_fn = [&](
const Graph &
G, vertex_t current_hit) {
 
  126     for(
auto it = topo_order.rbegin(); 
it != topo_order.rend(); ++
it) {
 
  128         int hit_id = 
boost::get(boost::vertex_name, newG, node_id);
 
  129         if (used_hits[hit_id]) 
continue;
 
  132         auto roads = 
buildRoads(newG, node_id, next_node_fn, used_hits);
 
  133         used_hits[node_id] = 
true;
 
  139         std::vector<int>& longest_road = *std::max_element(roads.begin(), roads.end(),
 
  140             [](
const std::vector<int> &
a, 
const std::vector<int> &
b) {
 
  141                 return a.size() < b.size();
 
  144         if (longest_road.size() >= 3) {
 
  145             std::vector<vertex_t> 
track;
 
  146             for (
int node_id : longest_road) {
 
  147                 auto hit_id = 
boost::get(boost::vertex_name, newG, node_id);
 
  148                 used_hits[hit_id] = 
true;
 
  149                 track.push_back(hit_id);
 
  151             sub_graphs.push_back(std::move(
track));
 
  157     for (
const auto& 
track : sub_graphs) {
 
  158         std::vector<uint32_t> this_track{
track.begin(), 
track.end()};
 
  159         tracks.push_back(std::move(this_track));
 
  165     std::vector<std::vector<vertex_t>> final_tracks;
 
  167     std::vector<vertex_t> component(num_vertices(
G));
 
  168     size_t num_components = boost::connected_components(
G, &component[0]);
 
  170     std::vector<std::vector<Vertex> > component_groups(num_components);
 
  171     for(
size_t i = 0; 
i < component.size(); ++
i) {
 
  172         component_groups[component[
i]].push_back(
i);
 
  176     for(
const auto& sub_graph : component_groups) {
 
  177         if (sub_graph.size() < 3) {
 
  180         bool is_signal_path = 
true;
 
  182         for (
int node : sub_graph) {
 
  184                 is_signal_path = 
false;
 
  190         if (is_signal_path) {
 
  191             std::vector<vertex_t> 
track;
 
  192             for (
int node : sub_graph) {
 
  194                 track.push_back(hit_id);
 
  196             final_tracks.push_back(std::move(
track));
 
  204     vertex_t current_hit,
 
  208     std::vector<vertex_t> next_hits;
 
  209     auto [
begin, 
end] = boost::out_edges(current_hit, 
G);
 
  211     std::vector<std::pair<vertex_t, double>> neighbors_scores;
 
  216         if (neighbor == current_hit || 
score <= th_min) 
continue;
 
  217         neighbors_scores.push_back({neighbor, 
score});
 
  220     if (neighbors_scores.empty()) 
return {};
 
  223     auto best_neighbor = *std::max_element(neighbors_scores.begin(), neighbors_scores.end(),
 
  224                                       [](
const std::pair<int, double> &
a, 
const std::pair<int, double> &
b) {
 
  225                                           return a.second < b.second;
 
  229     for (
const auto &neighbor : neighbors_scores) {
 
  230         if (neighbor.second > th_add) {
 
  231             next_hits.push_back(neighbor.first);
 
  236     if (next_hits.empty()) {
 
  237         next_hits.push_back(best_neighbor.first);
 
  245     vertex_t starting_node,
 
  246     std::function<std::vector<vertex_t>(
const Graph&, vertex_t)> next_node_fn,
 
  247     std::map<vertex_t, bool>& used_hits
 
  249     std::vector<std::vector<int>> 
path = {{starting_node}};
 
  252         std::vector<std::vector<int>> new_path;
 
  253         bool is_all_done = 
true;
 
  255         for (
const auto &pp : 
path) {
 
  256             vertex_t 
start = pp.back();
 
  259                 new_path.push_back(pp);
 
  263             auto next_hits = next_node_fn(
G, 
start);
 
  265             next_hits.erase(std::remove_if(next_hits.begin(), next_hits.end(),
 
  267                     auto hit_id = boost::get(boost::vertex_name, G, node_id);
 
  268                     return used_hits[hit_id];
 
  269                 }), next_hits.end());
 
  271             if (next_hits.empty()) {
 
  272                 new_path.push_back(pp);
 
  275                 for (
int nh : next_hits) {
 
  276                     std::vector<int> pp_extended = pp;
 
  277                     pp_extended.push_back(nh);
 
  278                     new_path.push_back(std::move(pp_extended));
 
  283         path = std::move(new_path);
 
  284         if (is_all_done) 
break;
 
  294     std::map<vertex_t, vertex_t> old_vertex_to_new;
 
  295     vertex_t old_vertex_id = 0;
 
  296     vertex_t new_vertex_id = 0;
 
  297     for (
auto v : boost::make_iterator_range(vertices(
G))) {
 
  299         if (in_degree(
v, 
G) == 0 && out_degree(
v, 
G) == 0) {
 
  303         add_vertex(
name, newG);
 
  304         old_vertex_to_new[old_vertex_id] = new_vertex_id;
 
  309     auto [edge_b, edge_e] = boost::edges(
G);
 
  310     for (
auto it = edge_b; 
it != edge_e; ++
it) {
 
  316         if (
weight <= ccCut) 
continue;
 
  323     int64_t numSpacepoints,
 
  324     const std::vector<int64_t>& rowIndices,
 
  325     const std::vector<int64_t>& colIndices,
 
  326     std::vector<float>& edgeFeatures
 
  339     int64_t numFeatures = gNodeFeatures.size() / numSpacepoints;
 
  340     edgeFeatures.clear();
 
  341     edgeFeatures.reserve(rowIndices.size() * 6);
 
  342     auto diffPhi = [](
float phi1, 
float phi2) {
 
  343         float dphi = (phi1 - phi2) * 
M_PI;
 
  346         } 
else if (dphi <= -
M_PI) {
 
  351     for (
size_t idx = 0; 
idx < rowIndices.size(); ++
idx) {
 
  352         int64_t 
src = rowIndices[
idx];
 
  353         int64_t dst = colIndices[
idx];
 
  354         std::vector<float> src_features(gNodeFeatures.begin() + 
src * numFeatures, 
 
  355                                         gNodeFeatures.begin() + 
src * numFeatures + 4);
 
  356         std::vector<float> dst_features(gNodeFeatures.begin() + dst * numFeatures, 
 
  357                                         gNodeFeatures.begin() + dst * numFeatures + 4);
 
  359         float dr = dst_features[0] - src_features[0];
 
  360         float dphi = diffPhi(dst_features[1], src_features[1]);
 
  361         float dz = dst_features[2] - src_features[2];
 
  362         float deta = dst_features[3] - src_features[3];
 
  363         float phislope = (fabs(
dr) > 1
e-7) ? dphi / 
dr : 0.;
 
  364         float rphislope = (fabs(phislope) > 1
e-7) ? (dst_features[0] + src_features[0]) / 2 * phislope : 0.0; 
 
  366         edgeFeatures.push_back(
dr);
 
  367         edgeFeatures.push_back(dphi);
 
  368         edgeFeatures.push_back(dz);
 
  369         edgeFeatures.push_back(deta);
 
  370         edgeFeatures.push_back(phislope);
 
  371         edgeFeatures.push_back(rphislope);