|
| 1 | +from __future__ import annotations |
| 2 | + |
| 3 | +import bioimage_cpp as bic |
| 4 | + |
| 5 | +from _compatibility import parser, run_comparison |
| 6 | + |
| 7 | + |
| 8 | +def main() -> None: |
| 9 | + args = parser( |
| 10 | + "Compare bioimage-cpp and nifty fusion-move lifted multicut at matched " |
| 11 | + "settings." |
| 12 | + ).parse_args() |
| 13 | + # Match settings on both sides: |
| 14 | + # - threads / parallel-proposals = `--threads N` (default 1). We pin |
| 15 | + # P = T explicitly on the bic side so the comparison is |
| 16 | + # apples-to-apples regardless of either library's default for P. |
| 17 | + # - greedy-additive warm-start: we do it automatically when the |
| 18 | + # objective's labels are the trivial singleton labeling. nifty's |
| 19 | + # `fusionMoveBasedFactory` has no warm-start parameter, so we make it |
| 20 | + # explicit on the nifty side by chaining greedy-additive in front. |
| 21 | + # - greedy-additive sub-solver (the implicit default on both sides). |
| 22 | + # - watershed proposal generator seeded from local edges. The bic |
| 23 | + # proposal generator only sees the base graph, so seeding from |
| 24 | + # "local" mirrors that exactly; the nifty default |
| 25 | + # `SEED_FROM_LIFTED` would put seeds where bic cannot. |
| 26 | + threads = int(args.threads) |
| 27 | + # nifty's lifted-multicut fusion-move backend only implements single- |
| 28 | + # threaded execution; passing numberOfThreads > 1 raises at solve time. |
| 29 | + # Cap the nifty side at 1 so multi-threaded bic benchmarks still run, and |
| 30 | + # surface the asymmetry in the printed output. |
| 31 | + nifty_threads = 1 |
| 32 | + if threads != nifty_threads: |
| 33 | + print( |
| 34 | + f"note: nifty lifted fusion-move runs single-threaded; comparing " |
| 35 | + f"bic threads={threads} vs nifty threads={nifty_threads}." |
| 36 | + ) |
| 37 | + run_comparison( |
| 38 | + "lifted_fusion_move", |
| 39 | + lambda: bic.graph.FusionMoveLiftedMulticut( |
| 40 | + proposal_generator=bic.graph.WatershedProposalGenerator(), |
| 41 | + number_of_iterations=10, |
| 42 | + stop_if_no_improvement=4, |
| 43 | + number_of_threads=threads, |
| 44 | + number_of_parallel_proposals=threads, |
| 45 | + ), |
| 46 | + lambda objective: objective.chainedSolversFactory( |
| 47 | + [ |
| 48 | + objective.liftedMulticutGreedyAdditiveFactory(), |
| 49 | + objective.fusionMoveBasedFactory( |
| 50 | + proposalGenerator=objective.watershedProposalGenerator( |
| 51 | + seedingStrategy="SEED_FROM_LOCAL", |
| 52 | + ), |
| 53 | + numberOfIterations=10, |
| 54 | + stopIfNoImprovement=4, |
| 55 | + numberOfThreads=nifty_threads, |
| 56 | + ), |
| 57 | + ] |
| 58 | + ), |
| 59 | + args, |
| 60 | + ) |
| 61 | + |
| 62 | + |
| 63 | +if __name__ == "__main__": |
| 64 | + main() |
0 commit comments