Skip to content

Commit 378461f

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents b6add10 + 1e1665f commit 378461f

21 files changed

+865
-58
lines changed

.bazelrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
common --noenable_bzlmod --enable_workspace
1+
common --enable_bzlmod --enable_workspace
22
build --cxxopt='-std=c++20'

MODULE.bazel

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module(name = "tesseract", version = "1.0")
2+
3+
bazel_dep(name = "bazel_skylib", version = "1.7.1")
4+
bazel_dep(name = "platforms", version = "0.0.10")
5+
bazel_dep(name = "rules_python", version = "0.40.0")
6+
bazel_dep(name = "rules_cc", version = "0.0.17")
7+
bazel_dep(name = "pybind11_bazel", version = "2.13.6")
8+
9+
DEFAULT_PYTHON_VERSION = "3.11"
10+
11+
python_configure = use_extension("@pybind11_bazel//:python_configure.bzl", "extension")
12+
use_repo(python_configure, "local_config_python")
13+
14+
15+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
16+
17+
pip.parse(
18+
hub_name = "pypi",
19+
python_version = "3.11",
20+
requirements_lock = "//src/py:requirements_lock.txt",
21+
)
22+
23+
use_repo(pip, "pypi")

WORKSPACE

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -68,51 +68,9 @@ http_archive(
6868
)
6969

7070
http_archive(
71-
name = "rules_python",
72-
sha256 = "62ddebb766b4d6ddf1712f753dac5740bea072646f630eb9982caa09ad8a7687",
73-
strip_prefix = "rules_python-0.39.0",
74-
url = "https://github.com/bazelbuild/rules_python/releases/download/0.39.0/rules_python-0.39.0.tar.gz",
75-
)
76-
77-
78-
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
79-
80-
http_archive(
81-
name = "rules_proto",
82-
sha256 = "14a225870ab4e91869652cfd69ef2028277fc1dc4910d65d353b62d6e0ae21f4",
83-
strip_prefix = "rules_proto-7.1.0",
84-
url = "https://github.com/bazelbuild/rules_proto/releases/download/7.1.0/rules_proto-7.1.0.tar.gz",
85-
)
86-
87-
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies")
88-
rules_proto_dependencies()
89-
90-
load("@rules_proto//proto:toolchains.bzl", "rules_proto_toolchains")
91-
rules_proto_toolchains()
92-
93-
94-
load("@rules_python//python:repositories.bzl", "py_repositories", "python_register_toolchains")
95-
96-
py_repositories()
97-
98-
python_register_toolchains(
99-
name = "python",
100-
ignore_root_user_error = True,
101-
python_version = "3.12",
102-
)
103-
104-
105-
http_archive(
106-
name = "pybind11_bazel",
107-
strip_prefix = "pybind11_bazel-2.13.6",
108-
sha256 = "9df284330336958c837fb70dc34c0a6254dac52a5c983b3373a8c2bbb79ac35e",
109-
urls = ["https://github.com/pybind/pybind11_bazel/archive/v2.13.6.zip"],
110-
)
111-
# We still require the pybind library.
112-
http_archive(
113-
name = "pybind11",
114-
build_file = "@pybind11_bazel//:pybind11-BUILD.bazel",
115-
strip_prefix = "pybind11-2.13.6",
116-
sha256 = "d0a116e91f64a4a2d8fb7590c34242df92258a61ec644b79127951e821b47be6",
117-
urls = ["https://github.com/pybind/pybind11/archive/v2.13.6.zip"],
71+
name = "stim_py",
72+
build_file = "//external:stim_py.BUILD",
73+
sha256 = "95236006859d6754be99629d4fb44788e742e962ac8c59caad421ca088f7350e",
74+
strip_prefix = "stim-1.15.0",
75+
urls = ["https://github.com/quantumlib/Stim/releases/download/v1.15.0/stim-1.15.0.tar.gz"],
11876
)

