use crate::model::data_center::model::ServerType;
use noisy_float::prelude::*;
use pyo3::prelude::*;
use std::collections::HashMap;
#[derive(Clone, FromPyObject)]
pub struct SwitchingCostModel(HashMap<String, SwitchingCost>);
#[pyclass]
#[derive(Clone)]
pub struct SwitchingCost {
#[pyo3(get, set)]
pub energy_cost: f64,
#[pyo3(get, set)]
pub phi_min: f64,
#[pyo3(get, set)]
pub phi_max: f64,
#[pyo3(get, set)]
pub epsilon: f64,
#[pyo3(get, set)]
pub delta: f64,
#[pyo3(get, set)]
pub tau: f64,
#[pyo3(get, set)]
pub rho: f64,
}
impl SwitchingCost {
pub fn switching_cost(&self) -> N64 {
n64(
self.energy_cost * (self.epsilon + self.delta * self.phi_max)
+ self.tau
+ self.rho,
)
}
pub fn normalized_switching_cost(&self, delta: f64) -> N64 {
self.switching_cost() / (self.energy_cost * delta * self.phi_min)
}
pub fn from_normalized(
delta: f64,
normalized_switching_cost: f64,
energy_cost: f64,
phi_min: f64,
) -> Self {
Self {
energy_cost,
phi_min,
phi_max: 0.,
epsilon: 0.,
delta: 0.,
tau: 0.,
rho: normalized_switching_cost * energy_cost * delta * phi_min,
}
}
}
#[pymethods]
impl SwitchingCost {
#[new]
fn constructor(
energy_cost: f64,
phi_min: f64,
phi_max: f64,
epsilon: f64,
delta: f64,
tau: f64,
rho: f64,
) -> Self {
SwitchingCost {
energy_cost,
phi_min,
phi_max,
epsilon,
delta,
tau,
rho,
}
}
#[pyo3(name = "switching_cost")]
fn switching_cost_py(&self) -> PyResult<f64> {
Ok(self.switching_cost().raw())
}
#[pyo3(name = "normalized_switching_cost")]
fn normalized_switching_cost_py(&self, delta: f64) -> PyResult<f64> {
Ok(self.normalized_switching_cost(delta).raw())
}
#[staticmethod]
#[pyo3(name = "from_normalized")]
fn from_normalized_py(
delta: f64,
normalized_switching_cost: f64,
energy_cost: f64,
phi_min: f64,
) -> PyResult<Self> {
Ok(Self::from_normalized(
delta,
normalized_switching_cost,
energy_cost,
phi_min,
))
}
}
impl SwitchingCostModel {
pub fn new(switching_costs: HashMap<String, SwitchingCost>) -> Self {
SwitchingCostModel(switching_costs)
}
pub fn switching_costs(&self, server_types: &Vec<ServerType>) -> Vec<f64> {
server_types
.iter()
.map(|server_type| self.model(server_type).switching_cost().raw())
.collect()
}
pub fn normalized_switching_costs(
&self,
delta: f64,
server_types: &Vec<ServerType>,
) -> Vec<f64> {
server_types
.iter()
.map(|server_type| {
self.model(server_type)
.normalized_switching_cost(delta)
.raw()
})
.collect()
}
fn model(&self, server_type: &ServerType) -> &SwitchingCost {
&self.0[&server_type.key]
}
}