,
Space: SearchSpace,
```
.mermaid[
sequenceDiagram
participant CuttingPlaneOptim
participant Oracle as OracleOptim
participant Space as SearchSpace
loop max_iters times
CuttingPlaneOptim->>Space: xc()
Space-->>CuttingPlaneOptim: center
CuttingPlaneOptim->>Oracle: assess_optim(&xc, &gamma)
Oracle-->>CuttingPlaneOptim: ((g, ฮฒ), shrunk)
alt shrunk == true
CuttingPlaneOptim->>CuttingPlaneOptim: save x_best
CuttingPlaneOptim->>Space: update_central_cut((g, ฮฒ))
else shrunk == false
CuttingPlaneOptim->>Space: update_bias_cut((g, ฮฒ))
end
alt Failed or converged
Space-->>CuttingPlaneOptim: CutStatus
CuttingPlaneOptim-->>CuttingPlaneOptim: return (x_best, n)
end
end
]
---
### โ๏ธ CuttingPlaneOptimQ โ Quantized Optimization
```rust
pub fn cutting_plane_optim_q(
omega: &mut Oracle,
space_q: &mut Space,
gamma: &mut f64,
options: &Options,
) -> (Option, usize)
where
T: UpdateByCutChoice,
Oracle: OracleOptimQ,
Space: SearchSpace, // uses same SearchSpace, not SearchSpaceQ!
```
This variant adds **retry logic** ๐:
- On `CutStatus::NoEffect` and `more_alt == true`, it retries with a different quantized point
- On `CutStatus::NoEffect` and `more_alt == false`, it terminates
- Uses `SearchSpace::update_q` (default or overridden) instead of bias/central dispatch
---
### ๐ BSearchAdaptor โ Composing Traits
`BSearchAdaptor` bridges binary search with feasibility oracles:
```rust
pub struct BSearchAdaptor
where
T: UpdateByCutChoice,
Oracle: OracleFeas, // not OracleFeas2!
Space: SearchSpace + Clone,
{
pub omega: Oracle;
pub space: Space;
pub options: Options;
}
impl OracleBS for BSearchAdaptor
where ...
{
fn assess_bs(&mut self, gamma: f64) -> bool {
let mut space = self.space.clone(); // ๐งฌ Clone!
self.omega.update(gamma); // ๐ Calls OracleFeas::update()
let (x_feas, _) = cutting_plane_feas(
&mut self.omega, &mut space, &self.options
);
if let Some(x) = x_feas {
self.space.set_xc(x); // ๐พ Remember the best solution
return true;
}
false
}
}
```
This is the **power of trait composition** โ `OracleFeas2` eliminated by giving `OracleFeas` a default `update()` method. The binary search adaptor uses the same trait with an optional override.
---
class: nord-light, middle, center
## ๐ฆ Oracle Implementations โ Real-World Examples
---
### ๐ฐ ProfitOracle โ A Complete Example
```rust
impl OracleOptim for ProfitOracle {
type CutChoice = SingleCut;
fn assess_optim(&mut self, y: &Arr, gamma: &mut f64)
-> ((Arr, SingleCut), bool)
{
// 1. Check first constraint: y[0] โค log(k)
if y[0] > self.log_k {
return ((Arr::from(vec![1.0, 0.0]), SingleCut(y[0] - self.log_k)), false);
}
// 2. Check second constraint (Cobb-Douglas)
self.log_cobb = self.log_pA + self.elasticities.dot(y);
// 3. Shrink: update gamma with optimal value
*gamma = self.log_cobb.exp() - self.vx;
((grad, SingleCut(0.0)), true) // โ central cut with shrunk=true
}
}
```
The oracle's `CutChoice = SingleCut` wraps the $\beta$ value in a named type โ self-documenting and type-safe. No more bare `f64` floating around.
---
### ๐ก๏ธ ProfitRbOracle โ Robust Variant
For robust optimization with interval uncertainty:
```rust
impl OracleOptim for ProfitRbOracle {
type CutChoice = SingleCut;
fn assess_optim(&mut self, y: &Arr, gamma: &mut f64) -> ((Arr, SingleCut), bool) {
let mut a_rb = self.elasticities.clone();
for i in 0..2 {
a_rb[i] += if y[i] > 0.0 { -self.uie[i] }
else { self.uie[i] };
}
self.omega.elasticities = a_rb;
self.omega.assess_optim(y, gamma)
}
}
```
**Wraps** another oracle โ adjusts parameters before delegating. The trait architecture makes this composition trivial.
---
### ๐ข ProfitOracleQ โ Quantized Variant
```rust
impl OracleOptimQ for ProfitOracleQ {
type CutChoice = SingleCut;
fn assess_optim_q(&mut self, y: &Arr, gamma: &mut f64, retry: bool)
-> ((Arr, SingleCut), bool, Arr, bool)
{
if !retry {
let mut x_disc = y.map(|x| x.exp().round());
if x_disc[0] == 0.0 { x_disc[0] = 1.0; }
if x_disc[1] == 0.0 { x_disc[1] = 1.0; }
self.yd = x_disc.map(f64::ln);
}
let ((grad, SingleCut(beta)), shrunk) =
self.omega.assess_optim(&self.yd, gamma);
let beta = beta + grad.dot(&(&self.yd - y));
((grad, SingleCut(beta)), shrunk, self.yd.clone(), !retry)
}
}
```
The `retry` flag and `more_alt` (4th return value) enable **iterative refinement** of the quantized solution. ๐งฉ
---
### โธ๏ธ LowpassOracle โ Parallel Cut Example
The `LowpassOracle` uses `ParallelCut` for box constraints on filter magnitude:
```rust
impl OracleFeas for LowpassOracle {
type CutChoice = ParallelCut;
fn assess_feas(&mut self, x: &Arr) -> Option<(Arr, ParallelCut)> {
// ... passband and stopband checks ...
if val > self.up_sq {
// Two violations: val > up_sq AND val > lp_sq
return Some((col_k.clone(),
ParallelCut(val - self.up_sq, Some(val - self.lp_sq))));
}
// Single violation
return Some((col_k.clone(), ParallelCut(-val, None)));
}
}
```
`ParallelCut(beta0, Some(beta1))` represents a true parallel cut, while `ParallelCut(beta, None)` falls back to single-cut behavior.
---
class: nord-light, middle, center
## ๐ Architecture Summary
---
### ๐ Complete Trait Wiring Diagram
.mermaid[
graph TB
subgraph Algorithm["โ๏ธ Algorithms"]
CPF[cutting_plane_feas]
CPO[cutting_plane_optim]
CPQ[cutting_plane_optim_q]
BS[bsearch]
end
subgraph Oracle["๐ฎ Oracle Traits"]
OF[OracleFeas <+update()>]
OO[OracleOptim]
OOQ[OracleOptimQ]
OBS[OracleBS]
end
subgraph Space["๐ฅ SearchSpace"]
ELL[Ell]
ELS[EllStable]
EL1[Ell1D]
end
subgraph CutStrat["โ๏ธ Cut Strategy"]
SC[SingleCut]
PC[ParallelCut]
CT[CutType] -.->|internal| SC
CT -.->|internal| PC
end
CPF -->|"uses"| OF
CPF -->|"uses"| Space
CPF -->|"uses CutChoice=T"| CutStrat
CPO -->|"uses"| OO
CPO -->|"uses"| Space
CPO -->|"uses CutChoice=T"| CutStrat
CPQ -->|"uses"| OOQ
CPQ -->|"uses"| Space
CPQ -->|"uses CutChoice=T"| CutStrat
BS -->|"uses"| OBS
OBS -.->|"BSearchAdaptor wraps"| OF
style CPF fill:#ff9800
style CPO fill:#ff9800
style CPQ fill:#ff9800
style BS fill:#ff9800
style OF fill:#4caf50
style OO fill:#4caf50
style OOQ fill:#4caf50
style OBS fill:#4caf50
style ELL fill:#2196f3
style ELS fill:#2196f3
style EL1 fill:#2196f3
style SC fill:#e91e63
style PC fill:#e91e63
]
---
### ๐ก Key Design Decisions
| Decision | Rationale |
|----------|-----------|
| **Associated types** for `ArrayType` and `CutChoice` | Allows type-level dispatch without runtime overhead |
| **`CutChoice = T` constraint** connects Oracle โ UpdateByCutChoice | Compile-time guarantee that cut types match |
| **`OracleFeas::update()`** default method | Replaced `OracleFeas2` โ one less trait ๐งน |
| **`SearchSpace::update_q()`** default method | Replaced `SearchSpaceQ` โ one less trait ๐งน |
| **`SingleCut` / `ParallelCut` newtypes** | Named types instead of bare `f64` / tuples ๐ |
| **Internal `CutType` trait** (in `ell.rs`) | Blanket impl avoids duplicating `UpdateByCutChoice` for `Ell` |
| **`BSearchAdaptor`** composes `OracleBS` from `OracleFeas` | Reuses existing traits without new abstractions |
---
### ๐ฏ Why This Architecture Works
.pull-left[
**โ
Zero-cost abstraction**
All polymorphism is resolved at compile time via generics and associated types. No `dyn` trait objects, no vtable dispatch.
**โ
Open for extension**
Add a new oracle โ implement `OracleOptim`. Add a new search space โ implement `SearchSpace`. No existing code changes.
]
.pull-right[
**โ
Type safety**
Wrong cut type or array type โ **compiler error**. The type system prevents mixing single cuts with parallel updates.
**โ
Leaner trait hierarchy**
Two traits eliminated (`OracleFeas2`, `SearchSpaceQ`) via default methods โ same power, fewer concepts. ๐งน
**โ
Composition over inheritance**
`BSearchAdaptor` = `OracleFeas` + `SearchSpace + Clone` โ `OracleBS`. Traits compose like building blocks. ๐งฑ
]
---
### ๐ Type-Level State Machine
The algorithm functions encode a **type-level protocol**:
```
cutting_plane_feas
where T: UpdateByCutChoice,
Oracle: OracleFeas,
Space: SearchSpace
๐
Oracle::CutChoice โโโ type-equals โโโโ T โโโ implements โโโโ UpdateByCutChoice
Space::ArrayType โโโ type-equals โโโโ Oracle::ArrayType โโโ T::ArrayType
```
If any of these type relationships is violated, the code **doesn't compile** ๐ซ. This is Rust's superpower โ catching architectural mismatches at compile time.
---
### ๐ Benchmark: ProfitOracle
```terminal
test_profit_oracle ...... regression: 83 iterations
test_profit_oracle_rb ..... regression: 90 iterations
test_profit_oracle_q ...... regression: 29 iterations
```
The quantized oracle (`OracleOptimQ`) converges **~3ร faster** in iterations than the continuous variant, because the discrete search space is smaller. The same algorithm function adapts via trait dispatch! โก
All numerical regression values are preserved exactly โ the type-level refactoring changed no arithmetic.
---
count: false
class: nord-dark, middle, center
## โ
Summary
### ๐ฆ Rust Traits Make the Ellipsoid Method:
- ๐ฎ **Generic** โ same algorithm, any oracle
- ๐ฅ **Flexible** โ any search space (`Ell`, `EllStable`, `Ell1D`)
- โ๏ธ **Composable** โ cut strategies as named types (`SingleCut` / `ParallelCut`)
- โก **Zero-cost** โ all dispatch resolved at compile time
- ๐งน **Clean** โ merged traits via default methods, two traits removed
- ๐งฉ **Extensible** โ new oracles, spaces, or strategies without touching existing code
The **three-pillar trait architecture** demonstrates how Rust's type system can model a complex optimization algorithm with clarity, safety, and performance. ๐
---
count: false
class: nord-dark, middle, center
## ๐ค Q&A
### Questions? ๐