external/stim_py.BUILD

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
load("@pybind11_bazel//:build_defs.bzl", "pybind_library")
2+
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
3+
4+
SOURCE_FILES_NO_MAIN = glob(
5+
[
6+
"src/**/*.cc",
7+
"src/**/*.h",
8+
"src/**/*.inl",
9+
],
10+
exclude = glob([
11+
"src/**/*.test.cc",
12+
"src/**/*.test.h",
13+
"src/**/*.perf.cc",
14+
"src/**/*.perf.h",
15+
"src/**/*.pybind.cc",
16+
"src/**/*.pybind.h",
17+
"src/**/main.cc",
18+
]),
19+
)
20+
21+
PYBIND_MODULES = [
22+
"src/stim/py/march.pybind.cc",
23+
"src/stim/py/stim.pybind.cc",
24+
]
25+
26+
PYBIND_FILES_WITHOUT_MODULES = glob(
27+
[
28+
"src/**/*.pybind.cc",
29+
"src/**/*.pybind.h",
30+
],
31+
exclude=PYBIND_MODULES,
32+
)
33+
34+
35+
36+
pybind_library(
37+
name = "stim_pybind_lib",
38+
srcs = SOURCE_FILES_NO_MAIN + PYBIND_FILES_WITHOUT_MODULES,
39+
copts = [
40+
"-O3",
41+
"-std=c++20",
42+
"-fvisibility=hidden",
43+
"-march=native",
44+
"-DVERSION_INFO=0.0.dev0",
45+
],
46+
includes = ["src/"],
47+
visibility = ["//visibility:public"],
48+
)
49+
50+
pybind_extension(
51+
name = "stim",
52+
srcs = PYBIND_MODULES,
53+
copts = [
54+
"-O3",
55+
"-std=c++20",
56+
"-fvisibility=hidden",
57+
"-march=native",
58+
"-DSTIM_PYBIND11_MODULE_NAME=stim",
59+
"-DVERSION_INFO=0.0.dev0",
60+
],
61+
deps=[":stim_pybind_lib"],
62+
includes = ["src/"],
63+
visibility = ["//visibility:public"],
64+
)

src/BUILD

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
# load("@benchmark//:benchmark.bzl", "cc_benchmark")
16-
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension")
16+
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension", "pybind_library")
1717
load("@rules_python//python:defs.bzl", "py_library")
1818

1919
package(default_visibility = ["//visibility:public"])
@@ -64,22 +64,41 @@ cc_library(
6464
)
6565

6666

67+
pybind_library(
68+
name = "tesseract_decoder_pybind",
69+
srcs = [
70+
"common.pybind.h",
71+
"utils.pybind.h",
72+
"simplex.pybind.h",
73+
"tesseract.pybind.h",
74+
],
75+
deps = [
76+
":libcommon",
77+
":libutils",
78+
":libsimplex",
79+
":libtesseract",
80+
"@stim_py//:stim_pybind_lib",
81+
],
82+
)
83+
6784
pybind_extension(
6885
name = "tesseract_decoder",
6986
srcs = [
70-
"common.pybind.h",
7187
"tesseract.pybind.cc",
7288
],
7389
deps = [
74-
":libcommon",
90+
":tesseract_decoder_pybind",
91+
"@stim_py//:stim",
7592
],
7693
)
7794

7895

7996
py_library(
8097
name="lib_tesseract_decoder",
81-
data=[":tesseract_decoder"],
8298
imports=["src"],
99+
deps=[
100+
":tesseract_decoder",
101+
],
83102
)
84103

85104

src/common.pybind.h

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
115
#ifndef TESSERACT_COMMON_PY_H
216
#define TESSERACT_COMMON_PY_H
317

@@ -8,13 +22,14 @@
822
#include <vector>
923

1024
#include "common.h"
25+
#include "src/stim/dem/dem_instruction.pybind.h"
26+
#include "stim/dem/detector_error_model_target.pybind.h"
1127

1228
namespace py = pybind11;
1329

1430
void add_common_module(py::module &root) {
1531
auto m = root.def_submodule("common", "classes commonly used by the decoder");
1632

17-
// TODO: add as_dem_instruction_targets
1833
py::class_<common::Symptom>(m, "Symptom")
1934
.def(py::init<std::vector<int>, common::ObservablesMask>(),
2035
py::arg("detectors") = std::vector<int>(),
@@ -23,19 +38,38 @@ void add_common_module(py::module &root) {
2338
.def_readwrite("observables", &common::Symptom::observables)
2439
.def("__str__", &common::Symptom::str)
2540
.def(py::self == py::self)
26-
.def(py::self != py::self);
41+
.def(py::self != py::self)
42+
.def("as_dem_instruction_targets", [](common::Symptom s) {
43+
std::vector<stim_pybind::ExposedDemTarget> ret;
44+
for (auto &t : s.as_dem_instruction_targets()) ret.emplace_back(t);
45+
return ret;
46+
});
2747

28-
// TODO: add constructor with stim::DemInstruction.
2948
py::class_<common::Error>(m, "Error")
3049
.def_readwrite("likelihood_cost", &common::Error::likelihood_cost)
3150
.def_readwrite("probability", &common::Error::probability)
3251
.def_readwrite("symptom", &common::Error::symptom)
3352
.def("__str__", &common::Error::str)
3453
.def(py::init<>())
3554
.def(py::init<double, std::vector<int> &, common::ObservablesMask,
36-
std::vector<bool> &>())
55+
std::vector<bool> &>(),
56+
py::arg("likelihood_cost"), py::arg("detectors"),
57+
py::arg("observables"), py::arg("dets_array"))
3758
.def(py::init<double, double, std::vector<int> &, common::ObservablesMask,
38-
std::vector<bool> &>());
59+
std::vector<bool> &>(),
60+
py::arg("likelihood_cost"), py::arg("probability"),
61+
py::arg("detectors"), py::arg("observables"), py::arg("dets_array"))
62+
.def(py::init([](stim_pybind::ExposedDemInstruction edi) {
63+
return new common::Error(edi.as_dem_instruction());
64+
}),
65+
py::arg("error"));
66+
67+
m.def("merge_identical_errors", &common::merge_identical_errors,
68+
py::arg("dem"));
69+
m.def("remove_zero_probability_errors",
70+
&common::remove_zero_probability_errors, py::arg("dem"));
71+
m.def("dem_from_counts", &common::dem_from_counts, py::arg("orig_dem"),
72+
py::arg("error_counts"), py::arg("num_shots"));
3973
}
4074

