Skip to content

Commit

Permalink
feat: Add a parent namespace to Parameters. (#234)
Browse files Browse the repository at this point in the history
Core Parameters can now be identified with an optional parent
string. This is helpful for creating Parameters in compound
nodes without risking naming conflicts with the user's own
parameter names.

Fixes #179.
  • Loading branch information
jetuk authored Aug 7, 2024
1 parent cc1bb93 commit f28360c
Show file tree
Hide file tree
Showing 58 changed files with 325 additions and 206 deletions.
2 changes: 1 addition & 1 deletion pywr-core/src/aggregated_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ mod tests {
network.connect_nodes(input_node, link_node1).unwrap();
network.connect_nodes(link_node1, output_node1).unwrap();

let factor_profile = MonthlyProfileParameter::new("factor-profile", [2.0; 12], None);
let factor_profile = MonthlyProfileParameter::new("factor-profile".into(), [2.0; 12], None);
let factor_profile_idx = network.add_simple_parameter(Box::new(factor_profile)).unwrap();

let factors = Some(Factors::Ratio(vec![factor_profile_idx.into(), 1.0.into()]));
Expand Down
25 changes: 15 additions & 10 deletions pywr-core/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use crate::edge::{Edge, EdgeIndex, EdgeVec};
use crate::metric::{MetricF64, SimpleMetricF64};
use crate::models::ModelDomain;
use crate::node::{Node, NodeVec, StorageInitialVolume};
use crate::parameters::{GeneralParameterType, ParameterCollection, ParameterIndex, ParameterStates, VariableConfig};
use crate::parameters::{
GeneralParameterType, ParameterCollection, ParameterIndex, ParameterName, ParameterStates, VariableConfig,
};
use crate::recorders::{MetricSet, MetricSetIndex, MetricSetState};
use crate::scenario::ScenarioIndex;
use crate::solvers::{MultiStateSolver, Solver, SolverFeatures, SolverTimings};
Expand Down Expand Up @@ -1118,15 +1120,15 @@ impl Network {
}

/// Get a `Parameter` from a parameter's name
pub fn get_parameter_by_name(&self, name: &str) -> Result<&dyn parameters::Parameter, PywrError> {
pub fn get_parameter_by_name(&self, name: &ParameterName) -> Result<&dyn parameters::Parameter, PywrError> {
match self.parameters.get_f64_by_name(name) {
Some(parameter) => Ok(parameter),
None => Err(PywrError::ParameterNotFound(name.to_string())),
}
}

/// Get a `ParameterIndex` from a parameter's name
pub fn get_parameter_index_by_name(&self, name: &str) -> Result<ParameterIndex<f64>, PywrError> {
pub fn get_parameter_index_by_name(&self, name: &ParameterName) -> Result<ParameterIndex<f64>, PywrError> {
match self.parameters.get_f64_index_by_name(name) {
Some(idx) => Ok(idx),
None => Err(PywrError::ParameterNotFound(name.to_string())),
Expand All @@ -1142,15 +1144,15 @@ impl Network {
}

/// Get a `IndexParameter` from a parameter's name
pub fn get_index_parameter_by_name(&self, name: &str) -> Result<&dyn parameters::Parameter, PywrError> {
pub fn get_index_parameter_by_name(&self, name: &ParameterName) -> Result<&dyn parameters::Parameter, PywrError> {
match self.parameters.get_usize_by_name(name) {
Some(parameter) => Ok(parameter),
None => Err(PywrError::ParameterNotFound(name.to_string())),
}
}

/// Get a `IndexParameterIndex` from a parameter's name
pub fn get_index_parameter_index_by_name(&self, name: &str) -> Result<ParameterIndex<usize>, PywrError> {
pub fn get_index_parameter_index_by_name(&self, name: &ParameterName) -> Result<ParameterIndex<usize>, PywrError> {
match self.parameters.get_usize_index_by_name(name) {
Some(idx) => Ok(idx),
None => Err(PywrError::ParameterNotFound(name.to_string())),
Expand All @@ -1171,7 +1173,7 @@ impl Network {
/// Get a `MultiValueParameterIndex` from a parameter's name
pub fn get_multi_valued_parameter_index_by_name(
&self,
name: &str,
name: &ParameterName,
) -> Result<ParameterIndex<MultiValue>, PywrError> {
match self.parameters.get_multi_index_by_name(name) {
Some(idx) => Ok(idx),
Expand Down Expand Up @@ -1729,7 +1731,7 @@ mod tests {
let mut network = Network::default();
let _node_index = network.add_input_node("input", None).unwrap();

let input_max_flow = parameters::ConstantParameter::new("my-constant", 10.0);
let input_max_flow = parameters::ConstantParameter::new("my-constant".into(), 10.0);
let parameter = network.add_const_parameter(Box::new(input_max_flow)).unwrap();

// assign the new parameter to one of the nodes.
Expand Down Expand Up @@ -1788,7 +1790,10 @@ mod tests {
let recorder = AssertionRecorder::new("output-flow", MetricF64::NodeInFlow(idx), expected, None, None);
model.network_mut().add_recorder(Box::new(recorder)).unwrap();

let idx = model.network().get_parameter_index_by_name("total-demand").unwrap();
let idx = model
.network()
.get_parameter_index_by_name(&"total-demand".into())
.unwrap();
let expected = Array2::from_elem((366, 10), 12.0);
let recorder = AssertionRecorder::new("total-demand", idx.into(), expected, None, None);
model.network_mut().add_recorder(Box::new(recorder)).unwrap();
Expand Down Expand Up @@ -1846,7 +1851,7 @@ mod tests {
// Set-up a control curve that uses the proportional volume
// This should be use the initial proportion (100%) on the first time-step, and then the previous day's end value
let cc = ControlCurveInterpolatedParameter::new(
"interp",
"interp".into(),
MetricF64::DerivedMetric(dm_idx),
vec![],
vec![100.0.into(), 0.0.into()],
Expand Down Expand Up @@ -1967,7 +1972,7 @@ mod tests {
let mut model = simple_model(1);

let variable = ActivationFunction::Unit { min: 0.0, max: 10.0 };
let input_max_flow = parameters::ConstantParameter::new("my-constant", 10.0);
let input_max_flow = parameters::ConstantParameter::new("my-constant".into(), 10.0);

assert!(input_max_flow.can_be_f64_variable());

Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/aggregated.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Parameter, ParameterState, PywrError, SimpleParameter};
use super::{Parameter, ParameterName, ParameterState, PywrError, SimpleParameter};
use crate::metric::{MetricF64, SimpleMetricF64};
use crate::network::Network;
use crate::parameters::{GeneralParameter, ParameterMeta};
Expand Down Expand Up @@ -41,7 +41,7 @@ impl<M> AggregatedParameter<M>
where
M: Send + Sync + Clone,
{
pub fn new(name: &str, metrics: &[M], agg_func: AggFunc) -> Self {
pub fn new(name: ParameterName, metrics: &[M], agg_func: AggFunc) -> Self {
Self {
meta: ParameterMeta::new(name),
metrics: metrics.to_vec(),
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/aggregated_index.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// AggregatedIndexParameter
///
use super::{Parameter, ParameterState, PywrError};
use super::{Parameter, ParameterName, ParameterState, PywrError};
use crate::metric::MetricUsize;
use crate::network::Network;
use crate::parameters::{GeneralParameter, ParameterMeta};
Expand Down Expand Up @@ -41,7 +41,7 @@ pub struct AggregatedIndexParameter {
}

impl AggregatedIndexParameter {
pub fn new(name: &str, values: Vec<MetricUsize>, agg_func: AggIndexFunc) -> Self {
pub fn new(name: ParameterName, values: Vec<MetricUsize>, agg_func: AggIndexFunc) -> Self {
Self {
meta: ParameterMeta::new(name),
values,
Expand Down
11 changes: 8 additions & 3 deletions pywr-core/src/parameters/array.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::network::Network;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -13,7 +13,7 @@ pub struct Array1Parameter {
}

impl Array1Parameter {
pub fn new(name: &str, array: Array1<f64>, timestep_offset: Option<i32>) -> Self {
pub fn new(name: ParameterName, array: Array1<f64>, timestep_offset: Option<i32>) -> Self {
Self {
meta: ParameterMeta::new(name),
array,
Expand Down Expand Up @@ -60,7 +60,12 @@ pub struct Array2Parameter {
}

impl Array2Parameter {
pub fn new(name: &str, array: Array2<f64>, scenario_group_index: usize, timestep_offset: Option<i32>) -> Self {
pub fn new(
name: ParameterName,
array: Array2<f64>,
scenario_group_index: usize,
timestep_offset: Option<i32>,
) -> Self {
Self {
meta: ParameterMeta::new(name),
array,
Expand Down
6 changes: 4 additions & 2 deletions pywr-core/src/parameters/asymmetric.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::metric::MetricUsize;
use crate::network::Network;
use crate::parameters::{downcast_internal_state_mut, GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{
downcast_internal_state_mut, GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState,
};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -13,7 +15,7 @@ pub struct AsymmetricSwitchIndexParameter {
}

impl AsymmetricSwitchIndexParameter {
pub fn new(name: &str, on_parameter: MetricUsize, off_parameter: MetricUsize) -> Self {
pub fn new(name: ParameterName, on_parameter: MetricUsize, off_parameter: MetricUsize) -> Self {
Self {
meta: ParameterMeta::new(name),
on_parameter,
Expand Down
6 changes: 3 additions & 3 deletions pywr-core/src/parameters/constant.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::parameters::{
downcast_internal_state_mut, downcast_internal_state_ref, downcast_variable_config_ref, ActivationFunction,
ConstParameter, Parameter, ParameterMeta, ParameterState, VariableConfig, VariableParameter,
ConstParameter, Parameter, ParameterMeta, ParameterName, ParameterState, VariableConfig, VariableParameter,
};
use crate::scenario::ScenarioIndex;
use crate::state::ConstParameterValues;
Expand All @@ -16,7 +16,7 @@ pub struct ConstantParameter {
type InternalValue = Option<f64>;

impl ConstantParameter {
pub fn new(name: &str, value: f64) -> Self {
pub fn new(name: ParameterName, value: f64) -> Self {
Self {
meta: ParameterMeta::new(name),
value,
Expand Down Expand Up @@ -129,7 +129,7 @@ mod tests {
let domain = default_domain();

let var = ActivationFunction::Unit { min: 0.0, max: 2.0 };
let p = ConstantParameter::new("test", 1.0);
let p = ConstantParameter::new("test".into(), 1.0);
let mut state = p
.setup(domain.time().timesteps(), domain.scenarios().indices().first().unwrap())
.unwrap();
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/control_curves/apportion.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::{MultiValue, State};
use crate::timestep::Timestep;
Expand All @@ -22,7 +22,7 @@ pub struct ApportionParameter {
}

impl ApportionParameter {
pub fn new(name: &str, metric: MetricF64, control_curve: MetricF64) -> Self {
pub fn new(name: ParameterName, metric: MetricF64, control_curve: MetricF64) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/control_curves/index.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -13,7 +13,7 @@ pub struct ControlCurveIndexParameter {
}

impl ControlCurveIndexParameter {
pub fn new(name: &str, metric: MetricF64, control_curves: Vec<MetricF64>) -> Self {
pub fn new(name: ParameterName, metric: MetricF64, control_curves: Vec<MetricF64>) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/control_curves/interpolated.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::interpolate::interpolate;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -15,7 +15,7 @@ pub struct ControlCurveInterpolatedParameter {
}

impl ControlCurveInterpolatedParameter {
pub fn new(name: &str, metric: MetricF64, control_curves: Vec<MetricF64>, values: Vec<MetricF64>) -> Self {
pub fn new(name: ParameterName, metric: MetricF64, control_curves: Vec<MetricF64>, values: Vec<MetricF64>) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
Expand Down
8 changes: 4 additions & 4 deletions pywr-core/src/parameters/control_curves/piecewise.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::interpolate::interpolate;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -18,7 +18,7 @@ pub struct PiecewiseInterpolatedParameter {

impl PiecewiseInterpolatedParameter {
pub fn new(
name: &str,
name: ParameterName,
metric: MetricF64,
control_curves: Vec<MetricF64>,
values: Vec<[f64; 2]>,
Expand Down Expand Up @@ -85,12 +85,12 @@ mod test {
let mut model = simple_model(1);

// Create an artificial volume series to use for the interpolation test
let volume = Array1Parameter::new("test-x", Array1::linspace(1.0, 0.0, 21), None);
let volume = Array1Parameter::new("test-x".into(), Array1::linspace(1.0, 0.0, 21), None);

let volume_idx = model.network_mut().add_parameter(Box::new(volume)).unwrap();

let parameter = PiecewiseInterpolatedParameter::new(
"test-parameter",
"test-parameter".into(),
volume_idx.into(), // Interpolate with the parameter based values
vec![0.8.into(), 0.5.into()],
vec![[10.0, 1.0], [0.0, 0.0], [-1.0, -10.0]],
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/control_curves/simple.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -14,7 +14,7 @@ pub struct ControlCurveParameter {
}

impl ControlCurveParameter {
pub fn new(name: &str, metric: MetricF64, control_curves: Vec<MetricF64>, values: Vec<MetricF64>) -> Self {
pub fn new(name: ParameterName, metric: MetricF64, control_curves: Vec<MetricF64>, values: Vec<MetricF64>) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
Expand Down
4 changes: 2 additions & 2 deletions pywr-core/src/parameters/control_curves/volume_between.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::metric::SimpleMetricF64;
use crate::parameters::{Parameter, ParameterMeta, ParameterState, SimpleParameter};
use crate::parameters::{Parameter, ParameterMeta, ParameterName, ParameterState, SimpleParameter};
use crate::scenario::ScenarioIndex;
use crate::state::SimpleParameterValues;
use crate::timestep::Timestep;
Expand All @@ -14,7 +14,7 @@ pub struct VolumeBetweenControlCurvesParameter<M> {
}

impl<M> VolumeBetweenControlCurvesParameter<M> {
pub fn new(name: &str, total: M, upper: Option<M>, lower: Option<M>) -> Self {
pub fn new(name: ParameterName, total: M, upper: Option<M>, lower: Option<M>) -> Self {
Self {
meta: ParameterMeta::new(name),
total,
Expand Down
9 changes: 5 additions & 4 deletions pywr-core/src/parameters/delay.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::metric::{MetricF64, SimpleMetricF64};
use crate::network::Network;
use crate::parameters::{
downcast_internal_state_mut, GeneralParameter, Parameter, ParameterMeta, ParameterState, SimpleParameter,
downcast_internal_state_mut, GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState,
SimpleParameter,
};
use crate::scenario::ScenarioIndex;
use crate::state::{SimpleParameterValues, State};
Expand All @@ -17,7 +18,7 @@ pub struct DelayParameter<M> {
}

impl<M> DelayParameter<M> {
pub fn new(name: &str, metric: M, delay: usize, initial_value: f64) -> Self {
pub fn new(name: ParameterName, metric: M, delay: usize, initial_value: f64) -> Self {
Self {
meta: ParameterMeta::new(name),
metric,
Expand Down Expand Up @@ -173,13 +174,13 @@ mod test {

// Create an artificial volume series to use for the delay test
let volumes = Array1::linspace(1.0, 0.0, 21);
let volume = Array1Parameter::new("test-x", volumes.clone(), None);
let volume = Array1Parameter::new("test-x".into(), volumes.clone(), None);

let volume_idx = model.network_mut().add_parameter(Box::new(volume)).unwrap();

const DELAY: usize = 3; // 3 time-step delay
let parameter = DelayParameter::new(
"test-parameter",
"test-parameter".into(),
volume_idx.into(), // Interpolate with the parameter based values
DELAY,
0.0,
Expand Down
8 changes: 4 additions & 4 deletions pywr-core/src/parameters/discount_factor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::metric::MetricF64;
use crate::network::Network;
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterState};
use crate::parameters::{GeneralParameter, Parameter, ParameterMeta, ParameterName, ParameterState};
use crate::scenario::ScenarioIndex;
use crate::state::State;
use crate::timestep::Timestep;
Expand All @@ -14,7 +14,7 @@ pub struct DiscountFactorParameter {
}

impl DiscountFactorParameter {
pub fn new(name: &str, discount_rate: MetricF64, base_year: i32) -> Self {
pub fn new(name: ParameterName, discount_rate: MetricF64, base_year: i32) -> Self {
Self {
meta: ParameterMeta::new(name),
discount_rate,
Expand Down Expand Up @@ -66,12 +66,12 @@ mod test {

// Create an artificial volume series to use for the delay test
let volumes = Array1::linspace(1.0, 0.0, 21);
let volume = Array1Parameter::new("test-x", volumes.clone(), None);
let volume = Array1Parameter::new("test-x".into(), volumes.clone(), None);

let _volume_idx = network.add_parameter(Box::new(volume)).unwrap();

let parameter = DiscountFactorParameter::new(
"test-parameter",
"test-parameter".into(),
0.03.into(), // Interpolate with the parameter based values
2020,
);
Expand Down
Loading

0 comments on commit f28360c

Please sign in to comment.