Skip to content

Commit 5779b47

Browse files
authored
Renew greedy ambiguity solver (#923)
* Fix conflicts * Change header file from track_state to track_candidate * Use unique measurement ID to avoid potential huge memory allocation * Do not use cache for relative number of shared measurements * Fix typo * Fix type conversion issue * Use meas ids instead of track candidates * Add more test * Fix format
1 parent 7911e66 commit 5779b47

13 files changed

+1004
-655
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ Demonstrator tracking chain for accelerators.
1313
| | Seed finding |||||||
1414
| | Track param estimation |||||||
1515
| **Track finding** | Combinatorial KF |||| 🟡 |||
16-
| **Track fitting** | KF ||| 🟡 ||||
1716
| **Ambiguity resolution** | Greedy resolver |||||||
17+
| **Track fitting** | KF ||| 🟡 ||||
1818

1919
✅: exists, 🟡: work started, ⚪: work not started yet
2020

core/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,11 @@ traccc_add_library( traccc_core core TYPE SHARED
115115
"src/seeding/silicon_pixel_spacepoint_formation_algorithm_defdet.cpp"
116116
"src/seeding/silicon_pixel_spacepoint_formation_algorithm_teldet.cpp"
117117
# Ambiguity resolution
118+
"include/traccc/ambiguity_resolution/ambiguity_resolution_config.hpp"
118119
"include/traccc/ambiguity_resolution/greedy_ambiguity_resolution_algorithm.hpp"
119-
"src/ambiguity_resolution/greedy_ambiguity_resolution_algorithm.cpp" )
120+
"src/ambiguity_resolution/greedy_ambiguity_resolution_algorithm.cpp"
121+
"include/traccc/ambiguity_resolution/legacy/greedy_ambiguity_resolution_algorithm.hpp"
122+
"src/ambiguity_resolution/legacy/greedy_ambiguity_resolution_algorithm.cpp")
120123
target_link_libraries( traccc_core
121124
PUBLIC Eigen3::Eigen vecmem::core detray::core detray::detectors
122125
traccc::algebra ActsCore )
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/** TRACCC library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2025 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#pragma once
9+
10+
// System include(s).
11+
#include <cstdint>
12+
#include <limits>
13+
14+
namespace traccc {
15+
16+
/// Configuration struct for ambiguity resolution
17+
struct ambiguity_resolution_config {
18+
19+
/// Minimum number of measurement to form a track.
20+
unsigned int min_meas_per_track = 3;
21+
22+
/// Max iteration to remove the bad tracks
23+
unsigned int max_iterations = std::numeric_limits<unsigned int>::max();
24+
25+
/// Max shared measurements to break the iteration
26+
unsigned int max_shared_meas = 1;
27+
};
28+
29+
} // namespace traccc
Lines changed: 22 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,165 +1,56 @@
11
/** TRACCC library, part of the ACTS project (R&D line)
22
*
3-
* (c) 2024 CERN for the benefit of the ACTS project
3+
* (c) 2025 CERN for the benefit of the ACTS project
44
*
55
* Mozilla Public License Version 2.0
66
*/
77

88
#pragma once
99

10-
// System include
11-
#include <algorithm>
12-
#include <initializer_list>
13-
#include <iostream>
14-
#include <limits>
15-
#include <map>
16-
#include <set>
17-
#include <unordered_map>
18-
#include <vector>
19-
20-
// VecMem include(s).
21-
#include <vecmem/containers/vector.hpp>
22-
2310
// Project include(s).
24-
#include "traccc/definitions/qualifiers.hpp"
11+
#include "traccc/ambiguity_resolution/ambiguity_resolution_config.hpp"
2512
#include "traccc/edm/track_candidate.hpp"
26-
#include "traccc/edm/track_state.hpp"
2713
#include "traccc/utils/algorithm.hpp"
14+
#include "traccc/utils/memory_resource.hpp"
2815
#include "traccc/utils/messaging.hpp"
2916

