Skip to content

Commit

Permalink
feat: Add min parameter (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
s-simoncelli authored Sep 18, 2023
1 parent 72b4456 commit 5f9702c
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 3 deletions.
45 changes: 45 additions & 0 deletions src/parameters/min.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::metric::Metric;
use crate::model::Model;
use crate::parameters::{Parameter, ParameterMeta};
use crate::scenario::ScenarioIndex;
use std::any::Any;

use crate::state::State;
use crate::timestep::Timestep;
use crate::PywrError;

pub struct MinParameter {
meta: ParameterMeta,
metric: Metric,
threshold: f64,
}

impl MinParameter {
pub fn new(name: &str, metric: Metric, threshold: f64) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
threshold,
}
}
}

impl Parameter for MinParameter {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn meta(&self) -> &ParameterMeta {
&self.meta
}
fn compute(
&self,
_timestep: &Timestep,
_scenario_index: &ScenarioIndex,
model: &Model,
state: &State,
_internal_state: &mut Option<Box<dyn Any + Send>>,
) -> Result<f64, PywrError> {
let x = self.metric.get_value(model, state)?;
Ok(x.min(self.threshold))
}
}
2 changes: 2 additions & 0 deletions src/parameters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod control_curves;
mod delay;
mod indexed_array;
mod max;
mod min;
mod negative;
mod polynomial;
mod profiles;
Expand Down Expand Up @@ -33,6 +34,7 @@ pub use control_curves::{
pub use delay::DelayParameter;
pub use indexed_array::IndexedArrayParameter;
pub use max::MaxParameter;
pub use min::MinParameter;
pub use negative::NegativeParameter;
pub use polynomial::Polynomial1DParameter;
pub use profiles::{DailyProfileParameter, MonthlyInterpDay, MonthlyProfileParameter, UniformDrawdownProfileParameter};
Expand Down
70 changes: 69 additions & 1 deletion src/schema/parameters/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::schema::parameters::{
};
use crate::{ParameterIndex, PywrError};
use pywr_schema::parameters::{
ConstantParameter as ConstantParameterV1, MaxParameter as MaxParameterV1, NegativeParameter as NegativeParameterV1,
ConstantParameter as ConstantParameterV1, MaxParameter as MaxParameterV1, MinParameter as MinParameterV1,
NegativeParameter as NegativeParameterV1,
};
use std::collections::HashMap;
use std::path::Path;
Expand Down Expand Up @@ -114,6 +115,73 @@ impl TryFromV1Parameter<MaxParameterV1> for MaxParameter {
}
}

/// This parameter takes the minimum of another Parameter and a constant value (threshold).
///
/// # Arguments
///
/// * `parameter` - The parameter to compare with the float.
/// * `threshold` - The threshold value to compare with the given parameter.
///
/// # Examples
///
/// ```json
/// {
/// "type": "Min",
/// "parameter": {
/// "type": "MonthlyProfile",
/// "values": [1, 4, 5, 9, 1, 5, 10, 8, 11, 9, 11 ,12]
/// },
/// "threshold": 2
/// }
/// ```
#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
pub struct MinParameter {
#[serde(flatten)]
pub meta: ParameterMeta,
pub parameter: DynamicFloatValue,
pub threshold: Option<f64>,
}

impl MinParameter {
pub fn node_references(&self) -> HashMap<&str, &str> {
HashMap::new()
}

pub fn add_to_model(
&self,
model: &mut crate::model::Model,
tables: &LoadedTableCollection,
data_path: Option<&Path>,
) -> Result<ParameterIndex, PywrError> {
let idx = self.parameter.load(model, tables, data_path)?;
let threshold = self.threshold.unwrap_or(0.0);

let p = crate::parameters::MinParameter::new(&self.meta.name, idx, threshold);
model.add_parameter(Box::new(p))
}
}

impl TryFromV1Parameter<MinParameterV1> for MinParameter {
type Error = ConversionError;

fn try_from_v1_parameter(
v1: MinParameterV1,
parent_node: Option<&str>,
unnamed_count: &mut usize,
) -> Result<Self, Self::Error> {
let meta: ParameterMeta = v1.meta.into_v2_parameter(parent_node, unnamed_count);

let parameter = v1.parameter.try_into_v2_parameter(Some(&meta.name), unnamed_count)?;

let p = Self {
meta,
parameter,
threshold: v1.threshold,
};
Ok(p)
}
}

