Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
70 changes: 45 additions & 25 deletions libs/qec/lib/detector_error_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,23 @@ void detector_error_model::canonicalize_for_rounds(
auto row_indices = dense_to_sparse(detector_error_matrix);
auto column_order =
get_sorted_pcm_column_indices(row_indices, num_syndromes_per_round);
const std::size_t num_obs = this->num_observables();

auto observables_match = [&](std::uint32_t lhs, std::uint32_t rhs) {
for (std::size_t r = 0; r < num_obs; r++) {
if (this->observables_flips_matrix.at({r, lhs}) !=
this->observables_flips_matrix.at({r, rhs}))
return false;
}
return true;
};

std::vector<std::uint32_t> final_column_order;
// March through the columns in topological order, and combine the probability
// weight vectors if the columns have the same row indices.
std::vector<std::vector<std::uint32_t>> new_row_indices;
std::vector<double> new_weights;
std::vector<std::size_t> new_error_ids;
const std::size_t num_obs = this->num_observables();
const auto num_cols = column_order.size();
bool has_error_ids =
error_ids.has_value() && error_ids->size() == error_rates.size();
Expand All @@ -59,6 +69,12 @@ void detector_error_model::canonicalize_for_rounds(
"or the detector_error_matrix was computed incorrectly.");
}

// Cap the number of "same syndrome, different observable" warnings emitted
// per invocation. Short-distance codes can have many such mechanisms, and
// logging every one of them would spam the console.
constexpr std::size_t max_same_syndrome_diff_obs_warnings = 10;
std::size_t num_same_syndrome_diff_obs = 0;

for (std::size_t c = 0; c < num_cols; c++) {
auto column_index = column_order[c];
auto &curr_row_indices = row_indices[column_index];
Expand All @@ -74,10 +90,12 @@ void detector_error_model::canonicalize_for_rounds(
new_error_ids.push_back(error_ids->at(column_index));
} else {
auto &prev_row_indices = new_row_indices.back();
if (prev_row_indices == curr_row_indices) {
// The current column has the same row indices as the previous column
// (i.e. has the same syndrome signature) so we update the error_rates
// and do NOT add the duplicate column.
auto previous_column = final_column_order.back();
if (prev_row_indices == curr_row_indices &&
observables_match(previous_column, column_index)) {
// The current column has the same syndrome and observable signatures
// as the previous column, so update the error rate and do NOT add a
// duplicate column.
auto prev_weight = new_weights.back();
auto prev_error_id = has_error_ids
? new_error_ids.back()
Expand All @@ -97,27 +115,19 @@ void detector_error_model::canonicalize_for_rounds(
if (has_error_ids)
new_error_ids.back() =
std::min(prev_error_id, error_ids->at(column_index));
// Verify that the observables are the same for the duplicate column.
auto previous_column = column_order[c - 1];
bool match = true;
for (std::size_t r = 0; r < num_obs; r++) {
if (this->observables_flips_matrix.at({r, previous_column}) !=
this->observables_flips_matrix.at({r, column_index})) {
match = false;
break;
}
}
if (!match) {
cudaq::info(
"detector_error_model::canonicalize_for_rounds: identical "
"syndromes exist in detector_error_matrix but have different "
"observables in observables_flips_matrix (columns {} and {})",
previous_column, column_index);
}
} else {
// The current column has different row indices than the previous
// column. So we add the current column to the new PCM, and update the
// error_rates.
// Either the syndrome differs, or the same syndrome has a different
// observable flip. In both cases this is a distinct error mechanism.
if (prev_row_indices == curr_row_indices) {
if (num_same_syndrome_diff_obs < max_same_syndrome_diff_obs_warnings)
cudaq::warn(
"detector_error_model::canonicalize_for_rounds: identical "
"syndromes exist in detector_error_matrix but have different "
"observables in observables_flips_matrix; keeping column {} as "
"a distinct error mechanism (previous column {})",
column_index, previous_column);
num_same_syndrome_diff_obs++;
}
new_row_indices.push_back(curr_row_indices);
new_weights.push_back(error_rates[column_index]);
final_column_order.push_back(column_index);
Expand All @@ -127,6 +137,16 @@ void detector_error_model::canonicalize_for_rounds(
}
}

// Emit a single summary if we suppressed any per-column warnings above.
if (num_same_syndrome_diff_obs > max_same_syndrome_diff_obs_warnings)
cudaq::warn(
"detector_error_model::canonicalize_for_rounds: found {} columns with "
"identical syndromes but different observables; suppressed {} "
"additional warnings (only the first {} were shown).",
num_same_syndrome_diff_obs,
num_same_syndrome_diff_obs - max_same_syndrome_diff_obs_warnings,
max_same_syndrome_diff_obs_warnings);

std::swap(this->error_rates, new_weights);
if (has_error_ids)
std::swap(*this->error_ids, new_error_ids);
Expand Down
Loading
Loading