30-
// Greedy ambiguity resolution adapted from ACTS code
31-
32-
namespace traccc {
17+
namespace traccc::host {
3318

3419
/// Evicts tracks that seem to be duplicates or fakes. This algorithm takes a
3520
/// greedy approach in the sense that it will remove the track which looks "most
36-
/// duplicate/fake" first and continues the same process with the rest. That
37-
/// process continues until the final state conditions are met.
38-
///
39-
/// The implementation works as follows:
40-
/// 1) Calculate shared hits per track.
41-
/// 2) If the maximum shared hits criteria is met, we are done.
42-
/// This is the configurable amount of shared hits we are ok with
43-
/// in our experiment.
44-
/// 3) Else, remove the track with the highest relative shared hits (i.e.
45-
/// shared hits / hits).
46-
/// 4) Back to square 1.
21+
/// duplicate/fake"
4722
class greedy_ambiguity_resolution_algorithm
48-
: public algorithm<track_state_container_types::host(
49-
const typename track_state_container_types::host&)>,
23+
: public algorithm<track_candidate_container_types::host(
24+
const typename track_candidate_container_types::const_view&)>,
5025
public messaging {
5126

5227
public:
53-
struct config_t {
54-
55-
config_t(){};
56-
57-
/// Maximum amount of shared hits per track. One (1) means "no shared
58-
/// hit allowed".
59-
std::uint32_t maximum_shared_hits = 1;
60-
61-
/// Maximum number of iterations.
62-
std::uint32_t maximum_iterations = 1000000;
63-
64-
/// Minimum number of measurement to form a track.
65-
std::size_t n_measurements_min = 3;
66-
67-
// True if obvious errors should be checked after the completion
68-
// of the algorithm.
69-
bool check_obvious_errs = true;
70-
71-
// Displays a warning if:
72-
// (number of measurements of ID 0 / total number of measurements)
73-
// is greater than measurement_id_0_warning_threshold.
74-
float measurement_id_0_warning_threshold = 0.1f;
75-
76-
bool verbose_error = true;
77-
bool verbose_warning = true;
78-
bool verbose_info = false;
79-
bool verbose_debug = false;
80-
};
81-
82-
struct state_t {
83-
std::size_t number_of_tracks{};
84-
85-
/// For this whole comment section, track_index refers to the index of a
86-
/// track in the initial input container.
87-
///
88-
/// There is no (track_id) in this algorithm, only (track_index).
89-
90-
/// Associates each track_index with the track's chi2 value
91-
std::vector<traccc::scalar> track_chi2;
92-
93-
/// Associates each track_index to the track's (measurement_id)s list
94-
std::vector<std::vector<std::size_t>> measurements_per_track;
95-
96-
/// Associates each measurement_id to a set of (track_index)es sharing
97-
/// it
98-
std::unordered_map<std::size_t, std::set<std::size_t>>
99-
tracks_per_measurement;
100-
101-
/// Associates each track_index to its number of shared measurements
102-
/// (among other tracks)
103-
std::vector<std::size_t> shared_measurements_per_track;
104-
105-
/// Keeps the selected tracks indexes that have not (yet) been removed
106-
/// by the algorithm
107-
std::set<std::size_t> selected_tracks;
108-
};
28+
using config_type = ambiguity_resolution_config;
10929

11030
/// Constructor for the greedy ambiguity resolution algorithm
11131
///
11232
/// @param cfg Configuration object
113-
// greedy_ambiguity_resolution_algorithm(const config_type& cfg) :
114-
// _config(cfg) {}
11533
greedy_ambiguity_resolution_algorithm(
116-
const config_t cfg,
34+
const config_type& cfg, traccc::memory_resource& mr,
11735
std::unique_ptr<const Logger> logger = getDummyLogger().clone())
118-
: messaging(std::move(logger)), _config{cfg} {}
36+
: messaging(std::move(logger)), m_config{cfg}, m_mr{mr} {}
11937

12038
/// Run the algorithm
12139
///
122-
/// @param track_states the container of the fitted track parameters
40+
/// @param track_candidates the container of found patterns
12341
/// @return the container without ambiguous tracks
124-
track_state_container_types::host operator()(
125-
const typename track_state_container_types::host& track_states)
126-
const override;
127-
128-
private:
129-
/// Computes the initial state for the input data. This function accumulates
130-
/// information that will later be used to accelerate the ambiguity
131-
/// resolution.
132-
///
133-
/// @param track_states The input track container (output of the fitting
134-
/// algorithm).
135-
/// @param state An empty state object which is expected to be default
136-
/// constructed.
137-
void compute_initial_state(
138-
const typename track_state_container_types::host& track_states,
139-
state_t& state) const;
140-
141-
/// Updates the state iteratively by evicting one track after the other
142-
/// until the final state conditions are met.
143-
///
144-
/// @param state A state object that was previously filled by the
145-
/// initialization.
146-
void resolve(state_t& state) const;
42+
track_candidate_container_types::host operator()(
43+
const track_candidate_container_types::const_view&
44+
track_candidates_view) const override;
14745

148-
/// Check for obvious errors returned by the algorithm:
149-
/// - Returned tracks should be independent of each other: they should share
150-
/// a maximum of (_config.maximum_shared_hits - 1) hits per track.
151-
/// - Each removed track should share at least (_config.maximum_shared_hits)
152-
/// with another initial track.
153-
///
154-
/// @param initial_track_states The input track container, as given to
155-
/// compute_initial_state.
156-
/// @param final_state The state object after the resolve method has been
157-
/// called.
158-
bool check_obvious_errors(
159-
const typename track_state_container_types::host& initial_track_states,
160-
state_t& final_state) const;
46+
/// Get configuration
47+
config_type& get_config() { return m_config; }
16148

162-
config_t _config;
49+
private:
50+
/// Algorithm configuration
51+
config_type m_config;
52+
/// The memory resource to use
53+
traccc::memory_resource m_mr;
16354
};
16455

165-
} // namespace traccc
56+
} // namespace traccc::host
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/** TRACCC library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2024 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#pragma once
9+
10+
// System include
11+
#include <algorithm>
12+
#include <initializer_list>
13+
#include <iostream>
14+
#include <limits>
15+
#include <map>
16+
#include <set>
17+
#include <unordered_map>
18+
#include <vector>
19+
20+
// VecMem include(s).
21+
#include <vecmem/containers/vector.hpp>
22+
23+
// Project include(s).
24+
#include "traccc/definitions/qualifiers.hpp"
25+
#include "traccc/edm/track_candidate.hpp"
26+
#include "traccc/edm/track_state.hpp"
27+
#include "traccc/utils/algorithm.hpp"
28+
#include "traccc/utils/messaging.hpp"
29+
30+
// Greedy ambiguity resolution adapted from ACTS code
31+
32+
namespace traccc::legacy {
33+
34+
/// Evicts tracks that seem to be duplicates or fakes. This algorithm takes a
35+
/// greedy approach in the sense that it will remove the track which looks "most
36+
/// duplicate/fake" first and continues the same process with the rest. That
37+
/// process continues until the final state conditions are met.
38+
///
39+
/// The implementation works as follows:
40+
/// 1) Calculate shared hits per track.
41+
/// 2) If the maximum shared hits criteria is met, we are done.
42+
/// This is the configurable amount of shared hits we are ok with
43+
/// in our experiment.
44+
/// 3) Else, remove the track with the highest relative shared hits (i.e.
45+
/// shared hits / hits).
46+
/// 4) Back to square 1.
47+
class greedy_ambiguity_resolution_algorithm
48+
: public algorithm<track_candidate_container_types::host(
49+
const typename track_candidate_container_types::host&)>,
50+
public messaging {
51+
52+
public:
53+
struct config_t {
54+
55+
config_t(){};
56+
57+
/// Maximum amount of shared hits per track. One (1) means "no shared
58+
/// hit allowed".
59+
std::uint32_t maximum_shared_hits = 1;
60+
61+
/// Maximum number of iterations.
62+
std::uint32_t maximum_iterations = 1000000;
63+
64+
/// Minimum number of measurement to form a track.
65+
std::size_t n_measurements_min = 3;
66+
};
67+
68+
struct state_t {
69+
std::size_t number_of_tracks{};
70+
71+
/// For this whole comment section, track_index refers to the index of a
72+
/// track in the initial input container.
73+
///
74+
/// There is no (track_id) in this algorithm, only (track_index).
75+
76+
/// Associates each track_index with the track's chi2 value
77+
std::vector<traccc::scalar> track_chi2;
78+
79+
/// Associates each track_index to the track's (measurement_id)s list
80+
std::vector<std::vector<std::size_t>> measurements_per_track;
81+
82+
/// Associates each measurement_id to a set of (track_index)es sharing
83+
/// it
84+
std::unordered_map<std::size_t, std::set<std::size_t>>
85+
tracks_per_measurement;
86+
87+
/// Associates each track_index to its number of shared measurements
88+
/// (among other tracks)
89+
std::vector<std::size_t> shared_measurements_per_track;
90+
91+
/// Keeps the selected tracks indexes that have not (yet) been removed
92+
/// by the algorithm
93+
std::set<std::pair<std::size_t, std::size_t>> selected_tracks;
94+
};
95+
96+
/// Constructor for the greedy ambiguity resolution algorithm
97+
///
98+
/// @param cfg Configuration object
99+
// greedy_ambiguity_resolution_algorithm(const config_type& cfg) :
100+
// _config(cfg) {}
101+
greedy_ambiguity_resolution_algorithm(
102+
const config_t cfg,
103+
std::unique_ptr<const Logger> logger = getDummyLogger().clone())
104+
: messaging(std::move(logger)), _config{cfg} {}
105+
106+
/// Run the algorithm
107+
///
108+
/// @param track_states the container of the fitted track parameters
109+
/// @return the container without ambiguous tracks
110+
track_candidate_container_types::host operator()(
111+
const typename track_candidate_container_types::host& track_states)
112+
const override;
113+
114+
/// Get configuration
115+
config_t& get_config() { return _config; }
116+
117+
private:
118+
/// Computes the initial state for the input data. This function accumulates
119+
/// information that will later be used to accelerate the ambiguity
120+
/// resolution.
121+
///
122+
/// @param track_states The input track container (output of the fitting
123+
/// algorithm).
124+
/// @param state An empty state object which is expected to be default
125+
/// constructed.
126+
void compute_initial_state(
127+
const typename track_candidate_container_types::host& track_states,
128+
state_t& state) const;
129+
130+
/// Updates the state iteratively by evicting one track after the other
131+
/// until the final state conditions are met.
132+
///
133+
/// @param state A state object that was previously filled by the
134+
/// initialization.
135+
void resolve(state_t& state) const;
136+
137+
config_t _config;
138+
};
139+
140+
} // namespace traccc::legacy

0 commit comments

Comments
 (0)