sinter 1.15.dev1745544934__tar.gz → 1.15.dev1745621353__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sinter might be problematic. Click here for more details.

Files changed (67) hide show
  1. {sinter-1.15.dev1745544934/src/sinter.egg-info → sinter-1.15.dev1745621353}/PKG-INFO +1 -1
  2. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/setup.py +1 -1
  3. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/__init__.py +1 -1
  4. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_manager.py +5 -1
  5. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_test.py +46 -3
  6. sinter-1.15.dev1745621353/src/sinter/_collection/_sampler_ramp_throttled_test.py +144 -0
  7. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353/src/sinter.egg-info}/PKG-INFO +1 -1
  8. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter.egg-info/SOURCES.txt +1 -0
  9. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/MANIFEST.in +0 -0
  10. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/README.md +0 -0
  11. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/readme_example_plot.png +0 -0
  12. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/requirements.txt +0 -0
  13. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/setup.cfg +0 -0
  14. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/__init__.py +0 -0
  15. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection.py +0 -0
  16. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_manager_test.py +0 -0
  17. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_worker_loop.py +0 -0
  18. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_worker_state.py +0 -0
  19. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_collection_worker_test.py +0 -0
  20. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_mux_sampler.py +0 -0
  21. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_printer.py +0 -0
  22. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_collection/_sampler_ramp_throttled.py +0 -0
  23. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/__init__.py +0 -0
  24. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main.py +0 -0
  25. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_collect.py +0 -0
  26. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_collect_test.py +0 -0
  27. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_combine.py +0 -0
  28. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_combine_test.py +0 -0
  29. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_plot.py +0 -0
  30. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_plot_test.py +0 -0
  31. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_predict.py +0 -0
  32. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_command/_main_predict_test.py +0 -0
  33. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/__init__.py +0 -0
  34. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_anon_task_stats.py +0 -0
  35. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_anon_task_stats_test.py +0 -0
  36. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_collection_options.py +0 -0
  37. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_collection_options_test.py +0 -0
  38. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_csv_out.py +0 -0
  39. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_existing_data.py +0 -0
  40. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_existing_data_test.py +0 -0
  41. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_task.py +0 -0
  42. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_task_stats.py +0 -0
  43. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_task_stats_test.py +0 -0
  44. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_data/_task_test.py +0 -0
  45. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/__init__.py +0 -0
  46. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding.py +0 -0
  47. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_all_built_in_decoders.py +0 -0
  48. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_decoder_class.py +0 -0
  49. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_fusion_blossom.py +0 -0
  50. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_mwpf.py +0 -0
  51. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_pymatching.py +0 -0
  52. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_test.py +0 -0
  53. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_decoding_vacuous.py +0 -0
  54. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_perfectionist_sampler.py +0 -0
  55. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_sampler.py +0 -0
  56. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_stim_then_decode_sampler.py +0 -0
  57. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_decoding/_stim_then_decode_sampler_test.py +0 -0
  58. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_plotting.py +0 -0
  59. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_plotting_test.py +0 -0
  60. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_predict.py +0 -0
  61. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_predict_test.py +0 -0
  62. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_probability_util.py +0 -0
  63. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter/_probability_util_test.py +0 -0
  64. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter.egg-info/dependency_links.txt +0 -0
  65. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter.egg-info/entry_points.txt +0 -0
  66. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter.egg-info/requires.txt +0 -0
  67. {sinter-1.15.dev1745544934 → sinter-1.15.dev1745621353}/src/sinter.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sinter
3
- Version: 1.15.dev1745544934
3
+ Version: 1.15.dev1745621353
4
4
  Summary: Samples stim circuits and decodes them using pymatching.
5
5
  Author: Craig Gidney
6
6
  Author-email: craig.gidney@gmail.com
@@ -19,7 +19,7 @@ with open('README.md', encoding='UTF-8') as f:
19
19
  with open('requirements.txt', encoding='UTF-8') as f:
20
20
  requirements = f.read().splitlines()
21
21
 
22
- __version__ = '1.15.dev1745544934'
22
+ __version__ = '1.15.dev1745621353'
23
23
 
