Skip to content

Commit a3e2663

Browse files
authored
Merge pull request #39 from noajshu/codex/create-detorder-enum-and-update-tesseract
Add explicit DetIndex branch for detector ordering
2 parents 20e506d + 61867e2 commit a3e2663

File tree

6 files changed

+80
-33
lines changed

6 files changed

+80
-33
lines changed

src/py/utils_test.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,25 @@ def test_build_det_orders():
5050
) == [[0, 1]]
5151

5252

53-
def test_build_det_orders_no_bfs():
53+
def test_build_det_orders_coordinate():
5454
assert tesseract_decoder.utils.build_det_orders(
55-
_DETECTOR_ERROR_MODEL, num_det_orders=1, det_order_bfs=False, seed=0
55+
_DETECTOR_ERROR_MODEL,
56+
num_det_orders=1,
57+
method=tesseract_decoder.utils.DetOrder.DetCoordinate,
58+
seed=0,
5659
) == [[0, 1]]
5760

5861

62+
def test_build_det_orders_index():
63+
res = tesseract_decoder.utils.build_det_orders(
64+
_DETECTOR_ERROR_MODEL,
65+
num_det_orders=1,
66+
method=tesseract_decoder.utils.DetOrder.DetIndex,
67+
seed=0,
68+
)
69+
assert res == [[0, 1]] or res == [[1, 0]]
70+
71+
5972
def test_get_errors_from_dem():
6073
expected = "Error{cost=1.945910, symptom=Symptom{detectors=[0], observables=[]}}, Error{cost=0.510826, symptom=Symptom{detectors=[0 1], observables=[]}}, Error{cost=1.098612, symptom=Symptom{detectors=[1], observables=[]}}"
6174
assert (

src/tesseract.pybind.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ TesseractConfig tesseract_config_maker_no_dem(
4141
double det_penalty = 0.0, bool create_visualization = false) {
4242
stim::DetectorErrorModel empty_dem;
4343
if (det_orders.empty()) {
44-
det_orders = build_det_orders(empty_dem, 20, /*det_order_bfs=*/true, 2384753);
44+
det_orders = build_det_orders(empty_dem, 20, DetOrder::DetBFS, 2384753);
4545
}
4646
return TesseractConfig({empty_dem, det_beam, beam_climbing, no_revisit_dets,
4747
at_most_two_errors_per_detector, verbose, merge_errors, pqlimit,
@@ -57,7 +57,7 @@ TesseractConfig tesseract_config_maker(
5757
double det_penalty = 0.0, bool create_visualization = false) {
5858
stim::DetectorErrorModel input_dem = parse_py_object<stim::DetectorErrorModel>(dem);
5959
if (det_orders.empty()) {
60-
det_orders = build_det_orders(input_dem, 20, true, 2384753);
60+
det_orders = build_det_orders(input_dem, 20, DetOrder::DetBFS, 2384753);
6161
}
6262
return TesseractConfig({input_dem, det_beam, beam_climbing, no_revisit_dets,
6363
at_most_two_errors_per_detector, verbose, merge_errors, pqlimit,

src/tesseract_main.cc

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ struct Args {
3434
// Manifold orientation options
3535
uint64_t det_order_seed;
3636
size_t num_det_orders = 10;
37-
bool det_order_bfs = true;
37+
bool det_order_bfs = false;
38+
bool det_order_index = false;
39+
bool det_order_coordinate = false;
3840

3941
// Sampling options
4042
size_t sample_num_shots = 0;
@@ -88,6 +90,12 @@ struct Args {
8890
throw std::invalid_argument("Must provide at least one of --circuit or --dem");
8991
}
9092

93+
int det_order_flags = int(det_order_bfs) + int(det_order_index) + int(det_order_coordinate);
94+
if (det_order_flags > 1) {
95+
throw std::invalid_argument(
96+
"Only one of --det-order-bfs, --det-order-index, or --det-order-coordinate may be set.");
97+
}
98+
9199
int num_data_sources = int(sample_num_shots > 0) + int(!in_fname.empty());
92100
if (num_data_sources != 1) {
93101
throw std::invalid_argument("Requires exactly 1 source of shots.");
@@ -180,8 +188,13 @@ struct Args {
180188
std::cout << ")" << std::endl;
181189
}
182190
}
183-
config.det_orders =
184-
build_det_orders(config.dem, num_det_orders, det_order_bfs, det_order_seed);
191+
DetOrder order = DetOrder::DetBFS;
192+
if (det_order_index) {
193+
order = DetOrder::DetIndex;
194+
} else if (det_order_coordinate) {
195+
order = DetOrder::DetCoordinate;
196+
}
197+
config.det_orders = build_det_orders(config.dem, num_det_orders, order, det_order_seed);
185198
}
186199

187200
if (sample_num_shots > 0) {
@@ -296,21 +309,18 @@ int main(int argc, char* argv[]) {
296309
.metavar("N")
297310
.default_value(size_t(1))
298311
.store_into(args.num_det_orders);
299-
program.add_argument("--no-det-order-bfs")
300-
.help("Disable BFS-based detector ordering and use geometric orientation")
301-
.default_value(true)
302-
.implicit_value(false)
303-
.store_into(args.det_order_bfs);
304312
program.add_argument("--det-order-bfs")
305-
.action([&](auto const&) {
306-
std::cout << "BFS-based detector ordering is the default now; "
307-
"--det-order-bfs is ignored."
308-
<< std::endl;
309-
})
310-
.default_value(true)
311-
.implicit_value(true)
312-
.store_into(args.det_order_bfs)
313-
.hidden();
313+
.help("Use BFS-based detector ordering (default if no method specified)")
314+
.flag()
315+
.store_into(args.det_order_bfs);
316+
program.add_argument("--det-order-index")
317+
.help("Randomly choose increasing or decreasing detector index order")
318+
.flag()
319+
.store_into(args.det_order_index);
320+
program.add_argument("--det-order-coordinate")
321+
.help("Random geometric detector orientation ordering")
322+
.flag()
323+
.store_into(args.det_order_coordinate);
314324
program.add_argument("--det-order-seed")
315325
.help(
316326
"Seed used when initializing the random detector traversal "

src/utils.cc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,15 @@ std::vector<std::vector<size_t>> build_detector_graph(const stim::DetectorErrorM
8383
}
8484

8585
std::vector<std::vector<size_t>> build_det_orders(const stim::DetectorErrorModel& dem,
86-
size_t num_det_orders, bool det_order_bfs,
86+
size_t num_det_orders, DetOrder method,
8787
uint64_t seed) {
8888
std::vector<std::vector<size_t>> det_orders(num_det_orders);
8989
std::mt19937_64 rng(seed);
9090
std::normal_distribution<double> dist(0, 1);
9191

9292
auto detector_coords = get_detector_coords(dem);
9393

94-
if (det_order_bfs) {
94+
if (method == DetOrder::DetBFS) {
9595
auto graph = build_detector_graph(dem);
9696
std::uniform_int_distribution<size_t> dist_det(0, graph.size() - 1);
9797
for (size_t det_order = 0; det_order < num_det_orders; ++det_order) {
@@ -131,7 +131,7 @@ std::vector<std::vector<size_t>> build_det_orders(const stim::DetectorErrorModel
131131
}
132132
det_orders[det_order] = inv_perm;
133133
}
134-
} else {
134+
} else if (method == DetOrder::DetCoordinate) {
135135
std::vector<double> inner_products(dem.count_detectors());
136136
if (!detector_coords.size() || !detector_coords.at(0).size()) {
137137
for (size_t det_order = 0; det_order < num_det_orders; ++det_order) {
@@ -163,6 +163,19 @@ std::vector<std::vector<size_t>> build_det_orders(const stim::DetectorErrorModel
163163
det_orders[det_order] = inv_perm;
164164
}
165165
}
166+
} else if (method == DetOrder::DetIndex) {
167+
std::uniform_int_distribution<int> dist_bool(0, 1);
168+
size_t n = dem.count_detectors();
169+
for (size_t det_order = 0; det_order < num_det_orders; ++det_order) {
170+
det_orders[det_order].resize(n);
171+
if (dist_bool(rng)) {
172+
for (size_t i = 0; i < n; ++i) {
173+
det_orders[det_order][i] = n - 1 - i;
174+
}
175+
} else {
176+
std::iota(det_orders[det_order].begin(), det_orders[det_order].end(), 0);
177+
}
178+
}
166179
}
167180
return det_orders;
168181
}

src/utils.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@ std::vector<std::vector<double>> get_detector_coords(const stim::DetectorErrorMo
3434
// in the model activates them both.
3535
std::vector<std::vector<size_t>> build_detector_graph(const stim::DetectorErrorModel& dem);
3636

37+
enum class DetOrder { DetBFS, DetIndex, DetCoordinate };
38+
3739
std::vector<std::vector<size_t>> build_det_orders(const stim::DetectorErrorModel& dem,
38-
size_t num_det_orders, bool det_order_bfs = true,
40+
size_t num_det_orders,
41+
DetOrder method = DetOrder::DetBFS,
3942
uint64_t seed = 0);
4043

4144
const double INF = std::numeric_limits<double>::infinity();

src/utils.pybind.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ void add_utils_module(py::module& root) {
3232
m.attr("INF") = INF;
3333
m.doc() = "A representation of infinity for floating point numbers.";
3434

35+
py::enum_<DetOrder>(m, "DetOrder", "Detector ordering methods")
36+
.value("DetBFS", DetOrder::DetBFS)
37+
.value("DetIndex", DetOrder::DetIndex)
38+
.value("DetCoordinate", DetOrder::DetCoordinate)
39+
.export_values();
40+
3541
m.def(
3642
"get_detector_coords",
3743
[](py::object dem) {
@@ -79,11 +85,11 @@ void add_utils_module(py::module& root) {
7985
)pbdoc");
8086
m.def(
8187
"build_det_orders",
82-
[](py::object dem, size_t num_det_orders, bool det_order_bfs, uint64_t seed) {
88+
[](py::object dem, size_t num_det_orders, DetOrder method, uint64_t seed) {
8389
auto input_dem = parse_py_object<stim::DetectorErrorModel>(dem);
84-
return build_det_orders(input_dem, num_det_orders, det_order_bfs, seed);
90+
return build_det_orders(input_dem, num_det_orders, method, seed);
8591
},
86-
py::arg("dem"), py::arg("num_det_orders"), py::arg("det_order_bfs") = true,
92+
py::arg("dem"), py::arg("num_det_orders"), py::arg("method") = DetOrder::DetBFS,
8793
py::arg("seed") = 0, R"pbdoc(
8894
Generates various detector orderings for decoding.
8995
@@ -93,17 +99,19 @@ void add_utils_module(py::module& root) {
9399
The detector error model to generate orders for.
94100
num_det_orders : int
95101
The number of detector orderings to generate.
96-
det_order_bfs : bool, default=True
97-
If True, uses a Breadth-First Search (BFS) to generate
98-
the orders. If False, uses a randomized ordering.
102+
method : tesseract_decoder.utils.DetOrder, default=tesseract_decoder.utils.DetOrder.DetBFS
103+
Strategy for ordering detectors. ``DetBFS`` performs a breadth-first
104+
traversal, ``DetCoordinate`` uses randomized geometric orientations,
105+
and ``DetIndex`` chooses either increasing or decreasing detector
106+
index order at random.
99107
seed : int, default=0
100108
A seed for the random number generator.
101109
102110
Returns
103111
-------
104112
list[list[int]]
105-
A list of detector orderings. Each inner list is a
106-
permutation of the detector indices.
113+
A list of detector orderings. Each inner list maps a detector index
114+
to its position in the ordering.
107115
)pbdoc");
108116
m.def(
109117
"get_errors_from_dem",

0 commit comments

Comments
 (0)