Skip to content

Commit

Permalink
feat: Add clp feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
jetuk committed Jun 20, 2024
1 parent 8936baa commit 2e41933
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 12 deletions.
7 changes: 7 additions & 0 deletions pywr-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@ schemars = { workspace = true }

pywr-core = { path = "../pywr-core" }
pywr-schema = { path = "../pywr-schema" }

[features]
clp = ["pywr-core/clp"]
highs = ["pywr-core/highs"]
ipm-ocl = ["pywr-core/ipm-ocl"]
ipm-simd = ["pywr-core/ipm-simd"]
default = ["clp"]
12 changes: 9 additions & 3 deletions pywr-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use anyhow::{bail, Context, Result};
use clap::{Parser, Subcommand, ValueEnum};
#[cfg(feature = "ipm-ocl")]
use pywr_core::solvers::{ClIpmF32Solver, ClIpmF64Solver, ClIpmSolverSettings};
#[cfg(feature = "clp")]
use pywr_core::solvers::{ClpSolver, ClpSolverSettings};
#[cfg(feature = "highs")]
use pywr_core::solvers::{HighsSolver, HighsSolverSettings};
Expand All @@ -22,6 +23,7 @@ use std::path::{Path, PathBuf};

#[derive(Copy, Clone, ValueEnum)]
enum Solver {
#[cfg(feature = "clp")]
Clp,
#[cfg(feature = "highs")]
HIGHS,
Expand All @@ -36,6 +38,7 @@ enum Solver {
impl Display for Solver {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
#[cfg(feature = "clp")]
Solver::Clp => write!(f, "clp"),
#[cfg(feature = "highs")]
Solver::HIGHS => write!(f, "highs"),
Expand Down Expand Up @@ -79,7 +82,7 @@ enum Commands {
/// Path to Pywr model JSON.
model: PathBuf,
/// Solver to use.
#[arg(short, long, default_value_t=Solver::Clp)]
#[arg(short, long)]
solver: Solver,
#[arg(short, long)]
data_path: Option<PathBuf>,
Expand All @@ -96,7 +99,7 @@ enum Commands {
/// Path to Pywr model JSON.
model: PathBuf,
/// Solver to use.
#[arg(short, long, default_value_t=Solver::Clp)]
#[arg(short, long)]
solver: Solver,
#[arg(short, long)]
data_path: Option<PathBuf>,
Expand All @@ -114,7 +117,7 @@ enum Commands {
density: usize,
num_scenarios: usize,
/// Solver to use.
#[arg(short, long, default_value_t=Solver::Clp)]
#[arg(short, long)]
solver: Solver,
},
ExportSchema {
Expand Down Expand Up @@ -263,6 +266,7 @@ fn run(path: &Path, solver: &Solver, data_path: Option<&Path>, output_path: Opti
let model = schema_v2.build_model(data_path, output_path).unwrap();

match *solver {
#[cfg(feature = "clp")]
Solver::Clp => model.run::<ClpSolver>(&ClpSolverSettings::default()),
#[cfg(feature = "highs")]
Solver::HIGHS => model.run::<HighsSolver>(&HighsSolverSettings::default()),
Expand All @@ -285,6 +289,7 @@ fn run_multi(path: &Path, solver: &Solver, data_path: Option<&Path>, output_path
let model = schema_v2.build_model(data_path, output_path).unwrap();

match *solver {
#[cfg(feature = "clp")]
Solver::Clp => model.run::<ClpSolver>(&ClpSolverSettings::default()),
#[cfg(feature = "highs")]
Solver::HIGHS => model.run::<HighsSolver>(&HighsSolverSettings::default()),
Expand All @@ -303,6 +308,7 @@ fn run_random(num_systems: usize, density: usize, num_scenarios: usize, solver:
let model = make_random_model(num_systems, density, num_scenarios, &mut rng).unwrap();

match *solver {
#[cfg(feature = "clp")]
Solver::Clp => model.run::<ClpSolver>(&ClpSolverSettings::default()),
#[cfg(feature = "highs")]
Solver::HIGHS => model.run::<HighsSolver>(&HighsSolverSettings::default()),
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ csv = { workspace = true }
ipm-ocl = { path = "../ipm-ocl", optional = true }
ipm-simd = { path = "../ipm-simd", optional = true }
tracing = { workspace = true }
coinclp-sys = { version = "0.2.5", optional = true }
coinclp-sys = { version = "0.2", optional = true }
highs-sys = { version = "1.6.2", optional = true }
nalgebra = "0.32.3"
chrono = { workspace = true }
Expand All @@ -51,7 +51,7 @@ serde = { version = "1.0.197", features = ["derive"] }
criterion = "0.5"

[features]
clp = ["dep:coinclp-sys"]
clp = ["dep:coinclp-sys", "coinclp-sys/default"]
highs = ["dep:highs-sys"]
ipm-ocl = ["dep:ipm-ocl", "dep:ocl"]
ipm-simd = ["dep:ipm-simd"]
Expand Down
4 changes: 4 additions & 0 deletions pywr-core/benches/random_models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
#[cfg(feature = "ipm-ocl")]
use pywr_core::solvers::{ClIpmF64Solver, ClIpmSolverSettings, ClIpmSolverSettingsBuilder};
#[cfg(feature = "clp")]
use pywr_core::solvers::{ClpSolver, ClpSolverSettings, ClpSolverSettingsBuilder};
#[cfg(feature = "highs")]
use pywr_core::solvers::{HighsSolver, HighsSolverSettings};
Expand Down Expand Up @@ -50,6 +51,7 @@ fn random_benchmark(

for setup in solver_setups {
match &setup.setting {
#[cfg(feature = "clp")]
SolverSetting::Clp(settings) => {
let parameter_string = format!("clp * {n_sys} * {density} * {n_sc} * {}", &setup.name);

Expand Down Expand Up @@ -162,6 +164,7 @@ fn random_benchmark(
}

enum SolverSetting {
#[cfg(feature = "clp")]
Clp(ClpSolverSettings),
#[cfg(feature = "highs")]
Highs(HighsSolverSettings),
Expand All @@ -187,6 +190,7 @@ fn default_solver_setups() -> Vec<SolverSetup> {
setting: SolverSetting::Highs(HighsSolverSettings::default()),
name: "default".to_string(),
},
#[cfg(feature = "clp")]
SolverSetup {
setting: SolverSetting::Clp(ClpSolverSettings::default()),
name: "default".to_string(),
Expand Down
2 changes: 0 additions & 2 deletions pywr-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#![cfg_attr(feature = "ipm-simd", feature(portable_simd))]

extern crate core;

use crate::derived_metric::DerivedMetricIndex;
use crate::models::MultiNetworkTransferIndex;
use crate::node::NodeIndex;
Expand Down
2 changes: 2 additions & 0 deletions pywr-core/src/solvers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::ops::{Add, AddAssign};
use std::time::Duration;

mod builder;
#[cfg(feature = "clp")]
mod clp;
mod col_edge_map;
#[cfg(feature = "highs")]
Expand All @@ -19,6 +20,7 @@ mod ipm_simd;
pub use self::ipm_ocl::{ClIpmF32Solver, ClIpmF64Solver, ClIpmSolverSettings, ClIpmSolverSettingsBuilder};
#[cfg(feature = "ipm-simd")]
pub use self::ipm_simd::{SimdIpmF64Solver, SimdIpmSolverSettings, SimdIpmSolverSettingsBuilder};
#[cfg(feature = "clp")]
pub use clp::{ClpError, ClpSolver, ClpSolverSettings, ClpSolverSettingsBuilder};
#[cfg(feature = "highs")]
pub use highs::{HighsSolver, HighsSolverSettings, HighsSolverSettingsBuilder};
Expand Down
11 changes: 7 additions & 4 deletions pywr-core/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::recorders::AssertionRecorder;
use crate::scenario::ScenarioGroupCollection;
#[cfg(feature = "ipm-ocl")]
use crate::solvers::ClIpmF64Solver;
#[cfg(feature = "clp")]
use crate::solvers::ClpSolver;
#[cfg(feature = "highs")]
use crate::solvers::HighsSolver;
Expand Down Expand Up @@ -193,10 +194,12 @@ pub fn run_and_assert_parameter(
/// The model will only be run if the solver has the required solver features (and
/// is also enabled as a Cargo feature).
pub fn run_all_solvers(model: &Model) {
model
.run::<ClpSolver>(&Default::default())
.expect("Failed to solve with CLP");

#[cfg(feature = "clp")]
{
model
.run::<ClpSolver>(&Default::default())
.expect("Failed to solve with CLP");
}
#[cfg(feature = "highs")]
{
if model.check_solver_features::<HighsSolver>() {
Expand Down
3 changes: 3 additions & 0 deletions pywr-python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use pyo3::types::{PyDict, PyType};
#[cfg(feature = "ipm-ocl")]
use pywr_core::solvers::{ClIpmF32Solver, ClIpmF64Solver, ClIpmSolverSettings};
#[cfg(feature = "clp")]
use pywr_core::solvers::{ClpSolver, ClpSolverSettings, ClpSolverSettingsBuilder};
#[cfg(feature = "highs")]
use pywr_core::solvers::{HighsSolver, HighsSolverSettings, HighsSolverSettings, HighsSolverSettingsBuilde};
Expand Down Expand Up @@ -111,6 +112,7 @@ pub struct Model {
impl Model {
fn run(&self, solver_name: &str, solver_kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<()> {
match solver_name {
#[cfg(feature = "clp")]
"clp" => {
let settings = build_clp_settings(solver_kwargs)?;
self.model.run::<ClpSolver>(&settings)?;
Expand All @@ -131,6 +133,7 @@ impl Model {
}
}

#[cfg(feature = "clp")]
fn build_clp_settings(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult<ClpSolverSettings> {
let mut builder = ClpSolverSettingsBuilder::default();

Expand Down
6 changes: 5 additions & 1 deletion pywr-schema/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,8 @@ tempfile = "3.3.0"
[features]
# Core feature requires additional dependencies
core = ["dep:pywr-core", "dep:hdf5", "dep:csv", "dep:polars", "dep:pyo3", "dep:pyo3-polars", "dep:ndarray", "dep:tracing"]
default = ["core"]
clp = ["pywr-core/clp"]
highs = ["pywr-core/highs"]
ipm-ocl = ["pywr-core/ipm-ocl"]
ipm-simd = ["pywr-core/ipm-simd"]
default = ["core", "clp"]

0 comments on commit 2e41933

Please sign in to comment.