#![cfg_attr(
test,
allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::float_cmp,
clippy::panic,
clippy::too_many_lines
)
)]
#[cfg(all(feature = "highs", feature = "clp"))]
compile_error!(
"enable exactly one LP backend: `highs` OR `clp`. \
To use CLP, build with `--no-default-features --features clp`."
);
#[cfg(not(any(feature = "highs", feature = "clp")))]
compile_error!("no LP backend selected: enable exactly one of `highs` or `clp`.");
pub mod ffi;
#[cfg(feature = "clp")]
pub use ffi::clp as clp_ffi;
pub mod trait_def;
pub use trait_def::SolverInterface;
pub mod types;
pub use types::{
Basis, LpSolution, RowBatch, SolutionView, SolverError, SolverStatistics, StageTemplate,
};
pub mod profile;
pub use profile::{DEFAULT_PROFILE_HEURISTIC_SENTINEL, DEFAULT_PROFILE_IPM_UNBOUNDED_SENTINEL};
pub mod baking;
pub use baking::{BakingScratch, bake_rows_into_template};
pub mod backends;
pub use backends::profiled::ProfiledSolver;
#[cfg(feature = "highs")]
pub use backends::highs::{HighsProfile, HighsSolver, highs_version};
#[cfg(feature = "clp")]
pub use backends::clp::{ClpAlgorithm, ClpProfile, ClpSolver, clp_version};
#[cfg(feature = "clp")]
pub use backends::clp;
#[cfg(feature = "highs")]
pub use backends::highs;
#[cfg(feature = "clp")]
pub type ActiveSolver = ClpSolver;
#[cfg(all(feature = "highs", not(feature = "clp")))]
pub type ActiveSolver = HighsSolver;
#[cfg(feature = "clp")]
pub type ActiveProfile = ClpProfile;
#[cfg(all(feature = "highs", not(feature = "clp")))]
pub type ActiveProfile = HighsProfile;
#[cfg(feature = "clp")]
#[must_use]
pub fn active_solver_version() -> String {
clp_version()
}
#[cfg(all(feature = "highs", not(feature = "clp")))]
#[must_use]
pub fn active_solver_version() -> String {
highs_version()
}
#[cfg(feature = "clp")]
#[must_use]
pub fn active_solver_name() -> &'static str {
"CLP"
}
#[cfg(all(feature = "highs", not(feature = "clp")))]
#[must_use]
pub fn active_solver_name() -> &'static str {
"HiGHS"
}
#[cfg(feature = "clp")]
#[must_use]
pub fn active_solver_metadata_id() -> &'static str {
"clp"
}
#[cfg(all(feature = "highs", not(feature = "clp")))]
#[must_use]
pub fn active_solver_metadata_id() -> &'static str {
"highs"
}
#[cfg(all(feature = "test-support", feature = "highs"))]
pub mod test_support {
pub use crate::ffi::{
cobre_highs_get_double_option, cobre_highs_get_int_option, cobre_highs_set_double_option,
cobre_highs_set_int_option, cobre_highs_set_string_option,
};
}
#[cfg(all(test, any(feature = "highs", feature = "clp")))]
mod active_alias_tests {
use crate::{
ActiveProfile, ActiveSolver, SolverInterface, active_solver_metadata_id,
active_solver_name, active_solver_version,
};
#[allow(dead_code)]
const fn _assert_profile_identity(
p: ActiveProfile,
) -> <ActiveSolver as SolverInterface>::Profile {
p
}
#[test]
fn active_aliases_resolve_per_feature() {
let name = active_solver_name();
let version = active_solver_version();
assert!(!version.is_empty(), "active version must be non-empty");
assert!(
version.contains('.'),
"active version `{version}` should contain a `.`"
);
#[cfg(feature = "clp")]
assert_eq!(name, "CLP");
#[cfg(all(feature = "highs", not(feature = "clp")))]
assert_eq!(name, "HiGHS");
}
#[test]
fn active_solver_name_matches_instance_name() {
let solver = ActiveSolver::new().expect("active solver must construct");
assert_eq!(solver.name(), active_solver_name());
}
#[cfg(all(feature = "highs", not(feature = "clp")))]
#[test]
fn active_backend_is_highs_when_only_highs_enabled() {
assert_eq!(active_solver_name(), "HiGHS");
assert_eq!(active_solver_metadata_id(), "highs");
}
#[cfg(feature = "clp")]
#[test]
fn active_backend_is_clp_when_clp_enabled() {
assert_eq!(active_solver_name(), "CLP");
assert_eq!(active_solver_metadata_id(), "clp");
}
}