Skip to content

Commit fe7d40e

Browse files
authored
feat: Expose advanced Badger timeout options to tket2-py (#506)
#496 introduced a new timeout criterion for Badger based on the number of circuits seen during optimisation. This was not consistently exposed to the Python API. Fly-by: The `progress_timeout` timeout criterion that was added in #259 was also not exposed properly. This PR also fixes this. The timeout option `max_circuit_cnt` is now called `max_circuit_count`.
1 parent 573d0ba commit fe7d40e

File tree

6 files changed

+41
-20
lines changed

6 files changed

+41
-20
lines changed

badger-optimiser/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ struct CmdLineArgs {
8585
#[arg(
8686
short = 'c',
8787
long,
88-
value_name = "MAX_CIRCUIT_CNT",
88+
value_name = "MAX_CIRCUIT_COUNT",
8989
help = "Maximum number of circuits to process (default=None)."
9090
)]
91-
max_circuit_cnt: Option<usize>,
91+
max_circuit_count: Option<usize>,
9292
/// Number of threads (default=1)
9393
#[arg(
9494
short = 'j',
@@ -176,7 +176,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
176176
n_threads,
177177
split_circuit: opts.split_circ,
178178
queue_size: opts.queue_size,
179-
max_circuit_cnt: opts.max_circuit_cnt,
179+
max_circuit_count: opts.max_circuit_count,
180180
},
181181
);
182182

