1010import cudaq
1111import cudaq_qec as qec
1212import pytest
13- import os
14- import tempfile
1513
1614
1715@pytest .fixture (scope = "function" , autouse = True )
@@ -22,16 +20,6 @@ def setTarget():
2220 cudaq .set_target (old_target )
2321
2422
25- @pytest .mark .parametrize ("decoder_name" ,
26- ["multi_error_lut" , "nv-qldpc-decoder" ])
27- @pytest .mark .parametrize ("batched" , [True , False ])
28- @pytest .mark .parametrize ("num_rounds" , [5 , 10 ])
29- @pytest .mark .parametrize ("num_windows" , [1 , 2 , 3 ])
30- def test_sliding_window_multi_error_lut_and_nv_qldpc_decoder (
31- decoder_name , batched , num_rounds , num_windows ):
32- test_sliding_window_1 (decoder_name , batched , num_rounds , num_windows )
33-
34-
3523@pytest .mark .parametrize ("decoder_name" , ["single_error_lut" ])
3624@pytest .mark .parametrize ("batched" , [True , False ])
3725@pytest .mark .parametrize ("num_rounds" , [5 , 10 ])
@@ -61,27 +49,9 @@ def test_sliding_window_1(decoder_name, batched, num_rounds, num_windows):
6149 # First compare the results of the full decoder to the sliding window
6250 # decoder using an inner decoder of the full window size. The results should
6351 # be the same.
64- if decoder_name == "nv-qldpc-decoder" :
65- # nv-qldpc-decoder requires use_sparsity=True for batched decoding
66- full_decoder = qec .get_decoder (decoder_name ,
67- dem .detector_error_matrix ,
68- use_sparsity = True ,
69- error_rate_vec = np .array (dem .error_rates ))
70- else :
71- full_decoder = qec .get_decoder (decoder_name , dem .detector_error_matrix )
52+ full_decoder = qec .get_decoder (decoder_name , dem .detector_error_matrix )
7253 num_syndromes_per_round = dem .detector_error_matrix .shape [0 ] // num_rounds
7354
74- # Set up inner decoder parameters based on decoder type
75- if decoder_name == "nv-qldpc-decoder" :
76- inner_decoder_params = {
77- "use_sparsity" : True ,
78- "error_rate_vec" : np .array (dem .error_rates )
79- }
80- elif decoder_name == "multi_error_lut" :
81- inner_decoder_params = {"lut_error_depth" : 2 }
82- else :
83- inner_decoder_params = {}
84-
8555 sw_as_full_decoder = qec .get_decoder (
8656 "sliding_window" ,
8757 dem .detector_error_matrix ,
@@ -92,28 +62,7 @@ def test_sliding_window_1(decoder_name, batched, num_rounds, num_windows):
9262 straddle_end_round = True ,
9363 error_rate_vec = np .array (dem .error_rates ),
9464 inner_decoder_name = decoder_name ,
95- inner_decoder_params = inner_decoder_params )
96-
97- # Save sliding window configuration to YAML file for verification
98- config_filename = save_sliding_window_config_to_yaml (
99- n_rounds = num_rounds ,
100- n_errs_per_round = dem .detector_error_matrix .shape [1 ] // num_rounds ,
101- n_syndromes_per_round = num_syndromes_per_round ,
102- window_size = num_rounds - num_windows + 1 ,
103- step_size = 1 ,
104- simplified_pcm = np .array (dem .detector_error_matrix ),
105- simplified_weights = np .array (dem .error_rates ),
106- inner_decoder_name = decoder_name )
107-
108- # ============================================================================
109- # PROVE END-TO-END SERIALIZATION: Load and configure decoders from the saved YAML
110- # ============================================================================
111- config_result = qec .configure_decoders_from_file (config_filename )
112- assert config_result == 0 , f"Failed to configure decoders from saved YAML file: { config_filename } "
113- print (
114- f"✅ Successfully configured decoders from saved YAML file: { config_filename } "
115- )
116- print ("End-to-end YAML serialization and decoder configuration verified!" )
65+ inner_decoder_params = {'dummy_param' : 1 })
11766
11867 if batched :
11968 full_results = full_decoder .decode_batch (syndromes )
@@ -134,127 +83,3 @@ def test_sliding_window_1(decoder_name, batched, num_rounds, num_windows):
13483 if r1 .result != r2 .result :
13584 num_mismatches += 1
13685 assert num_mismatches == 0
137-
138- # Cleanup: Finalize decoders after testing configuration
139- qec .qecrt .config .finalize_decoders ()
140-
141- # Clean up the generated YAML file
142- #if os.path.exists(config_filename):
143- # os.unlink(config_filename)
144-
145-
146- def save_sliding_window_config_to_yaml (n_rounds , n_errs_per_round ,
147- n_syndromes_per_round , window_size ,
148- step_size , simplified_pcm ,
149- simplified_weights , inner_decoder_name ):
150- """
151- Save sliding window decoder configuration to YAML (Python version of C++ function)
152- """
153- # Create a sliding_window_config struct with concrete inner decoder configs
154- sw_config = qec .qecrt .config .sliding_window_config ()
155- sw_config .window_size = window_size
156- sw_config .step_size = step_size
157- sw_config .num_syndromes_per_round = n_syndromes_per_round
158- sw_config .straddle_start_round = False # Default value from sliding_window.cpp
159- sw_config .straddle_end_round = True # Default value from sliding_window.cpp
160- sw_config .error_rate_vec = simplified_weights .tolist ()
161- sw_config .inner_decoder_name = inner_decoder_name
162-
163- # Set the appropriate concrete inner decoder config based on decoder name
164- if inner_decoder_name == "single_error_lut" :
165- single_config = qec .qecrt .config .single_error_lut_config ()
166- # single_error_lut_config is intentionally empty (no configuration parameters)
167- sw_config .single_error_lut_params = single_config
168- elif inner_decoder_name == "multi_error_lut" :
169- multi_config = qec .qecrt .config .multi_error_lut_config ()
170- multi_config .lut_error_depth = 2
171- # Note: error_rate_vec not supported in multi_error_lut_config for real-time decoding
172- sw_config .multi_error_lut_params = multi_config
173- elif inner_decoder_name == "nv-qldpc-decoder" :
174- nv_config = qec .qecrt .config .nv_qldpc_decoder_config ()
175- nv_config .use_sparsity = True
176- nv_config .error_rate_vec = simplified_weights .tolist ()
177- nv_config .use_osd = True
178- nv_config .max_iterations = 50
179- nv_config .osd_order = 60
180- nv_config .osd_method = 3
181- sw_config .nv_qldpc_decoder_params = nv_config
182-
183- # Create a decoder_config for the sliding window decoder
184- config = qec .qecrt .config .decoder_config ()
185- config .id = 0
186- config .type = "sliding_window"
187- config .block_size = simplified_pcm .shape [1 ] # Number of columns
188- config .syndrome_size = simplified_pcm .shape [0 ] # Number of rows
189- config .num_syndromes_per_round = n_syndromes_per_round
190-
191- # Convert PCM to sparse format for H_sparse and create empty O_sparse
192- H_sparse = []
193- for row in range (simplified_pcm .shape [0 ]):
194- for col in range (simplified_pcm .shape [1 ]):
195- if simplified_pcm [row , col ] == 1 :
196- H_sparse .append (int (col ))
197- H_sparse .append (- 1 ) # End of row marker
198-
199- config .H_sparse = H_sparse
200- config .O_sparse = [] # Empty for this test
201- # D_sparse is optional, leave unset
202-
203- # Set the sliding_window_config directly
204- config .decoder_custom_args = sw_config
205-
206- # Create multi_decoder_config and add our sliding window decoder
207- multi_config = qec .qecrt .config .multi_decoder_config ()
208- multi_config .decoders = [config ]
209-
210- # Generate YAML string using native serialization (no concatenation needed!)
211- config_str = multi_config .to_yaml_str (200 ) # 200 char line wrap
212-
213- # Create a unique filename based on test parameters
214- filename = f"sliding_window_config_r{ n_rounds } _e{ n_errs_per_round } _s{ n_syndromes_per_round } _w{ window_size } _st{ step_size } _{ inner_decoder_name } .yml"
215-
216- with open (filename , 'w' ) as config_file :
217- config_file .write (config_str )
218-
219- print (
220- f"Saved sliding window config (with native YAML inner decoder params) to file: { filename } "
221- )
222-
223- # Verify the config can be loaded back (inner decoder params should be natively serialized)
224- loaded_multi_config = qec .qecrt .config .multi_decoder_config .from_yaml_str (
225- config_str )
226- assert len (loaded_multi_config .decoders ) == 1
227- assert loaded_multi_config .decoders [0 ].type == "sliding_window"
228- assert loaded_multi_config .decoders [0 ].id == 0
229-
230- # Verify the YAML contains the expected structure and parameters
231- assert "decoder_custom_args:" in config_str
232- assert f"window_size: { window_size } " in config_str
233- assert f"step_size: { step_size } " in config_str
234- assert f"num_syndromes_per_round: { n_syndromes_per_round } " in config_str
235- assert f"inner_decoder_name: { inner_decoder_name } " in config_str
236-
237- # Verify that inner decoder parameters are preserved in the loaded config
238- print ("Successfully verified sliding window YAML config round-trip!" )
239- print (
240- "Sliding window parameters and inner decoder configs natively serialized!"
241- )
242-
243- if inner_decoder_name == "single_error_lut" :
244- # single_error_lut_config is intentionally empty (no configuration parameters)
245- print ("Single error LUT config parameters successfully verified!" )
246- elif inner_decoder_name == "multi_error_lut" :
247- assert "inner_decoder_params:" in config_str
248- assert "lut_error_depth: 2" in config_str
249- print ("Multi error LUT config parameters successfully verified!" )
250- elif inner_decoder_name == "nv-qldpc-decoder" :
251- assert "inner_decoder_params:" in config_str
252- assert "use_sparsity: true" in config_str
253- assert "use_osd: true" in config_str
254- assert "max_iterations: 50" in config_str
255- assert "osd_order: 60" in config_str
256- assert "osd_method: 3" in config_str
257- print ("NV QLDPC decoder config parameters successfully verified!" )
258-
259- # Return the filename for end-to-end verification
260- return filename
0 commit comments