diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a0a7ce..b7a4270 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,8 +19,8 @@ FetchContent_MakeAvailable(stim) # HiGHS FetchContent_Declare( highs - URL https://github.com/ERGO-Code/HiGHS/archive/refs/tags/v1.9.0.tar.gz - URL_HASH SHA256=dff575df08d88583c109702c7c5c75ff6e51611e6eacca8b5b3fdfba8ecc2cb4 + URL https://github.com/ERGO-Code/HiGHS/archive/refs/tags/v1.14.0.tar.gz + URL_HASH SHA256=05931e8dd8c8cac514da8297003c31a206a0004d542b7da500810b85c87c20b9 ) FetchContent_MakeAvailable(highs) diff --git a/src/py/tesseract_sinter_compat_test.py b/src/py/tesseract_sinter_compat_test.py index 8a4e15a..5015f31 100644 --- a/src/py/tesseract_sinter_compat_test.py +++ b/src/py/tesseract_sinter_compat_test.py @@ -687,5 +687,96 @@ def test_sinter_collect_different_dems(): assert results.json_metadata["d"] == expected_distances[i] +def test_tesseract_sinter_decoder_sparsify_attributes(): + decoder = TesseractSinterDecoder( + sparsify_errors=True, + sparsify_base_degree=2, + sparsify_max_degree=4, + sparsify_reactivate_limit=10, + ) + assert decoder.sparsify_errors is True + assert decoder.sparsify_base_degree == 2 + assert decoder.sparsify_max_degree == 4 + assert decoder.sparsify_reactivate_limit == 10 + + # Test equality + decoder2 = TesseractSinterDecoder( + sparsify_errors=True, + sparsify_base_degree=2, + sparsify_max_degree=4, + sparsify_reactivate_limit=10, + ) + assert decoder == decoder2 + + decoder3 = TesseractSinterDecoder( + sparsify_errors=True, + sparsify_base_degree=3, # different + sparsify_max_degree=4, + sparsify_reactivate_limit=10, + ) + assert decoder != decoder3 + + # Test pickle + import pickle + + dumped = pickle.dumps(decoder) + loaded = pickle.loads(dumped) + assert decoder == loaded + + +def test_make_tesseract_sinter_decoders_dict_contains_sparsify(): + decoders = make_tesseract_sinter_decoders_dict() + assert "tesseract-long-beam-sparsify3" in decoders + assert "tesseract-long-beam-sparsify2" in decoders + assert "tesseract-short-beam-sparsify3" in decoders + assert "tesseract-short-beam-sparsify2" in decoders + + d_long3 = decoders["tesseract-long-beam-sparsify3"] + assert d_long3.sparsify_errors is True + assert d_long3.sparsify_base_degree == 3 + assert d_long3.sparsify_max_degree == -1 + assert d_long3.sparsify_reactivate_limit == -1 + assert d_long3.det_beam == 20 + + d_short2 = decoders["tesseract-short-beam-sparsify2"] + assert d_short2.sparsify_errors is True + assert d_short2.sparsify_base_degree == 2 + assert d_short2.sparsify_max_degree == -1 + assert d_short2.sparsify_reactivate_limit == -1 + assert d_short2.det_beam == 15 + + +@pytest.mark.parametrize( + "decoder_name", + [ + "tesseract-long-beam-sparsify3", + "tesseract-long-beam-sparsify2", + "tesseract-short-beam-sparsify3", + "tesseract-short-beam-sparsify2", + ], +) +def test_sinter_decode_with_sparsify_decoders(decoder_name): + # Test that the new decoders can actually run and decode a simple repetition code. + circuit = stim.Circuit.generated( + "repetition_code:memory", + rounds=3, + distance=3, + after_clifford_depolarization=0.01, + ) + + result = sample_decode( + circuit_obj=circuit, + circuit_path=None, + dem_obj=circuit.detector_error_model(decompose_errors=True), + dem_path=None, + num_shots=100, + decoder=decoder_name, + custom_decoders=make_tesseract_sinter_decoders_dict(), + ) + assert result.discards == 0 + assert result.shots == 100 + assert 0 <= result.errors <= 10 + + if __name__ == "__main__": raise SystemExit(pytest.main([__file__])) diff --git a/src/py/tesseract_test.py b/src/py/tesseract_test.py index bb62bea..fbde369 100644 --- a/src/py/tesseract_test.py +++ b/src/py/tesseract_test.py @@ -286,5 +286,85 @@ def test_test_simplex_decode_batch_with_mismatched_syndrome_size(): ) +def test_create_tesseract_config_sparsify_defaults(): + config = tesseract_decoder.tesseract.TesseractConfig() + assert config.sparsify_errors is False + assert config.sparsify_base_degree == -1 + assert config.sparsify_max_degree == -1 + assert config.sparsify_reactivate_limit == -1 + + +def test_create_tesseract_config_sparsify_custom(): + config = tesseract_decoder.tesseract.TesseractConfig( + sparsify_errors=True, + sparsify_base_degree=2, + sparsify_max_degree=4, + sparsify_reactivate_limit=10, + ) + assert config.sparsify_errors is True + assert config.sparsify_base_degree == 2 + assert config.sparsify_max_degree == 4 + assert config.sparsify_reactivate_limit == 10 + + +def test_get_sparsify_reactivate_limit_heuristic(): + # We need a DEM to test this because it depends on number of detectors. + # _DETECTOR_ERROR_MODEL has 2 detectors (D0, D1) + config = tesseract_decoder.tesseract.TesseractConfig( + _DETECTOR_ERROR_MODEL, + sparsify_errors=True, + sparsify_base_degree=2, # k=2 + sparsify_reactivate_limit=-1, # use heuristic + ) + # Heuristic formula: round((4.5^(k-2) / 3) * num_detectors) + # For k=2, num_detectors=2: + # round((4.5^0 / 3) * 2) = round((1/3) * 2) = round(2/3) = round(0.666...) = 1 + assert config.get_sparsify_reactivate_limit() == 1 + + # Test with k=3 + config.sparsify_base_degree = 3 + # round((4.5^1 / 3) * 2) = round((4.5/3) * 2) = round(1.5 * 2) = round(3.0) = 3 + assert config.get_sparsify_reactivate_limit() == 3 + + # Test when sparsify_errors is False + config.sparsify_errors = False + assert config.get_sparsify_reactivate_limit() == -1 + + # Test when explicitly set + config.sparsify_errors = True + config.sparsify_reactivate_limit = 5 + assert config.get_sparsify_reactivate_limit() == 5 + + # Test validation: sparsify_base_degree < 0 throws + config.sparsify_reactivate_limit = -1 + config.sparsify_base_degree = -1 + with pytest.raises(ValueError, match="sparsify_base_degree must be >= 0"): + config.get_sparsify_reactivate_limit() + + +def test_get_sparsify_reactivate_limit_empty_dem(): + config = tesseract_decoder.tesseract.TesseractConfig( + sparsify_errors=True, + sparsify_base_degree=2, + sparsify_reactivate_limit=-1, + ) + assert config.get_sparsify_reactivate_limit() == 0 + + +def test_decoder_compilation_validation(): + # sparsify_base_degree < 0 throws + config = tesseract_decoder.tesseract.TesseractConfig( + _DETECTOR_ERROR_MODEL, sparsify_errors=True, sparsify_base_degree=-1 + ) + with pytest.raises(ValueError, match="sparsify_base_degree must be >= 0"): + config.compile_decoder() + + # sparsify_max_degree < sparsify_base_degree throws + config.sparsify_base_degree = 3 + config.sparsify_max_degree = 2 + with pytest.raises(ValueError, match="sparsify_max_degree must be >= sparsify_base_degree"): + config.compile_decoder() + + if __name__ == "__main__": raise SystemExit(pytest.main([__file__])) diff --git a/src/tesseract.cc b/src/tesseract.cc index 91651e0..07cd133 100644 --- a/src/tesseract.cc +++ b/src/tesseract.cc @@ -17,6 +17,7 @@ #include #include // For boost::hash_range #include +#include #include #include // For std::hash (though not strictly necessary here, but good practice) #include @@ -71,6 +72,22 @@ std::string TesseractConfig::str() { return ss.str(); } +int TesseractConfig::get_sparsify_reactivate_limit() const { + if (sparsify_reactivate_limit >= 0) { + return sparsify_reactivate_limit; + } + if (!sparsify_errors) { + return -1; + } + if (sparsify_base_degree < 0) { + throw std::invalid_argument( + "sparsify_base_degree must be >= 0 when sparsify_errors is enabled."); + } + double k = sparsify_base_degree; + double num_detectors = dem.count_detectors(); + return static_cast(std::round((std::pow(4.5, k - 2.0) / 3.0) * num_detectors)); +} + std::string Node::str() { std::stringstream ss; auto& self = *this; @@ -217,6 +234,17 @@ void TesseractDecoder::initialize_structures(size_t num_detectors) { } if (config.sparsify_errors) { + if (config.sparsify_base_degree < 0) { + throw std::invalid_argument( + "sparsify_base_degree must be >= 0 when sparsify_errors is enabled."); + } + if (config.sparsify_max_degree >= 0 && + config.sparsify_max_degree < config.sparsify_base_degree) { + throw std::invalid_argument("sparsify_max_degree must be >= sparsify_base_degree."); + } + + config.sparsify_reactivate_limit = config.get_sparsify_reactivate_limit(); + sparsify_mandatory_errors.clear(); sparsify_optional_errors.clear(); for (size_t ei = 0; ei < num_errors; ++ei) { diff --git a/src/tesseract.h b/src/tesseract.h index 37b5531..57d5a4f 100644 --- a/src/tesseract.h +++ b/src/tesseract.h @@ -50,6 +50,7 @@ struct TesseractConfig { int sparsify_max_degree = -1; int sparsify_reactivate_limit = -1; + int get_sparsify_reactivate_limit() const; std::string str(); }; diff --git a/src/tesseract.pybind.h b/src/tesseract.pybind.h index 3bdf477..555d7c9 100644 --- a/src/tesseract.pybind.h +++ b/src/tesseract.pybind.h @@ -38,13 +38,17 @@ TesseractConfig tesseract_config_maker_no_dem( bool verbose = false, bool merge_errors = true, size_t pqlimit = std::numeric_limits::max(), std::vector> det_orders = std::vector>(), - double det_penalty = 0.0, bool create_visualization = false) { + double det_penalty = 0.0, bool create_visualization = false, bool sparsify_errors = false, + int sparsify_base_degree = -1, int sparsify_max_degree = -1, + int sparsify_reactivate_limit = -1) { stim::DetectorErrorModel empty_dem; if (det_orders.empty()) { det_orders = build_det_orders(empty_dem, 20, DetOrder::DetBFS, 2384753); } return TesseractConfig({empty_dem, det_beam, beam_climbing, no_revisit_dets, verbose, - merge_errors, pqlimit, det_orders, det_penalty, create_visualization}); + merge_errors, pqlimit, det_orders, det_penalty, create_visualization, + sparsify_errors, sparsify_base_degree, sparsify_max_degree, + sparsify_reactivate_limit}); } TesseractConfig tesseract_config_maker( @@ -52,13 +56,17 @@ TesseractConfig tesseract_config_maker( bool no_revisit_dets = false, bool verbose = false, bool merge_errors = true, size_t pqlimit = std::numeric_limits::max(), std::vector> det_orders = std::vector>(), - double det_penalty = 0.0, bool create_visualization = false) { + double det_penalty = 0.0, bool create_visualization = false, bool sparsify_errors = false, + int sparsify_base_degree = -1, int sparsify_max_degree = -1, + int sparsify_reactivate_limit = -1) { stim::DetectorErrorModel input_dem = parse_py_object(dem); if (det_orders.empty()) { det_orders = build_det_orders(input_dem, 20, DetOrder::DetBFS, 2384753); } return TesseractConfig({input_dem, det_beam, beam_climbing, no_revisit_dets, verbose, - merge_errors, pqlimit, det_orders, det_penalty, create_visualization}); + merge_errors, pqlimit, det_orders, det_penalty, create_visualization, + sparsify_errors, sparsify_base_degree, sparsify_max_degree, + sparsify_reactivate_limit}); } }; // namespace @@ -82,7 +90,9 @@ void add_tesseract_module(py::module& root) { py::arg("beam_climbing") = false, py::arg("no_revisit_dets") = true, py::arg("verbose") = false, py::arg("merge_errors") = true, py::arg("pqlimit") = 200000, py::arg("det_orders") = std::vector>(), py::arg("det_penalty") = 0.0, - py::arg("create_visualization") = false, + py::arg("create_visualization") = false, py::arg("sparsify_errors") = false, + py::arg("sparsify_base_degree") = -1, py::arg("sparsify_max_degree") = -1, + py::arg("sparsify_reactivate_limit") = -1, R"pbdoc( The constructor for the `TesseractConfig` class without a `dem` argument. This creates an empty `DetectorErrorModel` by default. @@ -109,12 +119,22 @@ void add_tesseract_module(py::module& root) { A penalty value added to the cost of each detector visited. create_visualization: bool, defualt=False Whether to record the information needed to create a visualization or not. + sparsify_errors: bool, default=False + If True, enables per-shot sparse error activation. + sparsify_base_degree: int, default=-1 + Maximum detector degree for mandatory errors. + sparsify_max_degree: int, default=-1 + Maximum detector degree for optional errors. + sparsify_reactivate_limit: int, default=-1 + Maximum number of optional errors to reactivate per shot. Use -1 for heuristic default. )pbdoc") .def(py::init(&tesseract_config_maker), py::arg("dem"), py::arg("det_beam") = 5, py::arg("beam_climbing") = false, py::arg("no_revisit_dets") = true, py::arg("verbose") = false, py::arg("merge_errors") = true, py::arg("pqlimit") = 200000, py::arg("det_orders") = std::vector>(), py::arg("det_penalty") = 0.0, - py::arg("create_visualization") = false, + py::arg("create_visualization") = false, py::arg("sparsify_errors") = false, + py::arg("sparsify_base_degree") = -1, py::arg("sparsify_max_degree") = -1, + py::arg("sparsify_reactivate_limit") = -1, R"pbdoc( The constructor for the `TesseractConfig` class. @@ -142,6 +162,14 @@ void add_tesseract_module(py::module& root) { A penalty value added to the cost of each detector visited. create_visualization: bool, defualt=False Whether to record the information needed to create a visualization or not. + sparsify_errors: bool, default=False + If True, enables per-shot sparse error activation. + sparsify_base_degree: int, default=-1 + Maximum detector degree for mandatory errors. + sparsify_max_degree: int, default=-1 + Maximum detector degree for optional errors. + sparsify_reactivate_limit: int, default=-1 + Maximum number of optional errors to reactivate per shot. Use -1 for heuristic default. )pbdoc") .def_property("dem", &dem_getter, &dem_setter, "The `stim.DetectorErrorModel` that defines the error channels and detectors.") @@ -164,6 +192,17 @@ void add_tesseract_module(py::module& root) { "The penalty cost added for each detector.") .def_readwrite("create_visualization", &TesseractConfig::create_visualization, "If True, records necessary information to create visualization.") + .def_readwrite("sparsify_errors", &TesseractConfig::sparsify_errors, + "If True, enables per-shot sparse error activation.") + .def_readwrite("sparsify_base_degree", &TesseractConfig::sparsify_base_degree, + "Maximum detector degree for mandatory errors.") + .def_readwrite("sparsify_max_degree", &TesseractConfig::sparsify_max_degree, + "Maximum detector degree for optional errors.") + .def_readwrite("sparsify_reactivate_limit", &TesseractConfig::sparsify_reactivate_limit, + "Maximum number of optional errors to reactivate per shot. Use -1 for " + "heuristic default.") + .def("get_sparsify_reactivate_limit", &TesseractConfig::get_sparsify_reactivate_limit, + "Returns the resolved reactivate limit, applying the heuristic if it is set to -1.") .def("__str__", &TesseractConfig::str) .def("compile_decoder", &_compile_tesseract_decoder_helper, py::return_value_policy::take_ownership, diff --git a/src/tesseract_main.cc b/src/tesseract_main.cc index bcdf74e..fa7890c 100644 --- a/src/tesseract_main.cc +++ b/src/tesseract_main.cc @@ -334,16 +334,10 @@ struct Args { config.sparsify_errors = sparsify_errors; config.sparsify_base_degree = sparsify_base_degree; config.sparsify_max_degree = sparsify_max_degree; - - // Apply heuristic estimate for number of errors if sparsify_errors is enabled but no limit was - // provided - if (sparsify_errors && sparsify_reactivate_limit < 0) { - double k = sparsify_base_degree; - double num_detectors = config.dem.count_detectors(); - sparsify_reactivate_limit = - static_cast(std::round((std::pow(4.5, k - 2.0) / 3.0) * num_detectors)); - } config.sparsify_reactivate_limit = sparsify_reactivate_limit; + + config.sparsify_reactivate_limit = config.get_sparsify_reactivate_limit(); + sparsify_reactivate_limit = config.sparsify_reactivate_limit; } }; diff --git a/src/tesseract_sinter_compat.pybind.h b/src/tesseract_sinter_compat.pybind.h index c889423..e1969b9 100644 --- a/src/tesseract_sinter_compat.pybind.h +++ b/src/tesseract_sinter_compat.pybind.h @@ -109,6 +109,10 @@ struct TesseractSinterDecoder { size_t pqlimit; double det_penalty; bool create_visualization; + bool sparsify_errors; + int sparsify_base_degree; + int sparsify_max_degree; + int sparsify_reactivate_limit; // Parameters for build_det_orders size_t num_det_orders; @@ -125,6 +129,10 @@ struct TesseractSinterDecoder { pqlimit(DEFAULT_PQLIMIT), det_penalty(0.0), create_visualization(false), + sparsify_errors(false), + sparsify_base_degree(-1), + sparsify_max_degree(-1), + sparsify_reactivate_limit(-1), num_det_orders(0), det_order_method(DetOrder::DetBFS), seed(2384753) {} @@ -132,8 +140,9 @@ struct TesseractSinterDecoder { // Constructor with parameters TesseractSinterDecoder(int det_beam, bool beam_climbing, bool no_revisit_dets, bool verbose, bool merge_errors, size_t pqlimit, double det_penalty, - bool create_visualization, size_t num_det_orders, - DetOrder det_order_method, uint64_t seed) + bool create_visualization, bool sparsify_errors, int sparsify_base_degree, + int sparsify_max_degree, int sparsify_reactivate_limit, + size_t num_det_orders, DetOrder det_order_method, uint64_t seed) : det_beam(det_beam), beam_climbing(beam_climbing), no_revisit_dets(no_revisit_dets), @@ -142,6 +151,10 @@ struct TesseractSinterDecoder { pqlimit(pqlimit), det_penalty(det_penalty), create_visualization(create_visualization), + sparsify_errors(sparsify_errors), + sparsify_base_degree(sparsify_base_degree), + sparsify_max_degree(sparsify_max_degree), + sparsify_reactivate_limit(sparsify_reactivate_limit), num_det_orders(num_det_orders), det_order_method(det_order_method), seed(seed) {} @@ -151,6 +164,10 @@ struct TesseractSinterDecoder { no_revisit_dets == other.no_revisit_dets && verbose == other.verbose && merge_errors == other.merge_errors && pqlimit == other.pqlimit && det_penalty == other.det_penalty && create_visualization == other.create_visualization && + sparsify_errors == other.sparsify_errors && + sparsify_base_degree == other.sparsify_base_degree && + sparsify_max_degree == other.sparsify_max_degree && + sparsify_reactivate_limit == other.sparsify_reactivate_limit && num_det_orders == other.num_det_orders && det_order_method == other.det_order_method && seed == other.seed; } @@ -166,9 +183,20 @@ struct TesseractSinterDecoder { std::vector> det_orders = build_det_orders(stim_dem, num_det_orders, det_order_method, seed); - TesseractConfig local_config = { - stim_dem, det_beam, beam_climbing, no_revisit_dets, verbose, - merge_errors, pqlimit, det_orders, det_penalty, create_visualization}; + TesseractConfig local_config = {stim_dem, + det_beam, + beam_climbing, + no_revisit_dets, + verbose, + merge_errors, + pqlimit, + det_orders, + det_penalty, + create_visualization, + sparsify_errors, + sparsify_base_degree, + sparsify_max_degree, + sparsify_reactivate_limit}; auto decoder = std::make_unique(local_config); return TesseractSinterCompiledDecoder{ @@ -201,9 +229,20 @@ struct TesseractSinterDecoder { std::vector> det_orders = build_det_orders(stim_dem, num_det_orders, det_order_method, seed); - TesseractConfig local_config = { - stim_dem, det_beam, beam_climbing, no_revisit_dets, verbose, - merge_errors, pqlimit, det_orders, det_penalty, create_visualization}; + TesseractConfig local_config = {stim_dem, + det_beam, + beam_climbing, + no_revisit_dets, + verbose, + merge_errors, + pqlimit, + det_orders, + det_penalty, + create_visualization, + sparsify_errors, + sparsify_base_degree, + sparsify_max_degree, + sparsify_reactivate_limit}; TesseractDecoder decoder(local_config); // Calculate expected number of bytes per shot for detectors and observables. @@ -304,15 +343,17 @@ void pybind_sinter_compat(py::module& root) { .def(py::init<>(), R"pbdoc( Initializes a new TesseractSinterDecoder instance with a default TesseractConfig. )pbdoc") - .def( - py::init(), - py::arg("det_beam") = DEFAULT_DET_BEAM, py::arg("beam_climbing") = false, - py::arg("no_revisit_dets") = true, py::arg("verbose") = false, - py::arg("merge_errors") = true, py::arg("pqlimit") = DEFAULT_PQLIMIT, - py::arg("det_penalty") = 0.0, py::arg("create_visualization") = false, - py::arg("num_det_orders") = 0, py::arg("det_order_method") = DetOrder::DetBFS, - py::arg("seed") = 2384753, - R"pbdoc( + .def(py::init(), + py::arg("det_beam") = DEFAULT_DET_BEAM, py::arg("beam_climbing") = false, + py::arg("no_revisit_dets") = true, py::arg("verbose") = false, + py::arg("merge_errors") = true, py::arg("pqlimit") = DEFAULT_PQLIMIT, + py::arg("det_penalty") = 0.0, py::arg("create_visualization") = false, + py::arg("sparsify_errors") = false, py::arg("sparsify_base_degree") = -1, + py::arg("sparsify_max_degree") = -1, py::arg("sparsify_reactivate_limit") = -1, + py::arg("num_det_orders") = 0, py::arg("det_order_method") = DetOrder::DetBFS, + py::arg("seed") = 2384753, + R"pbdoc( Initializes a new TesseractSinterDecoder instance with custom TesseractConfig parameters. )pbdoc") .def("compile_decoder_for_dem", &TesseractSinterDecoder::compile_decoder_for_dem, @@ -347,6 +388,11 @@ void pybind_sinter_compat(py::module& root) { .def_readwrite("pqlimit", &TesseractSinterDecoder::pqlimit) .def_readwrite("det_penalty", &TesseractSinterDecoder::det_penalty) .def_readwrite("create_visualization", &TesseractSinterDecoder::create_visualization) + .def_readwrite("sparsify_errors", &TesseractSinterDecoder::sparsify_errors) + .def_readwrite("sparsify_base_degree", &TesseractSinterDecoder::sparsify_base_degree) + .def_readwrite("sparsify_max_degree", &TesseractSinterDecoder::sparsify_max_degree) + .def_readwrite("sparsify_reactivate_limit", + &TesseractSinterDecoder::sparsify_reactivate_limit) .def_readwrite("num_det_orders", &TesseractSinterDecoder::num_det_orders) .def_readwrite("det_order_method", &TesseractSinterDecoder::det_order_method) .def_readwrite("seed", &TesseractSinterDecoder::seed) @@ -358,17 +404,20 @@ void pybind_sinter_compat(py::module& root) { [](const TesseractSinterDecoder& self) -> py::tuple { // __getstate__ return py::make_tuple(self.det_beam, self.beam_climbing, self.no_revisit_dets, self.verbose, self.merge_errors, self.pqlimit, self.det_penalty, - self.create_visualization, self.num_det_orders, + self.create_visualization, self.sparsify_errors, + self.sparsify_base_degree, self.sparsify_max_degree, + self.sparsify_reactivate_limit, self.num_det_orders, self.det_order_method, self.seed); }, [](py::tuple t) { // __setstate__ - if (t.size() != 11) { + if (t.size() != 15) { throw std::runtime_error("Invalid state for TesseractSinterDecoder!"); } return TesseractSinterDecoder( t[0].cast(), t[1].cast(), t[2].cast(), t[3].cast(), t[4].cast(), t[5].cast(), t[6].cast(), t[7].cast(), - t[8].cast(), t[9].cast(), t[10].cast()); + t[8].cast(), t[9].cast(), t[10].cast(), t[11].cast(), + t[12].cast(), t[13].cast(), t[14].cast()); })); // Add a function to create a dictionary of custom decoders @@ -380,12 +429,44 @@ void pybind_sinter_compat(py::module& root) { /*det_beam=*/20, /*beam_climbing=*/true, /*no_revisit_dets=*/true, /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/1000000, /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/false, /*sparsify_base_degree=*/-1, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, /*num_det_orders=*/21, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); result["tesseract"] = result["tesseract-long-beam"]; + result["tesseract-long-beam-sparsify3"] = TesseractSinterDecoder( + /*det_beam=*/20, /*beam_climbing=*/true, /*no_revisit_dets=*/true, + /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/1000000, + /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/true, /*sparsify_base_degree=*/3, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, + /*num_det_orders=*/21, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); + result["tesseract-long-beam-sparsify2"] = TesseractSinterDecoder( + /*det_beam=*/20, /*beam_climbing=*/true, /*no_revisit_dets=*/true, + /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/1000000, + /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/true, /*sparsify_base_degree=*/2, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, + /*num_det_orders=*/21, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); result["tesseract-short-beam"] = TesseractSinterDecoder( /*det_beam=*/15, /*beam_climbing=*/true, /*no_revisit_dets=*/true, /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/200000, /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/false, /*sparsify_base_degree=*/-1, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, + /*num_det_orders=*/16, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); + result["tesseract-short-beam-sparsify3"] = TesseractSinterDecoder( + /*det_beam=*/15, /*beam_climbing=*/true, /*no_revisit_dets=*/true, + /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/200000, + /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/true, /*sparsify_base_degree=*/3, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, + /*num_det_orders=*/16, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); + result["tesseract-short-beam-sparsify2"] = TesseractSinterDecoder( + /*det_beam=*/15, /*beam_climbing=*/true, /*no_revisit_dets=*/true, + /*verbose=*/false, /*merge_errors=*/true, /*pqlimit=*/200000, + /*det_penalty=*/0.0, /*create_visualization=*/false, + /*sparsify_errors=*/true, /*sparsify_base_degree=*/2, + /*sparsify_max_degree=*/-1, /*sparsify_reactivate_limit=*/-1, /*num_det_orders=*/16, /*det_order_method=*/DetOrder::DetIndex, /*seed=*/2384753); return result; },