1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Cut list optimization and bin packing for 1D (linear stock), 2D (sheet
//! stock), and 3D (box) problems.
//!
//! The crate exposes three shipping entry points by default:
//!
//! - [`one_d::solve_1d`] — cutting stock / linear bin packing. Supports first-fit
//! decreasing, best-fit decreasing, multistart local search, and an exact
//! column-generation backend that reports an LP lower bound.
//! - [`two_d::solve_2d`] — rectangular sheet packing. Supports the MaxRects family
//! (best-area, best-short-side-fit, best-long-side-fit, bottom-left, contact-point),
//! the Skyline family (default and minimum-waste), Guillotine beam search with
//! configurable ranking and split rules (best-short-side-fit, best-long-side-fit,
//! shorter- and longer-leftover-axis, min- and max-area splits), shelf heuristics
//! (NFDH, FFDH, BFDH), and a multistart meta-strategy.
//! - [`three_d::solve_3d`] — rectangular box packing. Supports Extreme Points,
//! Guillotine 3D, layer/wall/column builders, DBLF, volume-sorted baselines,
//! randomized meta-strategies, and a restricted exact backend.
//!
//! The `three-d` feature (enabled by default) provides the 3D rectangular box
//! packing module with a 29-algorithm catalog. The legacy `three-d-preview`
//! alias remains available as a compatibility shim.
//!
//! The 1D and 2D entry points ship an `Auto` mode that runs multiple strategies and
//! returns the best candidate, ranked lexicographically by unplaced count, stock /
//! sheet count, waste, and cost (with `exact` as a secondary tiebreaker for 1D).
//!
//! Additional capabilities:
//!
//! - Multiple stock / sheet types per problem, each with its own cost and optional
//! inventory cap. When 1D inventory caps are present, [`one_d::solve_1d`] also
//! reports a relaxed-inventory procurement estimate per stock type.
//! - Per-item rotation control for 2D demands, plus a `guillotine_required` flag
//! that restricts the solver to guillotine-compatible layouts.
//! - Kerf and trim modeling for 1D cuts so layouts match physical cut lists.
//! - Reproducible randomized search via an optional `seed`.
//! - Automatic multi-core parallelism via [`rayon`] when the `parallel` feature
//! is enabled (on by default). Auto-mode solvers dispatch algorithms in
//! parallel and multi-start / GRASP / local-search meta-strategies run their
//! iterations concurrently. Falls back to sequential execution on single-core
//! hosts or when the feature is disabled.
//! - Structured [`BinPackingError`] variants for input validation, infeasible
//! demands (1D, 2D, and 3D), and unsupported solver configurations.
//! - `metrics` blocks with iteration counts, explored states, and diagnostic notes.
//!
//! All problem, option, solution, and metrics types derive [`serde::Serialize`] and
//! [`serde::Deserialize`] so they can flow through JSON APIs or other wire formats
//! without wrapping.
//!
//! # Example: 1D cutting stock
//!
//! ```no_run
//! # #[cfg(feature = "one-d")]
//! # {
//! use bin_packing::one_d::{CutDemand1D, OneDOptions, OneDProblem, Stock1D, solve_1d};
//!
//! let problem = OneDProblem {
//! stock: vec![Stock1D {
//! name: "bar".into(),
//! length: 96,
//! kerf: 1,
//! trim: 0,
//! cost: 1.0,
//! available: None,
//! }],
//! demands: vec![
//! CutDemand1D { name: "rail".into(), length: 45, quantity: 2 },
//! CutDemand1D { name: "brace".into(), length: 30, quantity: 2 },
//! ],
//! };
//! let solution = solve_1d(problem, OneDOptions::default())?;
//! println!("stock used: {}", solution.stock_count);
//! # Ok::<(), bin_packing::BinPackingError>(())
//! # }
//! # #[cfg(not(feature = "one-d"))]
//! # Ok::<(), bin_packing::BinPackingError>(())
//! ```
//!
//! # Example: 2D rectangular packing
//!
//! ```no_run
//! # #[cfg(feature = "two-d")]
//! # {
//! use bin_packing::two_d::{RectDemand2D, Sheet2D, TwoDOptions, TwoDProblem, solve_2d};
//!
//! let problem = TwoDProblem {
//! sheets: vec![Sheet2D {
//! name: "plywood".into(),
//! width: 96,
//! height: 48,
//! cost: 1.0,
//! quantity: None,
//! kerf: 0,
//! edge_kerf_relief: false,
//! }],
//! demands: vec![RectDemand2D {
//! name: "panel".into(),
//! width: 24,
//! height: 18,
//! quantity: 4,
//! can_rotate: true,
//! }],
//! };
//! let solution = solve_2d(problem, TwoDOptions::default())?;
//! println!("sheets used: {}", solution.sheet_count);
//! # Ok::<(), bin_packing::BinPackingError>(())
//! # }
//! # #[cfg(not(feature = "two-d"))]
//! # Ok::<(), bin_packing::BinPackingError>(())
//! ```
pub use CutPlanError;
pub use ;