From 78e5ec8dc7df71226193adc513fe3bdaf605931b Mon Sep 17 00:00:00 2001 From: Noah Shutty Date: Sun, 10 Aug 2025 22:46:23 -0400 Subject: [PATCH 1/7] Add visualization library to CMake build --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc3111bd..33420c7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,10 +73,15 @@ target_include_directories(utils PUBLIC ${TESSERACT_SRC_DIR}) target_compile_options(utils PRIVATE ${OPT_COPTS}) target_link_libraries(utils PUBLIC common libstim Threads::Threads) +add_library(visualization ${TESSERACT_SRC_DIR}/visualization.cc ${TESSERACT_SRC_DIR}/visualization.h) +target_include_directories(visualization PUBLIC ${TESSERACT_SRC_DIR}) +target_compile_options(visualization PRIVATE ${OPT_COPTS}) +target_link_libraries(visualization PUBLIC common boost_headers) + add_library(tesseract_lib ${TESSERACT_SRC_DIR}/tesseract.cc ${TESSERACT_SRC_DIR}/tesseract.h) target_include_directories(tesseract_lib PUBLIC ${TESSERACT_SRC_DIR}) target_compile_options(tesseract_lib PRIVATE ${OPT_COPTS}) -target_link_libraries(tesseract_lib PUBLIC utils boost_headers) +target_link_libraries(tesseract_lib PUBLIC utils boost_headers visualization) add_library(simplex ${TESSERACT_SRC_DIR}/simplex.cc ${TESSERACT_SRC_DIR}/simplex.h) target_include_directories(simplex PUBLIC ${TESSERACT_SRC_DIR}) From 5c211bc872714ed03b2333c16d6c49a153c39d24 Mon Sep 17 00:00:00 2001 From: Noah Shutty Date: Wed, 13 Aug 2025 11:27:13 -0400 Subject: [PATCH 2/7] Fix CMake Python module placement and add agent instructions --- .gitignore | 3 +++ AGENTS.md | 5 +++++ CMakeLists.txt | 7 +++++++ 3 files changed, 15 insertions(+) create mode 100644 AGENTS.md diff --git a/.gitignore b/.gitignore index 5b5d20b4..66d8f700 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ eclipse-*bin/ /.sass-cache # User-specific .bazelrc user.bazelrc + +# Ignore python extension module produced by CMake. +src/tesseract_decoder*.so diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..ea68e20e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,5 @@ +# Agent Instructions + +- Use the **CMake** build system when interacting with this repository. Humans use Bazel. +- A bug in some LLM coding environments makes Bazel difficult to use, so agents should rely on CMake. +- Keep both the CMake and Bazel builds working at all times. diff --git a/CMakeLists.txt b/CMakeLists.txt index 33420c7c..10e5ea69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,4 +103,11 @@ pybind11_add_module(tesseract_decoder MODULE ${TESSERACT_SRC_DIR}/tesseract.pybi target_compile_options(tesseract_decoder PRIVATE ${OPT_COPTS}) target_include_directories(tesseract_decoder PRIVATE ${TESSERACT_SRC_DIR}) target_link_libraries(tesseract_decoder PRIVATE common utils simplex tesseract_lib) +set_target_properties(tesseract_decoder PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src + LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_SOURCE_DIR}/src + LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/src + LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL ${PROJECT_SOURCE_DIR}/src + LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO ${PROJECT_SOURCE_DIR}/src +) From 7c10268eef32c22ce9189b195b84e83dc87e69ef Mon Sep 17 00:00:00 2001 From: Noah Shutty Date: Wed, 20 Aug 2025 15:09:33 -0700 Subject: [PATCH 3/7] Allow decode_to_errors to accept bitstring --- README.md | 6 +-- src/py/README.md | 25 +++++------ src/py/shared_decoding_tests.py | 6 +-- src/py/simplex_test.py | 3 +- src/py/tesseract_test.py | 7 +++- src/simplex.pybind.h | 34 ++++++++++++--- src/tesseract.pybind.h | 73 ++++++++++++++++++++++++++------- 7 files changed, 113 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 30230f7f..2e19e436 100644 --- a/README.md +++ b/README.md @@ -190,15 +190,15 @@ config = tesseract.TesseractConfig(dem=dem, det_beam=50) # 3. Create a decoder instance decoder = config.compile_decoder() -# 4. Simulate detection events -syndrome = [0, 1, 1] +# 4. Simulate detector outcomes +syndrome = np.array([0, 1, 1], dtype=bool) # 5a. Decode to observables flipped_observables = decoder.decode(syndrome) print(f"Flipped observables: {flipped_observables}") # 5b. Alternatively, decode to errors -decoder.decode_to_errors(np.where(syndrome)[0]) +decoder.decode_to_errors(syndrome) predicted_errors = decoder.predicted_errors_buffer # Indices of predicted errors print(f"Predicted errors indices: {predicted_errors}") diff --git a/src/py/README.md b/src/py/README.md index 79c0c396..625e41bd 100644 --- a/src/py/README.md +++ b/src/py/README.md @@ -64,28 +64,28 @@ print(f"Custom configuration detection penalty: {config2.det_beam}") #### Class `tesseract.TesseractDecoder` This is the main class that implements the Tesseract decoding logic. * `TesseractDecoder(config: tesseract.TesseractConfig)` -* `decode_to_errors(detections: list[int])` -* `decode_to_errors(detections: list[int], det_order: int, det_beam: int)` +* `decode_to_errors(syndrome: np.ndarray)` +* `decode_to_errors(syndrome: np.ndarray, det_order: int, det_beam: int)` * `get_observables_from_errors(predicted_errors: list[int]) -> list[bool]` * `cost_from_errors(predicted_errors: list[int]) -> float` -* `decode(detections: list[int]) -> list[bool]` +* `decode(syndrome: np.ndarray) -> np.ndarray` Explanation of each method: -#### `decode_to_errors(detections: list[int])` +#### `decode_to_errors(syndrome: np.ndarray)` Decodes a single measurement shot to predict a list of errors. -* **Parameters:** `detections` is a list of integers that represent the indices of the detectors that have fired in a single shot. +* **Parameters:** `syndrome` is a 1D NumPy array of booleans representing the detector outcomes for a single shot. * **Returns:** A list of integers, where each integer is the index of a predicted error. -#### `decode_to_errors(detections: list[int], det_order: int, det_beam: int)` +#### `decode_to_errors(syndrome: np.ndarray, det_order: int, det_beam: int)` An overloaded version of the `decode_to_errors` method that allows for a different decoding strategy. * **Parameters:** - * `detections` is a list of integers representing the indices of the fired detectors. + * `syndrome` is a 1D NumPy array of booleans representing the detector outcomes for a single shot. * `det_order` is an integer that specifies a different ordering of detectors to use for the decoding. @@ -219,10 +219,10 @@ print(f"Configuration verbose enabled: {config.verbose}") This is the main class for performing decoding using the Simplex algorithm. * `SimplexDecoder(config: simplex.SimplexConfig)` * `init_ilp()` -* `decode_to_errors(detections: list[int])` +* `decode_to_errors(syndrome: np.ndarray)` * `get_observables_from_errors(predicted_errors: list[int]) -> list[bool]` * `cost_from_errors(predicted_errors: list[int]) -> float` -* `decode(detections: list[int]) -> list[bool]` +* `decode(syndrome: np.ndarray) -> np.ndarray` **Example Usage**: @@ -230,6 +230,7 @@ This is the main class for performing decoding using the Simplex algorithm. import tesseract_decoder.simplex as simplex import stim import tesseract_decoder.common as common +import numpy as np # Create a DEM and a configuration dem = stim.DetectorErrorModel(""" @@ -245,9 +246,9 @@ decoder = simplex.SimplexDecoder(config) decoder.init_ilp() # Decode a shot where detector D1 fired -detections = [1] -flipped_observables = decoder.decode(detections) -print(f"Flipped observables for detections {detections}: {flipped_observables}") +syndrome = np.array([0, 1], dtype=bool) +flipped_observables = decoder.decode(syndrome) +print(f"Flipped observables for syndrome {syndrome.tolist()}: {flipped_observables}") # Access predicted errors predicted_error_indices = decoder.predicted_errors_buffer diff --git a/src/py/shared_decoding_tests.py b/src/py/shared_decoding_tests.py index 4500b141..82259d4b 100644 --- a/src/py/shared_decoding_tests.py +++ b/src/py/shared_decoding_tests.py @@ -302,16 +302,16 @@ def shared_test_merge_errors_affects_cost(decoder_class, config_class): error(0.01) D0 """ ) - detections = [0] + syndrome = np.array([True], dtype=bool) config_no_merge = config_class(dem, merge_errors=False) decoder_no_merge = decoder_class(config_no_merge) - predicted_errors_no_merge = decoder_no_merge.decode_to_errors(detections) + predicted_errors_no_merge = decoder_no_merge.decode_to_errors(syndrome) cost_no_merge = decoder_no_merge.cost_from_errors(decoder_no_merge.predicted_errors_buffer) config_merge = config_class(dem, merge_errors=True) decoder_merge = decoder_class(config_merge) - predicted_errors_merge = decoder_merge.decode_to_errors(detections) + predicted_errors_merge = decoder_merge.decode_to_errors(syndrome) cost_merge = decoder_merge.cost_from_errors(decoder_merge.predicted_errors_buffer) p_merged = 0.1 * (1 - 0.01) + 0.01 * (1 - 0.1) diff --git a/src/py/simplex_test.py b/src/py/simplex_test.py index 3a228d9c..752f9e8f 100644 --- a/src/py/simplex_test.py +++ b/src/py/simplex_test.py @@ -13,6 +13,7 @@ # limitations under the License. import pytest +import numpy as np import stim from src import tesseract_decoder @@ -56,7 +57,7 @@ def test_create_simplex_decoder(): decoder = tesseract_decoder.simplex.SimplexDecoder( tesseract_decoder.simplex.SimplexConfig(_DETECTOR_ERROR_MODEL, window_length=5) ) - decoder.decode_to_errors([1]) + decoder.decode_to_errors(np.array([False, True], dtype=bool)) assert decoder.get_observables_from_errors([1]) == [] assert decoder.cost_from_errors([2]) == pytest.approx(1.0986123) diff --git a/src/py/tesseract_test.py b/src/py/tesseract_test.py index 5df3e329..b7b21835 100644 --- a/src/py/tesseract_test.py +++ b/src/py/tesseract_test.py @@ -13,6 +13,7 @@ # limitations under the License. import pytest +import numpy as np import stim from src import tesseract_decoder @@ -60,8 +61,10 @@ def test_create_tesseract_config(): def test_create_tesseract_decoder(): config = tesseract_decoder.tesseract.TesseractConfig(_DETECTOR_ERROR_MODEL) decoder = tesseract_decoder.tesseract.TesseractDecoder(config) - decoder.decode_to_errors([0]) - decoder.decode_to_errors(detections=[0], det_order=0, det_beam=0) + decoder.decode_to_errors(np.array([True, False], dtype=bool)) + decoder.decode_to_errors( + syndrome=np.array([True, False], dtype=bool), det_order=0, det_beam=0 + ) assert decoder.get_observables_from_errors([1]) == [] assert decoder.cost_from_errors([1]) == pytest.approx(0.5108256237659907) diff --git a/src/simplex.pybind.h b/src/simplex.pybind.h index 79c8d59d..9c0e6b96 100644 --- a/src/simplex.pybind.h +++ b/src/simplex.pybind.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "common.h" #include "simplex.h" @@ -140,20 +141,43 @@ void add_simplex_module(py::module& root) { This method must be called before decoding. )pbdoc") - .def("decode_to_errors", &SimplexDecoder::decode_to_errors, py::arg("detections"), - py::call_guard(), R"pbdoc( + .def( + "decode_to_errors", + [](SimplexDecoder& self, const py::array_t& syndrome) { + if ((size_t)syndrome.size() != self.num_detectors) { + std::ostringstream msg; + msg << "Syndrome array size (" << syndrome.size() + << ") does not match the number of detectors in the decoder (" + << self.num_detectors << ")."; + throw std::invalid_argument(msg.str()); + } + + std::vector detections; + auto syndrome_unchecked = syndrome.unchecked<1>(); + for (size_t i = 0; i < (size_t)syndrome_unchecked.size(); ++i) { + if (syndrome_unchecked(i)) { + detections.push_back(i); + } + } + self.decode_to_errors(detections); + return self.predicted_errors_buffer; + }, + py::arg("syndrome"), + py::call_guard(), + R"pbdoc( Decodes a single shot to a list of error indices. Parameters ---------- - detections : list[int] - A list of indices of the detectors that have fired. + syndrome : np.ndarray + A 1D NumPy array of booleans representing the detector outcomes for a single shot. + The length of the array should match the number of detectors in the DEM. Returns ------- list[int] A list of predicted error indices. - )pbdoc") + )pbdoc") .def( "get_observables_from_errors", [](SimplexDecoder& self, const std::vector& predicted_errors) { diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index 267aa115..9c09e108 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "stim_utils.pybind.h" #include "tesseract.h" @@ -170,33 +171,75 @@ void add_tesseract_module(py::module& root) { config : TesseractConfig The configuration object for the decoder. )pbdoc") - .def("decode_to_errors", - py::overload_cast&>(&TesseractDecoder::decode_to_errors), - py::arg("detections"), - py::call_guard(), R"pbdoc( + .def( + "decode_to_errors", + [](TesseractDecoder& self, const py::array_t& syndrome) { + if ((size_t)syndrome.size() != self.num_detectors) { + std::ostringstream msg; + msg << "Syndrome array size (" << syndrome.size() + << ") does not match the number of detectors in the decoder (" + << self.num_detectors << ")."; + throw std::invalid_argument(msg.str()); + } + + std::vector detections; + auto syndrome_unchecked = syndrome.unchecked<1>(); + for (size_t i = 0; i < (size_t)syndrome_unchecked.size(); ++i) { + if (syndrome_unchecked(i)) { + detections.push_back(i); + } + } + self.decode_to_errors(detections); + return self.predicted_errors_buffer; + }, + py::arg("syndrome"), + py::call_guard(), + R"pbdoc( Decodes a single shot to a list of error indices. Parameters ---------- - detections : list[int] - A list of indices of the detectors that have fired. + syndrome : np.ndarray + A 1D NumPy array of booleans representing the detector outcomes for a single shot. + The length of the array should match the number of detectors in the DEM. Returns ------- list[int] A list of predicted error indices. - )pbdoc") - .def("decode_to_errors", - py::overload_cast&, size_t, size_t>( - &TesseractDecoder::decode_to_errors), - py::arg("detections"), py::arg("det_order"), py::arg("det_beam"), - py::call_guard(), R"pbdoc( + )pbdoc") + .def( + "decode_to_errors", + [](TesseractDecoder& self, const py::array_t& syndrome, size_t det_order, + size_t det_beam) { + if ((size_t)syndrome.size() != self.num_detectors) { + std::ostringstream msg; + msg << "Syndrome array size (" << syndrome.size() + << ") does not match the number of detectors in the decoder (" + << self.num_detectors << ")."; + throw std::invalid_argument(msg.str()); + } + + std::vector detections; + auto syndrome_unchecked = syndrome.unchecked<1>(); + for (size_t i = 0; i < (size_t)syndrome_unchecked.size(); ++i) { + if (syndrome_unchecked(i)) { + detections.push_back(i); + } + } + self.decode_to_errors(detections, det_order, det_beam); + return self.predicted_errors_buffer; + }, + py::arg("syndrome"), py::arg("det_order"), py::arg("det_beam"), + py::call_guard(), + R"pbdoc( Decodes a single shot using a specific detector ordering and beam size. Parameters ---------- - detections : list[int] - A list of indices of the detectors that have fired. + syndrome : np.ndarray + A 1D NumPy array of booleans representing the detector outcomes for a single shot. + The length of the array should match the number of detectors in the DEM. det_order : int The index of the detector ordering to use. det_beam : int @@ -206,7 +249,7 @@ void add_tesseract_module(py::module& root) { ------- list[int] A list of predicted error indices. - )pbdoc") + )pbdoc") .def( "get_observables_from_errors", [](TesseractDecoder& self, const std::vector& predicted_errors) { From c34dd80aec9f031bec0dcc47e6486b481f62d7b2 Mon Sep 17 00:00:00 2001 From: noajshu Date: Wed, 20 Aug 2025 22:18:00 +0000 Subject: [PATCH 4/7] clang-format --- src/simplex.pybind.h | 1 + src/tesseract.pybind.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/simplex.pybind.h b/src/simplex.pybind.h index 9c0e6b96..78f9a9e5 100644 --- a/src/simplex.pybind.h +++ b/src/simplex.pybind.h @@ -20,6 +20,7 @@ #include #include #include + #include #include "common.h" diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index 37c00ca8..32aa84d9 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -20,6 +20,7 @@ #include #include #include + #include #include "stim_utils.pybind.h" From 24c0d691dcd56e7e4aeea2341aac51e4fddbcfaa Mon Sep 17 00:00:00 2001 From: Noah Shutty Date: Wed, 20 Aug 2025 16:00:57 -0700 Subject: [PATCH 5/7] Update src/tesseract.pybind.h Co-authored-by: Noureldin --- src/tesseract.pybind.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index 32aa84d9..efdd17d7 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -253,7 +253,10 @@ void add_tesseract_module(py::module& root) { msg << "Syndrome array size (" << syndrome.size() << ") does not match the number of detectors in the decoder (" << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "Syndrome array size (" + std:to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")." + throw std::invalid_argument(msg); } std::vector detections; From 96849b67693c5beceb913b8f7f521bafdce1dc01 Mon Sep 17 00:00:00 2001 From: noajshu Date: Wed, 20 Aug 2025 23:38:00 +0000 Subject: [PATCH 6/7] remove stringstream --- src/simplex.pybind.h | 9 ++++----- src/tesseract.pybind.h | 9 +++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/simplex.pybind.h b/src/simplex.pybind.h index 78f9a9e5..7297fab8 100644 --- a/src/simplex.pybind.h +++ b/src/simplex.pybind.h @@ -253,11 +253,10 @@ void add_simplex_module(py::module& root) { "decode", [](SimplexDecoder& self, const py::array_t& syndrome) { if ((size_t)syndrome.size() != self.num_detectors) { - std::ostringstream msg; - msg << "Syndrome array size (" << syndrome.size() - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "Syndrome array size (" + std::to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } std::vector detections; diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index efdd17d7..1d27adf2 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -253,10 +253,11 @@ void add_tesseract_module(py::module& root) { msg << "Syndrome array size (" << syndrome.size() << ") does not match the number of detectors in the decoder (" << self.num_detectors << ")."; - std::string msg = "Syndrome array size (" + std:to_string(syndrome.size()) - + ") does not match the number of detectors in the decoder (" - + std::to_string(self.num_detectors) + ")." - throw std::invalid_argument(msg); + std::string msg = "Syndrome array size (" + + std + : to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")." throw std::invalid_argument(msg); } std::vector detections; From 3d486b0975025c822e3db1309d1c181b36faf4cf Mon Sep 17 00:00:00 2001 From: noajshu Date: Wed, 20 Aug 2025 23:51:20 +0000 Subject: [PATCH 7/7] more fixes --- src/simplex.pybind.h | 21 ++++++-------- src/tesseract.pybind.h | 43 +++++++++++----------------- src/tesseract_sinter_compat.pybind.h | 4 +-- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/simplex.pybind.h b/src/simplex.pybind.h index 7297fab8..9d00d3c6 100644 --- a/src/simplex.pybind.h +++ b/src/simplex.pybind.h @@ -21,8 +21,6 @@ #include #include -#include - #include "common.h" #include "simplex.h" #include "stim_utils.pybind.h" @@ -146,11 +144,10 @@ void add_simplex_module(py::module& root) { "decode_to_errors", [](SimplexDecoder& self, const py::array_t& syndrome) { if ((size_t)syndrome.size() != self.num_detectors) { - std::ostringstream msg; - msg << "Syndrome array size (" << syndrome.size() - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "Syndrome array size (" + std::to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } std::vector detections; @@ -311,11 +308,11 @@ void add_simplex_module(py::module& root) { size_t num_detectors = syndromes_unchecked.shape(1); if (num_detectors != self.num_detectors) { - std::ostringstream msg; - msg << "The number of detectors in the input array (" << num_detectors - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "The number of detectors in the input array (" + + std::to_string(num_detectors) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } // Allocate the result array. diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index 1d27adf2..b94c27f5 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -21,8 +21,6 @@ #include #include -#include - #include "stim_utils.pybind.h" #include "tesseract.h" @@ -249,15 +247,10 @@ void add_tesseract_module(py::module& root) { "decode_to_errors", [](TesseractDecoder& self, const py::array_t& syndrome) { if ((size_t)syndrome.size() != self.num_detectors) { - std::ostringstream msg; - msg << "Syndrome array size (" << syndrome.size() - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - std::string msg = "Syndrome array size (" + - std - : to_string(syndrome.size()) + - ") does not match the number of detectors in the decoder (" + - std::to_string(self.num_detectors) + ")." throw std::invalid_argument(msg); + std::string msg = "Syndrome array size (" + std::to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } std::vector detections; @@ -291,11 +284,10 @@ void add_tesseract_module(py::module& root) { [](TesseractDecoder& self, const py::array_t& syndrome, size_t det_order, size_t det_beam) { if ((size_t)syndrome.size() != self.num_detectors) { - std::ostringstream msg; - msg << "Syndrome array size (" << syndrome.size() - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "Syndrome array size (" + std::to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } std::vector detections; @@ -403,11 +395,10 @@ void add_tesseract_module(py::module& root) { "decode", [](TesseractDecoder& self, const py::array_t& syndrome) { if ((size_t)syndrome.size() != self.num_detectors) { - std::ostringstream msg; - msg << "Syndrome array size (" << syndrome.size() - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "Syndrome array size (" + std::to_string(syndrome.size()) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } std::vector detections; @@ -461,11 +452,11 @@ void add_tesseract_module(py::module& root) { size_t num_detectors = syndromes_unchecked.shape(1); if (num_detectors != self.num_detectors) { - std::ostringstream msg; - msg << "The number of detectors in the input array (" << num_detectors - << ") does not match the number of detectors in the decoder (" - << self.num_detectors << ")."; - throw std::invalid_argument(msg.str()); + std::string msg = "The number of detectors in the input array (" + + std::to_string(num_detectors) + + ") does not match the number of detectors in the decoder (" + + std::to_string(self.num_detectors) + ")."; + throw std::invalid_argument(msg); } // Allocate the result array. diff --git a/src/tesseract_sinter_compat.pybind.h b/src/tesseract_sinter_compat.pybind.h index 3d15e6b2..623253d9 100644 --- a/src/tesseract_sinter_compat.pybind.h +++ b/src/tesseract_sinter_compat.pybind.h @@ -83,7 +83,7 @@ struct TesseractSinterCompiledDecoder { // Store predictions into the output buffer uint8_t* single_result_buffer = result_buffer + shot * num_observable_bytes; std::fill(single_result_buffer, single_result_buffer + num_observable_bytes, 0); - for (int obs_index : predictions) { + for (size_t obs_index : predictions) { if (obs_index >= 0 && obs_index < num_observables) { single_result_buffer[obs_index / 8] ^= (1 << (obs_index % 8)); } @@ -191,7 +191,7 @@ struct TesseractSinterDecoder { // Pack the predictions back into a bit-packed format. std::fill(single_result_data.begin(), single_result_data.end(), 0); - for (int obs_index : predictions) { + for (size_t obs_index : predictions) { if (obs_index >= 0 && obs_index < num_obs) { single_result_data[obs_index / 8] ^= (1 << (obs_index % 8)); }