Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0a24685
Packing blocked errors and detection counts into a single array/struct
draganaurosgrbic Jun 14, 2025
779e7ac
Remove/refactor redundant code
draganaurosgrbic Jun 15, 2025
eff2a15
Minor changes
draganaurosgrbic Jun 16, 2025
4003520
Merge remote-tracking branch 'origin/main' into optimization-cpu
draganaurosgrbic Jun 25, 2025
144affe
Control the number of nodes inserted into priority queue
draganaurosgrbic Jul 1, 2025
02c1066
fix detector beam node skipping implementation
noajshu Jul 1, 2025
6f4b5dd
beam search pruning based on min cost per detector count
draganaurosgrbic Jul 1, 2025
e0d6f2f
Merge branch 'optimization-cpu' of https://github.com/quantumlib/tess…
draganaurosgrbic Jul 7, 2025
b16bc51
Merge remote-tracking branch 'origin/main' into optimization-cpu
draganaurosgrbic Jul 7, 2025
cfd157a
Format src/tesseract.cc file
draganaurosgrbic Jul 7, 2025
97b78eb
Merge branch 'main' into optimization-cpu
draganaurosgrbic Jul 7, 2025
59b73f1
Remove unnecessary code
draganaurosgrbic Jul 8, 2025
bb2ac2b
Merge remote-tracking branch 'origin/main' into optimization-cpu
draganaurosgrbic Jul 8, 2025
d6a5659
Merge branch 'optimization-cpu' of https://github.com/quantumlib/tess…
draganaurosgrbic Jul 8, 2025
29aa98a
Scripts for executing and plotting benchmarks
draganaurosgrbic Jul 10, 2025
d97840d
Remove scripts for benchmarking and plotting
draganaurosgrbic Jul 10, 2025
b1e9fef
Merge branch 'main' into optimization-cpu
LalehB Jul 16, 2025
1cb96cb
Merge branch 'main' into optimization-cpu
draganaurosgrbic Jul 21, 2025
053d286
remove d2e_detcost
draganaurosgrbic Jul 24, 2025
77d7250
Update src/tesseract.cc
draganaurosgrbic Jul 25, 2025
419d8aa
Update src/tesseract.cc
draganaurosgrbic Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 31 additions & 31 deletions src/tesseract.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,20 @@ bool Node::operator>(const Node& other) const {
double TesseractDecoder::get_detcost(
size_t d, const std::vector<DetectorCostTuple>& detector_cost_tuples) const {
double min_cost = INF;
double error_cost;
ErrorCost ec;
DetectorCostTuple dct;

for (size_t ei : d2e[d]) {
ec = error_costs[ei];
dct = detector_cost_tuples[ei];
if (ec.min_cost >= min_cost) break;

dct = detector_cost_tuples[ei];
if (!dct.error_blocked) {
double error_cost = ec.likelihood_cost / dct.detectors_count;
min_cost = std::min(min_cost, error_cost);
error_cost = ec.likelihood_cost / dct.detectors_count;
if (error_cost < min_cost) {
min_cost = error_cost;
}
}
}

Expand Down Expand Up @@ -214,15 +218,15 @@ void TesseractDecoder::flip_detectors_and_block_errors(
}

for (size_t oei : d2e[min_detector]) {
detector_cost_tuples[oei].error_blocked = true;
detector_cost_tuples[oei].error_blocked = 1;
if (!config.at_most_two_errors_per_detector && oei == ei) break;
}

for (size_t d : edets[ei]) {
detectors[d] = !detectors[d];
if (!detectors[d] && config.at_most_two_errors_per_detector) {
for (size_t oei : d2e[d]) {
detector_cost_tuples[oei].error_blocked = true;
detector_cost_tuples[oei].error_blocked = 1;
}
}
}
Expand All @@ -236,7 +240,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,

std::priority_queue<Node, std::vector<Node>, std::greater<Node>> pq;
std::unordered_map<size_t, std::unordered_set<std::vector<char>, VectorCharHash>>
discovered_detectors;
visited_detectors;

std::vector<char> initial_detectors(num_detectors, false);
std::vector<DetectorCostTuple> initial_detector_cost_tuples(num_errors);
Expand Down Expand Up @@ -264,7 +268,6 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
std::vector<size_t> next_errors;
std::vector<char> next_detectors;
std::vector<DetectorCostTuple> next_detector_cost_tuples;
std::vector<DetectorCostTuple> next_next_detector_cost_tuples;

pq.push({initial_cost, min_num_detectors, std::vector<size_t>()});
size_t num_pq_pushed = 1;
Expand Down Expand Up @@ -301,10 +304,8 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
return;
}

if (config.no_revisit_dets &&
!discovered_detectors[node.num_detectors].insert(detectors).second) {
if (config.no_revisit_dets && !visited_detectors[node.num_detectors].insert(detectors).second)
continue;
}

if (config.verbose) {
std::cout.precision(13);
Expand All @@ -330,7 +331,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
min_num_detectors = node.num_detectors;
if (config.no_revisit_dets) {
for (size_t i = min_num_detectors + detector_beam + 1; i <= max_num_detectors; ++i) {
discovered_detectors[i].clear();
visited_detectors[i].clear();
}
}
max_num_detectors = std::min(max_num_detectors, min_num_detectors + detector_beam);
Expand All @@ -355,23 +356,26 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,

if (config.at_most_two_errors_per_detector) {
for (int ei : d2e[min_detector]) {
next_detector_cost_tuples[ei].error_blocked = true;
next_detector_cost_tuples[ei].error_blocked = 1;
}
}

size_t prev_ei = std::numeric_limits<size_t>::max();
std::vector<double> detector_cost_cache(num_detectors, -1);

for (size_t ei : d2e[min_detector]) {
if (detector_cost_tuples[ei].error_blocked) {
continue;
}
if (detector_cost_tuples[ei].error_blocked) continue;

if (prev_ei != std::numeric_limits<size_t>::max()) {
for (int d : edets[prev_ei]) {
int fired = detectors[d] ? 1 : -1;
for (int oei : d2e[d]) {
next_detector_cost_tuples[oei].detectors_count += fired;

if (config.at_most_two_errors_per_detector &&
next_detector_cost_tuples[oei].error_blocked == 2) {
next_detector_cost_tuples[oei].error_blocked = 0;
}
}
}
}
Expand All @@ -380,15 +384,11 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
next_errors = node.errors;
next_errors.push_back(ei);
next_detectors = detectors;
next_detector_cost_tuples[ei].error_blocked = true;
next_detector_cost_tuples[ei].error_blocked = 1;

double next_cost = node.cost + errors[ei].likelihood_cost;
size_t next_num_detectors = node.num_detectors;

if (config.at_most_two_errors_per_detector) {
next_next_detector_cost_tuples = next_detector_cost_tuples;
}

for (int d : edets[ei]) {
next_detectors[d] = !next_detectors[d];
int fired = next_detectors[d] ? 1 : -1;
Expand All @@ -399,17 +399,21 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,

if (!next_detectors[d] && config.at_most_two_errors_per_detector) {
for (size_t oei : d2e[d]) {
next_next_detector_cost_tuples[oei].error_blocked = true;
next_detector_cost_tuples[oei].error_blocked =
next_detector_cost_tuples[oei].error_blocked == 1
? 1
: 2; // we store '2' value to indicate an error that was blocked due to the
// '--at-most-two-error-per-detector' heuristic, in order to revert it in
// the next decoding iteration
}
}
}

if (next_num_detectors > max_num_detectors) continue;

if (config.no_revisit_dets && discovered_detectors[next_num_detectors].find(next_detectors) !=
discovered_detectors[next_num_detectors].end()) {
if (config.no_revisit_dets && visited_detectors[next_num_detectors].find(next_detectors) !=
visited_detectors[next_num_detectors].end())
continue;
}

for (int d : edets[ei]) {
if (detectors[d]) {
Expand All @@ -418,9 +422,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
}
next_cost -= detector_cost_cache[d];
} else {
next_cost +=
get_detcost(d, config.at_most_two_errors_per_detector ? next_next_detector_cost_tuples
: next_detector_cost_tuples);
next_cost += get_detcost(d, next_detector_cost_tuples);
}
}

Expand All @@ -430,9 +432,7 @@ void TesseractDecoder::decode_to_errors(const std::vector<uint64_t>& detections,
detector_cost_cache[od] = get_detcost(od, detector_cost_tuples);
}
next_cost -= detector_cost_cache[od];
next_cost +=
get_detcost(od, config.at_most_two_errors_per_detector ? next_next_detector_cost_tuples
: next_detector_cost_tuples);
next_cost += get_detcost(od, next_detector_cost_tuples);
}

if (next_cost == INF) continue;
Expand Down Expand Up @@ -484,4 +484,4 @@ void TesseractDecoder::decode_shots(std::vector<stim::SparseShot>& shots,
for (size_t i = 0; i < shots.size(); ++i) {
obs_predicted[i] = decode(shots[i].hits);
}
}
}
2 changes: 1 addition & 1 deletion src/tesseract.pybind.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,4 @@ void add_tesseract_module(py::module &root) {
.def_readwrite("errors", &TesseractDecoder::errors);
}

#endif
#endif
Loading