4175
#endif

src/py/BUILD

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
load("@rules_python//python:py_test.bzl", "py_test")
2+
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
3+
4+
py_test(
5+
name = "common_test",
6+
srcs = ["common_test.py"],
7+
visibility = ["//:__subpackages__"],
8+
deps = [
9+
"@pypi//pytest",
10+
"//src:lib_tesseract_decoder",
11+
],
12+
)
13+
14+
py_test(
15+
name = "utils_test",
16+
srcs = ["utils_test.py"],
17+
visibility = ["//:__subpackages__"],
18+
deps = [
19+
"@pypi//pytest",
20+
"//src:lib_tesseract_decoder",
21+
],
22+
)
23+
24+
py_test(
25+
name = "simplex_test",
26+
srcs = ["simplex_test.py"],
27+
visibility = ["//:__subpackages__"],
28+
deps = [
29+
"@pypi//pytest",
30+
"//src:lib_tesseract_decoder",
31+
],
32+
)
33+
34+
py_test(
35+
name = "tesseract_test",
36+
srcs = ["tesseract_test.py"],
37+
visibility = ["//:__subpackages__"],
38+
deps = [
39+
"@pypi//pytest",
40+
"//src:lib_tesseract_decoder",
41+
],
42+
)
43+
44+
compile_pip_requirements(
45+
name = "requirements",
46+
src = "requirements.in",
47+
requirements_txt = "requirements_lock.txt",
48+
)

src/py/common_test.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http:#www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import pytest
16+
import stim
17+
18+
from src import tesseract_decoder
19+
20+
21+
def test_as_dem_instruction_targets():
22+
s = tesseract_decoder.common.Symptom([1, 2], 4324)
23+
dits = s.as_dem_instruction_targets()
24+
assert dits == [
25+
stim.DemTarget("D1"),
26+
stim.DemTarget("D2"),
27+
stim.DemTarget("L2"),
28+
stim.DemTarget("L5"),
29+
stim.DemTarget("L6"),
30+
stim.DemTarget("L7"),
31+
stim.DemTarget("L12"),
32+
]
33+
34+
35+
def test_error_from_dem_instruction():
36+
di = stim.DemInstruction("error", [0.125], [stim.target_logical_observable_id(3)])
37+
error = tesseract_decoder.common.Error(di)
38+
39+
assert str(error) == "Error{cost=1.945910, symptom=Symptom{}}"
40+
41+
42+
def test_merge_identical_errors():
43+
dem = stim.DetectorErrorModel()
44+
assert isinstance(
45+
tesseract_decoder.common.merge_identical_errors(dem), stim.DetectorErrorModel
46+
)
47+
48+
49+
def test_remove_zero_probability_errors():
50+
dem = stim.DetectorErrorModel()
51+
assert isinstance(
52+
tesseract_decoder.common.remove_zero_probability_errors(dem),
53+
stim.DetectorErrorModel,
54+
)
55+
56+
57+
def test_dem_from_counts():
58+
dem = stim.DetectorErrorModel()
59+
assert isinstance(
60+
tesseract_decoder.common.dem_from_counts(dem, [], 3), stim.DetectorErrorModel
61+
)
62+
63+
64+
if __name__ == "__main__":
65+
raise SystemExit(pytest.main([__file__]))

src/py/requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
stim
2+
pytest

0 commit comments

Comments
 (0)