tket2-py/src/optimiser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl PyBadgerOptimiser {
6161
/// If `None` the optimiser will run indefinitely, or until `timeout` is
6262
/// reached.
6363
///
64-
/// * `max_circuit_cnt`: The maximum number of circuits to process before
64+
/// * `max_circuit_count`: The maximum number of circuits to process before
6565
/// stopping the optimisation.
6666
///
6767
///
@@ -94,7 +94,7 @@ impl PyBadgerOptimiser {
9494
circ: &Bound<'py, PyAny>,
9595
timeout: Option<u64>,
9696
progress_timeout: Option<u64>,
97-
max_circuit_cnt: Option<usize>,
97+
max_circuit_count: Option<usize>,
9898
n_threads: Option<NonZeroUsize>,
9999
split_circ: Option<bool>,
100100
queue_size: Option<usize>,
@@ -103,7 +103,7 @@ impl PyBadgerOptimiser {
103103
let options = BadgerOptions {
104104
timeout,
105105
progress_timeout,
106-
max_circuit_cnt,
106+
max_circuit_count,
107107
n_threads: n_threads.unwrap_or(NonZeroUsize::new(1).unwrap()),
108108
split_circuit: split_circ.unwrap_or(false),
109109
queue_size: queue_size.unwrap_or(100),

tket2-py/src/passes.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,27 @@ fn lower_to_pytket<'py>(circ: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>>
102102
/// optimising. This can be deactivated by setting `rebase` to `false`, in which
103103
/// case the circuit is expected to be in the Nam gate set.
104104
///
105-
/// Will use at most `max_threads` threads (plus a constant) and take at most
106-
/// `timeout` seconds (plus a constant). Default to the number of cpus and
107-
/// 15min respectively.
105+
/// Will use at most `max_threads` threads (plus a constant). Defaults to the
106+
/// number of CPUs available.
107+
///
108+
/// The optimisation will terminate at the first of the following timeout
109+
/// criteria, if set:
110+
/// - `timeout` seconds (default: 15min) have elapsed since the start of the
111+
/// optimisation
112+
/// - `progress_timeout` (default: None) seconds have elapsed since progress
113+
/// in the cost function was last made
114+
/// - `max_circuit_count` (default: None) circuits have been explored.
108115
///
109116
/// Log files will be written to the directory `log_dir` if specified.
110117
#[pyfunction]
118+
#[allow(clippy::too_many_arguments)]
111119
fn badger_optimise<'py>(
112120
circ: &Bound<'py, PyAny>,
113121
optimiser: &PyBadgerOptimiser,
114122
max_threads: Option<NonZeroUsize>,
115123
timeout: Option<u64>,
116124
progress_timeout: Option<u64>,
125+
max_circuit_count: Option<usize>,
117126
log_dir: Option<PathBuf>,
118127
rebase: Option<bool>,
119128
) -> PyResult<Bound<'py, PyAny>> {
@@ -165,6 +174,7 @@ fn badger_optimise<'py>(
165174
progress_timeout,
166175
n_threads: n_threads.try_into().unwrap(),
167176
split_circuit: true,
177+
max_circuit_count,
168178
..Default::default()
169179
};
170180
circ = optimiser.optimise(circ, log_file, options);

tket2-py/tket2/_tket2/passes.pyi

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def badger_optimise(
3535
max_threads: int | None = None,
3636
timeout: int | None = None,
3737
progress_timeout: int | None = None,
38+
max_circuit_count: int | None = None,
3839
log_dir: Path | None = None,
3940
rebase: bool | None = False,
4041
) -> CircuitClass:
@@ -47,9 +48,16 @@ def badger_optimise(
4748
optimising. This can be deactivated by setting `rebase` to `false`, in which
4849
case the circuit is expected to be in the Nam gate set.
4950
50-
Will use at most `max_threads` threads (plus a constant) and take at most
51-
`timeout` seconds (plus a constant). Default to the number of cpus and
52-
15min respectively.
51+
Will use at most `max_threads` threads (plus a constant). Defaults to the
52+
number of CPUs available.
53+
54+
The optimisation will terminate at the first of the following timeout
55+
criteria, if set:
56+
- `timeout` seconds (default: 15min) have elapsed since the start of the
57+
optimisation
58+
- `progress_timeout` (default: None) seconds have elapsed since progress
59+
in the cost function was last made
60+
- `max_circuit_count` (default: None) circuits have been explored.
5361
5462
Log files will be written to the directory `log_dir` if specified.
5563
"""

tket2-py/tket2/passes.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def badger_pass(
3535
max_threads: Optional[int] = None,
3636
timeout: Optional[int] = None,
3737
progress_timeout: Optional[int] = None,
38+
max_circuit_count: Optional[int] = None,
3839
log_dir: Optional[Path] = None,
3940
rebase: bool = False,
4041
) -> BasePass:
@@ -44,8 +45,9 @@ def badger_pass(
4445
`compile-rewriter <https://github.com/CQCL/tket2/tree/main/badger-optimiser>`_
4546
utility. If `rewriter` is not specified, a default one will be used.
4647
47-
The arguments `max_threads`, `timeout`, `log_dir` and `rebase` are optional
48-
and will be passed on to the Badger optimiser if provided."""
48+
The arguments `max_threads`, `timeout`, `progress_timeout`, `max_circuit_count`,
49+
`log_dir` and `rebase` are optional and will be passed on to the Badger
50+
optimiser if provided."""
4951
if rewriter is None:
5052
with resources.as_file(
5153
resources.files("tket2").joinpath("data/nam_6_3.rwr")
@@ -61,6 +63,7 @@ def apply(circuit: Circuit) -> Circuit:
6163
max_threads=max_threads,
6264
timeout=timeout,
6365
progress_timeout=progress_timeout,
66+
max_circuit_count=max_circuit_count,
6467
log_dir=log_dir,
6568
rebase=rebase,
6669
)

tket2/src/optimiser/badger.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub struct BadgerOptions {
5757
/// per-thread basis, otherwise applies globally.
5858
///
5959
/// Defaults to `None`, which means no limit.
60-
pub max_circuit_cnt: Option<usize>,
60+
pub max_circuit_count: Option<usize>,
6161
/// The number of threads to use.
6262
///
6363
/// Defaults to `1`.
@@ -86,7 +86,7 @@ impl Default for BadgerOptions {
8686
n_threads: NonZeroUsize::new(1).unwrap(),
8787
split_circuit: Default::default(),
8888
queue_size: 20,
89-
max_circuit_cnt: None,
89+
max_circuit_count: None,
9090
}
9191
}
9292
}
@@ -251,8 +251,8 @@ where
251251
break;
252252
}
253253
}
254-
if let Some(max_circuit_cnt) = opt.max_circuit_cnt {
255-
if seen_hashes.len() >= max_circuit_cnt {
254+
if let Some(max_circuit_count) = opt.max_circuit_count {
255+
if seen_hashes.len() >= max_circuit_count {
256256
timeout_flag = true;
257257
break;
258258
}
@@ -347,8 +347,8 @@ where
347347
Ok(PriorityChannelLog::CircuitCount{processed_count: proc, seen_count: seen, queue_length}) => {
348348
processed_count = proc;
349349
seen_count = seen;
350-
if let Some(max_circuit_cnt) = opt.max_circuit_cnt {
351-
if seen_count > max_circuit_cnt {
350+
if let Some(max_circuit_count) = opt.max_circuit_count {
351+
if seen_count > max_circuit_count {
352352
timeout_flag = true;
353353
// Signal the workers to stop.
354354
let _ = pq.close();

0 commit comments

Comments
 (0)