#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)]
pub struct NegativeParameter {
#[serde(flatten)]
Expand Down
10 changes: 8 additions & 2 deletions src/schema/parameters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub use super::parameters::control_curves::{
ControlCurveIndexParameter, ControlCurveInterpolatedParameter, ControlCurveParameter,
ControlCurvePiecewiseInterpolatedParameter,
};
pub use super::parameters::core::{ConstantParameter, MaxParameter, NegativeParameter};
pub use super::parameters::core::{ConstantParameter, MaxParameter, MinParameter, NegativeParameter};
pub use super::parameters::delay::DelayParameter;
pub use super::parameters::indexed_array::IndexedArrayParameter;
pub use super::parameters::polynomial::Polynomial1DParameter;
Expand Down Expand Up @@ -135,6 +135,7 @@ pub enum Parameter {
MonthlyProfile(MonthlyProfileParameter),
UniformDrawdownProfile(UniformDrawdownProfileParameter),
Max(MaxParameter),
Min(MinParameter),
Negative(NegativeParameter),
Polynomial1D(Polynomial1DParameter),
ParameterThreshold(ParameterThresholdParameter),
Expand All @@ -160,6 +161,7 @@ impl Parameter {
Self::MonthlyProfile(p) => p.meta.name.as_str(),
Self::UniformDrawdownProfile(p) => p.meta.name.as_str(),
Self::Max(p) => p.meta.name.as_str(),
Self::Min(p) => p.meta.name.as_str(),
Self::Negative(p) => p.meta.name.as_str(),
Self::Polynomial1D(p) => p.meta.name.as_str(),
Self::ParameterThreshold(p) => p.meta.name.as_str(),
Expand Down Expand Up @@ -187,6 +189,7 @@ impl Parameter {
Self::MonthlyProfile(p) => p.node_references(),
Self::UniformDrawdownProfile(p) => p.node_references(),
Self::Max(p) => p.node_references(),
Self::Min(p) => p.node_references(),
Self::Negative(p) => p.node_references(),
Self::Polynomial1D(p) => p.node_references(),
Self::ParameterThreshold(p) => p.node_references(),
Expand Down Expand Up @@ -231,6 +234,7 @@ impl Parameter {
Self::MonthlyProfile(_) => "MonthlyProfile",
Self::UniformDrawdownProfile(_) => "UniformDrawdownProfile",
Self::Max(_) => "Max",
Self::Min(_) => "Min",
Self::Negative(_) => "Negative",
Self::Polynomial1D(_) => "Polynomial1D",
Self::ParameterThreshold(_) => "ParameterThreshold",
Expand Down Expand Up @@ -263,6 +267,7 @@ impl Parameter {
Self::MonthlyProfile(p) => ParameterType::Parameter(p.add_to_model(model, tables)?),
Self::UniformDrawdownProfile(p) => ParameterType::Parameter(p.add_to_model(model, tables)?),
Self::Max(p) => ParameterType::Parameter(p.add_to_model(model, tables, data_path)?),
Self::Min(p) => ParameterType::Parameter(p.add_to_model(model, tables, data_path)?),
Self::Negative(p) => ParameterType::Parameter(p.add_to_model(model, tables, data_path)?),
Self::Polynomial1D(p) => ParameterType::Parameter(p.add_to_model(model)?),
Self::ParameterThreshold(p) => ParameterType::Index(p.add_to_model(model, tables, data_path)?),
Expand Down Expand Up @@ -332,7 +337,8 @@ impl TryFromV1Parameter<ParameterV1> for Parameter {
CoreParameter::TablesArray(p) => {
Parameter::TablesArray(p.try_into_v2_parameter(parent_node, unnamed_count)?)
}
CoreParameter::Min(_) | CoreParameter::Division(_) => todo!(),
CoreParameter::Min(p) => Parameter::Min(p.try_into_v2_parameter(parent_node, unnamed_count)?),
CoreParameter::Division(_) => todo!(),
},
ParameterV1::Custom(p) => {
println!("Custom parameter: {:?} ({})", p.meta.name, p.ty);
Expand Down

0 comments on commit 5f9702c

Please sign in to comment.