#[cfg(feature = "pounce")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
use oximo::prelude::*;
use oximo::solvers::Pounce;
let m = Model::new("alkylation");
variable!(m, 10.0 <= olefin <= 2000.0, initial = 1745.0);
variable!(m, 0.0 <= isor <= 16000.0, initial = 12000.0);
variable!(m, 0.0 <= acid <= 120.0, initial = 110.0);
variable!(m, 0.0 <= alkylate <= 5000.0, initial = 3048.0);
variable!(m, 0.0 <= isom <= 2000.0, initial = 1974.0);
variable!(m, 85.0 <= strength <= 93.0, initial = 89.2);
variable!(m, 90.0 <= octane <= 95.0, initial = 92.8);
variable!(m, 3.0 <= ratio <= 12.0, initial = 8.0);
variable!(m, 1.2 <= dilute <= 4.0, initial = 3.6);
variable!(m, 145.0 <= f4 <= 162.0, initial = 145.0);
constraint!(m, yield_, alkylate == olefin * (1.12 + 0.13167 * ratio - 0.00667 * ratio.powi(2)));
constraint!(m, makeup, alkylate == olefin + isom - 0.22 * alkylate);
constraint!(m, sdef, acid == alkylate * dilute * strength / (98.0 - strength) / 1000.0);
constraint!(
m,
motor,
octane == 86.35 + 1.098 * ratio - 0.038 * ratio.powi(2) - 0.325 * (89.0 - strength)
);
constraint!(m, drat, ratio == (isor + isom) / olefin);
constraint!(m, ddil, dilute == 35.82 - 0.222 * f4);
constraint!(m, df4, f4 == -133.0 + 3.0 * octane);
param!(m, alk_price = 0.063);
objective!(
m,
Max,
alk_price * alkylate * octane - 5.04 * olefin - 0.035 * isor - 10.0 * acid - 3.36 * isom
);
#[cfg(not(feature = "pounce-enzyme"))]
let opts = PounceOptions::default().tol(1e-5);
#[cfg(feature = "pounce-enzyme")]
let opts = PounceOptions::default();
let result = Pounce.solve(&m, &opts)?;
println!("status = {:?}", result.termination);
println!("profit = {:.2} $/day", result.objective().unwrap_or(f64::NAN));
println!();
let streams = [
("olefin feed", olefin, "bpd"),
("isobutane recycle", isor, "bpd"),
("isobutane makeup", isom, "bpd"),
("alkylate yield", alkylate, "bpd"),
("acid addition", acid, "1000 lb/day"),
("acid strength", strength, "wt pct"),
("motor octane", octane, ""),
("i/o ratio", ratio, ""),
("dilution factor", dilute, ""),
("F-4 performance", f4, ""),
];
for (name, x, unit) in streams {
println!(" {name:<18} = {:>9.2} {unit}", result.value_of(x).unwrap_or(f64::NAN));
}
println!();
println!("alkylate price sweep:");
let mut solver = Pounce.persistent();
for price in [0.055, 0.059, 0.063, 0.067, 0.071] {
alk_price.set_param_value(price);
let res = solver.solve(&m, &opts)?;
println!(
" price {price:.3} $/oct-bbl -> profit {:>8.2} $/day, olefin {:>8.2} bpd, octane {:.2}",
res.objective().unwrap_or(f64::NAN),
res.value_of(olefin).unwrap_or(f64::NAN),
res.value_of(octane).unwrap_or(f64::NAN),
);
}
Ok(())
}
#[cfg(not(feature = "pounce"))]
fn main() {
println!("Enable the POUNCE backend:");
println!(" cargo run -p oximo --example pounce_alkylation --features pounce");
}