Skip to content

Create bpots_decoder.jl #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
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
358 changes: 358 additions & 0 deletions src/decoders/bpots_decoder.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,358 @@
using SparseArrays


# STATE FOR STORING BP-OTS COMPUTATIONS
#=
The mutable struct stores the computational state during decoding.
=#
mutable struct BPOTSState
messages_vc::Dict{Tuple{Int,Int}, Float64} # dictionary mapping (variable, check) pairs to message values
messages_cv::Dict{Tuple{Int,Int}, Float64} # mapping (check, variable) pairs to message values
oscillations::Vector{Int} # this is a counter that tracks how many times each bit's decision changes
biased_nodes::Set{Int} # variable nodes that have been biased
prior_decisions::Vector{Int} # bit decisions from the previous Iteration
prior_llrs::Vector{Float64} # log likelihood ratios from the previous iteration
end



# MAIN DECODER STRUCT
struct BPOTSDecoder <: AbstractDecoder
per::Float64 # Physical error rate (probability of a qubit error)
max_iters::Int # Maximum # of iterations before giving up
s::Int # Number of stabilizers (Dimension of the parity check matrix- s x n)
n::Int # Number of qubits
T::Int # Biasing period (How often to apply the bias)
C::Float64 # Bias constant
sparse_H::SparseMatrixCSC{Bool,Int} # Sparse parity check matrix
sparse_HT::SparseMatrixCSC{Bool,Int} # Transposed parity check matrix
scratch::BPOTSState # Working state for computations
end



# BP-OTS STATE INITIALIZATION
# This creates the inital computational state for the BP-OTS algorithm
function initialize_bpots_state(H::SparseMatrixCSC, n::Int)

Check warning on line 36 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L36

Added line #L36 was not covered by tests

# Initializing 2 variables to sotre messages that flow through the Tanner graph
messages_vc = Dict{Tuple{Int,Int}, Float64}()
messages_cv = Dict{Tuple{Int,Int}, Float64}()

Check warning on line 40 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L39-L40

Added lines #L39 - L40 were not covered by tests

# Initialize messages with small random values
rows = rowvals(H) # Since H is sparse, this gets the row indices of the non-zero elements
vals = nonzeros(H) # Column indices of the non-zero elements

Check warning on line 44 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L43-L44

Added lines #L43 - L44 were not covered by tests

# Loops throught every column j, and for each connected row i, initalizes the msg between those nodes to 0.0
for j in 1:size(H,2)
for idx in nzrange(H, j)
i = rows[idx]
if vals[idx]
messages_vc[(j,i)] = 0.0 # Makes sure there is no bias
messages_cv[(i,j)] = 0.0

Check warning on line 52 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L47-L52

Added lines #L47 - L52 were not covered by tests
end
end
end

Check warning on line 55 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L54-L55

Added lines #L54 - L55 were not covered by tests

# Create the state and returns it
return BPOTSState(

Check warning on line 58 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L58

Added line #L58 was not covered by tests
messages_vc,
messages_cv,
zeros(Int, n), # oscillations
Set{Int}(), # biased_nodes
zeros(Int, n), # prior_decisions
zeros(Float64, n) # prior_llrs
)
end