24
24
  setup(
25
25
  name='sinter',
@@ -1,4 +1,4 @@
1
- __version__ = '1.15.dev1745544934'
1
+ __version__ = '1.15.dev1745621353'
2
2
 
3
3
  from sinter._collection import (
4
4
  collect,
@@ -129,6 +129,10 @@ class CollectionManager:
129
129
  def start_workers(self, *, actually_start_worker_processes: bool = True):
130
130
  assert not self.started
131
131
 
132
+ # Use max_batch_size from collection_options if provided, otherwise default to 1024 as large
133
+ # batch sizes can lead to thrashing
134
+ max_batch_shots = self.collection_options.max_batch_size or 1024
135
+
132
136
  sampler = RampThrottledSampler(
133
137
  sub_sampler=MuxSampler(
134
138
  custom_decoders=self.custom_decoders,
@@ -137,7 +141,7 @@ class CollectionManager:
137
141
  tmp_dir=self.tmp_dir,
138
142
  ),
139
143
  target_batch_seconds=1,
140
- max_batch_shots=1024,
144
+ max_batch_shots=max_batch_shots,
141
145
  )
142
146
 
143
147
  self.started = True
@@ -1,14 +1,13 @@
1
1
  import collections
2
- import math
2
+ import multiprocessing
3
3
  import pathlib
4
- import sys
5
4
  import tempfile
6
5
  import time
7
6
 
8
7
  import pytest
9
- import stim
10
8
 
11
9
  import sinter
10
+ import stim
12
11
 
13
12
 
14
13
  def test_iter_collect():
@@ -272,3 +271,47 @@ def test_mock_timing_sampler():
272
271
  custom_decoders={'MockTimingSampler': MockTimingSampler()},
273
272
  )
274
273
  assert 1_000_000 <= results[0].shots <= 1_000_000 + 12000
274
+
275
+ class BatchSizeTrackingSampler(sinter.Sampler, sinter.CompiledSampler):
276
+ """A sampler that tracks the suggested batch size requests it receives."""
277
+
278
+ def __init__(self, batch_sizes: list[int]):
279
+ self.batch_sizes = batch_sizes
280
+
281
+ def compiled_sampler_for_task(self, task: sinter.Task) -> sinter.CompiledSampler:
282
+ return self
283
+
284
+ def sample(self, suggested_shots: int) -> sinter.AnonTaskStats:
285
+ self.batch_sizes.append(suggested_shots)
286
+ return sinter.AnonTaskStats(
287
+ shots=suggested_shots,
288
+ errors=1,
289
+ seconds=0.001,
290
+ )
291
+
292
+
293
+ def test_ramp_throttled_sampler_respects_max_batch_size():
294
+ """Test that the CollectionManager instantiated RampThrottledSampler respects the `max_batch_size`
295
+ parameter."""
296
+
297
+ # since the RampThrottledSampler and batch sizing happens in the worker process, we need a
298
+ # shared list to track what goes on with the sampler
299
+ with multiprocessing.Manager() as manager:
300
+ tracking_sampler = BatchSizeTrackingSampler(manager.list())
301
+
302
+ sinter.collect(
303
+ num_workers=1,
304
+ tasks=[
305
+ sinter.Task(
306
+ circuit=stim.Circuit(),
307
+ decoder='tracking_sampler',
308
+ json_metadata={'test': 'small_batch'},
309
+ )
310
+ ],
311
+ max_shots=10_000,
312
+ max_batch_size=128, # Set a small max batch size
313
+ custom_decoders={'tracking_sampler': tracking_sampler},
314
+ )
315
+ # batch size should start at one and then maximum seen should be at most 128
316
+ assert tracking_sampler.batch_sizes[0] == 1
317
+ assert 1 < max(tracking_sampler.batch_sizes) <= 128
@@ -0,0 +1,144 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+
5
+ import sinter
6
+ import stim
7
+ from sinter._collection._sampler_ramp_throttled import (
8
+ CompiledRampThrottledSampler,
9
+ RampThrottledSampler,
10
+ )
11
+ from sinter._data import AnonTaskStats, Task
12
+
13
+
14
+ class MockSampler(sinter.Sampler, sinter.CompiledSampler):
15
+ """Mock sampler that tracks `suggested_shots` parameter in `sample` calls."""
16
+
17
+ def __init__(self):
18
+ self.calls = []
19
+
20
+ def compiled_sampler_for_task(self, task: Task) -> sinter.CompiledSampler:
21
+ return self
22
+
23
+ def sample(self, suggested_shots: int) -> AnonTaskStats:
24
+ self.calls.append(suggested_shots)
25
+ return AnonTaskStats(
26
+ shots=suggested_shots,
27
+ errors=1,
28
+ seconds=0.001 * suggested_shots, # Simulate time proportional to shots
29
+ )
30
+
31
+
32
+ @pytest.fixture
33
+ def mock_sampler():
34
+ return MockSampler()
35
+
36
+
37
+ def test_initial_batch_size(mock_sampler):
38
+ """Test that the sampler starts with a batch size of 1."""
39
+ sampler = CompiledRampThrottledSampler(
40
+ sub_sampler=mock_sampler,
41
+ target_batch_seconds=1.0,
42
+ max_batch_shots=1024,
43
+ )
44
+
45
+ # First call should use batch_size=1
46
+ sampler.sample(100)
47
+ assert mock_sampler.calls[0] == 1
48
+
49
+
50
+ def test_batch_size_ramps_up(mock_sampler):
51
+ """Test that the batch size increases when execution is fast."""
52
+ sampler = CompiledRampThrottledSampler(
53
+ sub_sampler=mock_sampler,
54
+ target_batch_seconds=1.0,
55
+ max_batch_shots=1024,
56
+ )
57
+
58
+ # Mock time.monotonic to simulate fast execution
59
+ # two calls per sample for tic/toc
60
+ with mock.patch(
61
+ "time.monotonic", side_effect=[0.0, 0.001, 0.02, 0.021, 0.03, 0.031]
62
+ ):
63
+ sampler.sample(100) # First call, batch_size=1
64
+ sampler.sample(100) # Should double 4 times to 16
65
+ sampler.sample(100) # Should double 4 times again but hit limit of 100
66
+
67
+ assert mock_sampler.calls == [1, 16, 100]
68
+
69
+
70
+ def test_batch_size_decreases(mock_sampler):
71
+ """Test that the batch size decreases when execution is slow."""
72
+ sampler = CompiledRampThrottledSampler(
73
+ sub_sampler=mock_sampler,
74
+ target_batch_seconds=0.1,
75
+ max_batch_shots=1024,
76
+ )
77
+
78
+ # Set initial batch size higher for this test
79
+ sampler.batch_shots = 64
80
+
81
+ # Mock time.monotonic to simulate slow execution (>1.3x target)
82
+ with mock.patch("time.monotonic", side_effect=[0.0, 0.15, 0.5, 0.65]):
83
+ sampler.sample(100) # First call, batch_size=64
84
+ sampler.sample(100) # Should halve to 32
85
+
86
+ assert mock_sampler.calls == [64, 32]
87
+
88
+
89
+ def test_respects_max_batch_shots(mock_sampler):
90
+ """Test that the batch size never exceeds max_batch_shots."""
91
+ sampler = CompiledRampThrottledSampler(
92
+ sub_sampler=mock_sampler,
93
+ target_batch_seconds=1.0,
94
+ max_batch_shots=16, # Small max for testing
95
+ )
96
+
97
+ # Set initial batch size close to max
98
+ sampler.batch_shots = 8
99
+
100
+ # Mock time.monotonic to simulate very fast execution
101
+ # two calls per sample for tic/toc
102
+ with mock.patch(
103
+ "time.monotonic", side_effect=[0.0, 0.001, 0.02, 0.021, 0.03, 0.031]
104
+ ):
105
+ sampler.sample(100) # First call, batch_size=8
106
+ sampler.sample(100) # Should double to 16
107
+ sampler.sample(100) # Should stay at 16 (max)
108
+
109
+ assert mock_sampler.calls == [8, 16, 16]
110
+
111
+
112
+ def test_respects_max_shots_parameter(mock_sampler):
113
+ """Test that the sampler respects the max_shots parameter."""
114
+ sampler = CompiledRampThrottledSampler(
115
+ sub_sampler=mock_sampler,
116
+ target_batch_seconds=1.0,
117
+ max_batch_shots=1024,
118
+ )
119
+
120
+ # Set batch size higher than max_shots
121
+ sampler.batch_shots = 100
122
+
123
+ # Call with max_shots=10
124
+ sampler.sample(10)
125
+
126
+ # Should only request 10 shots, not 100
127
+ assert mock_sampler.calls[0] == 10
128
+
129
+
130
+ def test_sub_sampler_parameter_pass_through(mock_sampler):
131
+ """Test that parameters are passed through to compiled sub sampler."""
132
+ factory = RampThrottledSampler(
133
+ sub_sampler=mock_sampler,
134
+ target_batch_seconds=0.5,
135
+ max_batch_shots=512,
136
+ )
137
+
138
+ task = Task(circuit=stim.Circuit(), decoder="test")
139
+ compiled = factory.compiled_sampler_for_task(task)
140
+
141
+ assert isinstance(compiled, CompiledRampThrottledSampler)
142
+ assert compiled.target_batch_seconds == 0.5
143
+ assert compiled.max_batch_shots == 512
144
+ assert compiled.batch_shots == 1 # Initial batch size
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sinter
3
- Version: 1.15.dev1745544934
3
+ Version: 1.15.dev1745621353
4
4
  Summary: Samples stim circuits and decodes them using pymatching.
5
5
  Author: Craig Gidney
6
6
  Author-email: craig.gidney@gmail.com
@@ -27,6 +27,7 @@ src/sinter/_collection/_collection_worker_test.py
27
27
  src/sinter/_collection/_mux_sampler.py
28
28
  src/sinter/_collection/_printer.py
29
29
  src/sinter/_collection/_sampler_ramp_throttled.py
30
+ src/sinter/_collection/_sampler_ramp_throttled_test.py
30
31
  src/sinter/_command/__init__.py
31
32
  src/sinter/_command/_main.py
32
33
  src/sinter/_command/_main_collect.py