# CONSTRUCTOR FOR THE DECODER
function BPOTSDecoder(H::Union{SparseMatrixCSC{Bool,Int}, BitMatrix}, per::Float64, max_iters::Int; T::Int=9, C::Float64=2.0)
s, n = size(H) # Assigns the dimensions to s and n
sparse_H = sparse(H) # Makes H sparse, incase it is Dense
sparse_HT = sparse(H') # Transposes H
scratch = initialize_bpots_state(sparse_H, n) # Creates a workspace to carry out the decoding

Check warning on line 75 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L71-L75

Added lines #L71 - L75 were not covered by tests

return BPOTSDecoder(per, max_iters, s, n, T, C, sparse_H, sparse_HT, scratch)

Check warning on line 77 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L77

Added line #L77 was not covered by tests
end



# Initialize beliefs with weaker bias
function initialize_beliefs(n::Int, per::Float64)

Check warning on line 83 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L83

Added line #L83 was not covered by tests
# Convert error probability to LLR with weak bias toward no errors
Π = fill(0.5 * log((1-per)/per), n) # Weak initial bias
return Π

Check warning on line 86 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L85-L86

Added lines #L85 - L86 were not covered by tests
end



# COMPUTER BELIEFS AND MAKE DECISIONS
# After msg passing iterations, this function takes all the informations and decides which qubits most likely have the errors
function compute_beliefs!(decoder::BPOTSDecoder, state::BPOTSState, Ω::Vector{Float64})
n = decoder.n
decisions = zeros(Int, n)
llrs = zeros(Float64, n)

Check warning on line 96 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L93-L96

Added lines #L93 - L96 were not covered by tests

for j in 1:n

Check warning on line 98 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L98

Added line #L98 was not covered by tests
# Sum all incoming messages for this variable node
llr = Ω[j] # Start with prior belief or bias
for i in get_variable_neighbors(decoder.sparse_H, j) # finds all check nodes connected to this variable
if haskey(state.messages_cv, (i,j))
llr += state.messages_cv[(i,j)] # adds all the cv msgs to the prior

Check warning on line 103 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L100-L103

Added lines #L100 - L103 were not covered by tests
end
end
llrs[j] = llr

Check warning on line 106 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L105-L106

Added lines #L105 - L106 were not covered by tests

# Decision threshold at 0 - flip bit if LLR is negative
decisions[j] = llr < 0.0 ? 1 : 0 # 1 if LLR < 0, 0 otherwise
end

Check warning on line 110 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L109-L110

Added lines #L109 - L110 were not covered by tests

return decisions, llrs

Check warning on line 112 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L112

Added line #L112 was not covered by tests
end



#RESEST STATE BETWEEN DECODINGS
#Prepares the decoder for reuase by clearing its internal state
function reset!(decoder::BPOTSDecoder)
state = decoder.scratch # reference to scratch state object
empty!(state.biased_nodes) # clears set of nodes with their biases
fill!(state.oscillations, 0) # resets bit-flip counter to 0
fill!(state.prior_decisions, 0) # clears the past decisions
fill!(state.prior_llrs, 0) # clears previous llrs

Check warning on line 124 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L119-L124

Added lines #L119 - L124 were not covered by tests

# Reset messages to neutral values
for k in keys(state.messages_vc)
state.messages_vc[k] = 0.0
end
for k in keys(state.messages_cv)
state.messages_cv[k] = 0.0
end

Check warning on line 132 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L127-L132

Added lines #L127 - L132 were not covered by tests

return decoder

Check warning on line 134 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L134

Added line #L134 was not covered by tests
end



# UPDATE VARIABLE TO CHECK (Eq 1) [ν^(ℓ)j→i = Ω_j + ∑(i'∈M(v_j)\{c_i}) μ^(ℓ)_i'→j]
# Variable node j collects evidence from all sources except check node i, and sends this aggregate belief to check node i
function update_variable_to_check!(state::BPOTSState, j::Int, i::Int, H::SparseMatrixCSC, Ω::Vector{Float64})
connected_checks = get_variable_neighbors(H, j) # find all check nodes connected to variable j

Check warning on line 142 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L141-L142

Added lines #L141 - L142 were not covered by tests

# Sum all incoming messages except from target check
msg_sum = 0.0
for check in connected_checks
if check != i # skip the target check node i to prevent echo chammer effects
msg = get(state.messages_cv, (check,j), 0.0) # get the existing msg from the check node to the variable node
msg_sum += msg

Check warning on line 149 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L145-L149

Added lines #L145 - L149 were not covered by tests
end
end

Check warning on line 151 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L151

Added line #L151 was not covered by tests

# Add prior and store - Equation (1) from the paper
msg = Ω[j] + msg_sum #add prior belief/ bias to the sum
state.messages_vc[(j,i)] = msg

Check warning on line 155 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L154-L155

Added lines #L154 - L155 were not covered by tests
end



# UPDATE CHECK TO VARIABLE MSG (Eq 2) [μ^(ℓ)i→j = (-1)^s_i · 2 tanh^(-1)(∏(j'∈N(c_i)\{v_j}) tanh(1/2 ν^(ℓ-1)_j'→i))]
# Check node i evaluate the parity constraint based on all other connected variables and informs the variable j about what this implies for j's error status
function update_check_to_variable!(state::BPOTSState, i::Int, j::Int, H::SparseMatrixCSC, syndrome::Vector{Bool})
connected_vars = get_check_neighbors(H, i) # finds all variable nodes connected to check i

Check warning on line 163 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L162-L163

Added lines #L162 - L163 were not covered by tests

# Compute product of tanh values from other variables
prod_tanh = 1.0
MAX_TANH = 0.99999 # For numerical stability

Check warning on line 167 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L166-L167

Added lines #L166 - L167 were not covered by tests

for var in connected_vars
if var != j # for each connected variable node, this skips the target variable node j
msg = get(state.messages_vc, (var,i), 0.0) # gets the msg from that variable to this check
t = tanh(0.5 * msg)
t = min(MAX_TANH, max(-MAX_TANH, t))
prod_tanh *= t

Check warning on line 174 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L169-L174

Added lines #L169 - L174 were not covered by tests
end
end

Check warning on line 176 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L176

Added line #L176 was not covered by tests

# Apply syndrome as in Equation (2)
if syndrome[i]
prod_tanh = -prod_tanh # sign flip if syndrome is true

Check warning on line 180 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L179-L180

Added lines #L179 - L180 were not covered by tests
end

# Compute message using atanh function - SAFETY CHECKS
# Avoid atanh on values too close to ±1
if abs(prod_tanh) >= MAX_TANH
prod_tanh = prod_tanh > 0 ? MAX_TANH : -MAX_TANH

Check warning on line 186 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L185-L186

Added lines #L185 - L186 were not covered by tests
end
msg = 2.0 * atanh(prod_tanh)

Check warning on line 188 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L188

Added line #L188 was not covered by tests

# Limit extreme values to prevent overflow
MAX_MSG = 100.0
msg = min(MAX_MSG, max(-MAX_MSG, msg))

Check warning on line 192 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L191-L192

Added lines #L191 - L192 were not covered by tests

state.messages_cv[(i,j)] = msg

Check warning on line 194 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L194

Added line #L194 was not covered by tests
end



#=
HELPER FUNCTIONS FOR MESSAGE PASSING
=#

# HELPER TO GET CHECK NODE NEIGHBORS
# This function identifies all variable nodes (qubits) connected to a specific check node (stabilizer) in the tanner graph
function get_check_neighbors(H::SparseMatrixCSC, check_idx::Int)
neighbors = Int[]

Check warning on line 206 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L205-L206

Added lines #L205 - L206 were not covered by tests
# Look through the check node's row
for col in 1:size(H,2)
if H[check_idx, col]
push!(neighbors, col)

Check warning on line 210 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L208-L210

Added lines #L208 - L210 were not covered by tests
end
end
return neighbors

Check warning on line 213 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L212-L213

Added lines #L212 - L213 were not covered by tests
end


# HELPER TO GET VARIABLE NODE NEIGHBORS
# This function finds all check nodes (stabilizers) that involve a specific variable node (qubit)
# Since, for msg passing, we need to to know which stabilizers are affected by each qubit
function get_variable_neighbors(H::SparseMatrixCSC, var_idx::Int)
neighbors = Int[] # To sdtore connected check nodes

Check warning on line 221 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L220-L221

Added lines #L220 - L221 were not covered by tests
# Look through column's non-zero entries
for idx in nzrange(H, var_idx) # where var_idx is the col we are examining
row = rowvals(H)[idx]
if nonzeros(H)[idx]
push!(neighbors, row)

Check warning on line 226 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L223-L226

Added lines #L223 - L226 were not covered by tests
end
end
return neighbors

Check warning on line 229 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L228-L229

Added lines #L228 - L229 were not covered by tests
end

#=
END OF HELPPER FUNCTIONS
=#



# DECODE (MAIN ALGORITHM)
function decode!(decoder::BPOTSDecoder, syndrome::Vector{Bool})

Check warning on line 239 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L239

Added line #L239 was not covered by tests

state = decoder.scratch
reset!(decoder)

Check warning on line 242 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L241-L242

Added lines #L241 - L242 were not covered by tests

#println("\nDEBUG: Starting decode")
#println("DEBUG: Syndrome: ", syndrome)

# Initialize priors beliefs based on the physical error rate per
# Πj = log((1-(2ϵ/3))/(2ϵ/3)) from the paper
Π = fill(log((1-(2*decoder.per/3))/(2*decoder.per/3)), decoder.n)
Ω = copy(Π)

Check warning on line 250 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L249-L250

Added lines #L249 - L250 were not covered by tests

# Track best solution
best_decisions = zeros(Int, decoder.n)
best_mismatch = length(syndrome)
best_weight = decoder.n

Check warning on line 255 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L253-L255

Added lines #L253 - L255 were not covered by tests

for iter in 1:decoder.max_iters

Check warning on line 257 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L257

Added line #L257 was not covered by tests
#println("\nDEBUG: === Iteration $iter ===")

# Message passing
#println("\nDEBUG: Variable updates")
for j in 1:decoder.n
for i in get_variable_neighbors(decoder.sparse_H, j)
update_variable_to_check!(state, j, i, decoder.sparse_H, Ω)
end
end

Check warning on line 266 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L262-L266

Added lines #L262 - L266 were not covered by tests

#println("\nDEBUG: Check updates")
for i in 1:decoder.s
for j in 1:decoder.n
if decoder.sparse_H[i,j]
update_check_to_variable!(state, i, j, decoder.sparse_H, syndrome)

Check warning on line 272 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L269-L272

Added lines #L269 - L272 were not covered by tests
end
end
end

Check warning on line 275 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L274-L275

Added lines #L274 - L275 were not covered by tests

# Compute marginals (beliefs)
decisions = zeros(Int, decoder.n)
llrs = zeros(Float64, decoder.n)

Check warning on line 279 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L278-L279

Added lines #L278 - L279 were not covered by tests

#println("\nDEBUG: Computing beliefs")
for j in 1:decoder.n
llr = Ω[j]

Check warning on line 283 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L282-L283

Added lines #L282 - L283 were not covered by tests
#println("DEBUG: Node $j")
#println("DEBUG: Prior: $llr")

for i in get_variable_neighbors(decoder.sparse_H, j)
msg = state.messages_cv[(i,j)]
llr += msg

Check warning on line 289 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L287-L289

Added lines #L287 - L289 were not covered by tests
#println("DEBUG: Added check $i msg: $msg")
end

Check warning on line 291 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L291

Added line #L291 was not covered by tests

llrs[j] = llr
decisions[j] = llr < 0.0 ? 1 : 0

Check warning on line 294 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L293-L294

Added lines #L293 - L294 were not covered by tests
#println("DEBUG: Final LLR: $llr -> Decision: $(decisions[j])")
end

Check warning on line 296 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L296

Added line #L296 was not covered by tests

# Update oscillation vector using XOR between consecutive decisions
# This tracks how often bits flip, as described in the paper
if iter > 1
for j in 1:decoder.n
state.oscillations[j] += (decisions[j] ⊻ state.prior_decisions[j])
end

Check warning on line 303 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L300-L303

Added lines #L300 - L303 were not covered by tests
end
state.prior_decisions = copy(decisions)
state.prior_llrs = copy(llrs)

Check warning on line 306 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L305-L306

Added lines #L305 - L306 were not covered by tests

# Check solution
check_result = Bool.(mod.(decoder.sparse_H * decisions, 2))
mismatch = count(check_result .!= syndrome)
weight = sum(decisions)

Check warning on line 311 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L309-L311

Added lines #L309 - L311 were not covered by tests
#println("\nDEBUG: Mismatch: $mismatch, Weight: $weight")

if mismatch < best_mismatch || (mismatch == best_mismatch && weight < best_weight)

Check warning on line 314 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L314

Added line #L314 was not covered by tests
#println("DEBUG: New best solution!")
best_mismatch = mismatch
best_weight = weight
best_decisions = copy(decisions)

Check warning on line 318 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L316-L318

Added lines #L316 - L318 were not covered by tests

if mismatch == 0

Check warning on line 320 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L320

Added line #L320 was not covered by tests
#println("DEBUG: Found valid solution!")
return best_decisions, true

Check warning on line 322 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L322

Added line #L322 was not covered by tests
end
end

# Apply biasing if needed - following Algorithm 1 in the paper
if mismatch > 0 && iter % decoder.T == 0

Check warning on line 327 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L327

Added line #L327 was not covered by tests
# Reset priors to original values
Ω = copy(Π)

Check warning on line 329 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L329

Added line #L329 was not covered by tests

# Check if there are any oscillating nodes
if maximum(state.oscillations) > 0

Check warning on line 332 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L332

Added line #L332 was not covered by tests
# Step 1: Find nodes with maximum oscillations (F set in the paper)
max_osc = maximum(state.oscillations)
max_osc_indices = findall(o -> o == max_osc, state.oscillations)

Check warning on line 335 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L334-L335

Added lines #L334 - L335 were not covered by tests

# Step 2: From F, select j1 with minimum |LLR|
j1 = max_osc_indices[argmin([abs(llrs[j]) for j in max_osc_indices])]

Check warning on line 338 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L338

Added line #L338 was not covered by tests

# Reset oscillation counter for j1
state.oscillations[j1] = 0

Check warning on line 341 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L341

Added line #L341 was not covered by tests

# Bias j1
Ω[j1] = -decoder.C

Check warning on line 344 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L344

Added line #L344 was not covered by tests
#println("DEBUG: Biasing j1 (node $j1): $(Ω[j1])")

# Step 3: Select j2 with minimum |LLR| overall
j2 = argmin(abs.(llrs))

Check warning on line 348 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L348

Added line #L348 was not covered by tests

# Bias j2 (which may coincide with j1)
Ω[j2] = -decoder.C

Check warning on line 351 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L351

Added line #L351 was not covered by tests
#println("DEBUG: Biasing j2 (node $j2): $(Ω[j2])")
end
end
end

Check warning on line 355 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L355

Added line #L355 was not covered by tests

return best_decisions, false

Check warning on line 357 in src/decoders/bpots_decoder.jl

View check run for this annotation

Codecov / codecov/patch

src/decoders/bpots_decoder.jl#L357

Added line #L357 was not covered by tests
end
Loading