Skip to content

Commit

Permalink
Use linear regression when quadratic
Browse files Browse the repository at this point in the history
  • Loading branch information
bvrooman committed Nov 20, 2023
1 parent 12c044d commit be4d09c
Showing 1 changed file with 67 additions and 32 deletions.
99 changes: 67 additions & 32 deletions benches/src/collect/costs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::{
estimate_model,
regression::linear_regression,
LinearCoefficients,
Model,
};
use serde::{
Expand Down Expand Up @@ -35,7 +37,6 @@ pub fn dependent_cost(
points: Vec<(f64, f64)>,
) -> anyhow::Result<DependentCost> {
let model = estimate_model(&points)?;

let cost = match model {
Model::Zero => {
// Zero
Expand Down Expand Up @@ -63,34 +64,13 @@ pub fn dependent_cost(
}
}
Model::Linear(coefficients) => {
match coefficients.slope {
slope if slope > 0.0 && slope < 1.0 => {
// Slope is between (0.0, 1.0)
// Light operation
let base = coefficients.intercept;
let base = base.max(0.0);
let base = base.round() as u64;
let inverse_slope = 1.0 / slope;
let units_per_gas = inverse_slope.round() as u64;
DependentCost::LightOperation {
base,
units_per_gas,
}
}
slope if slope >= 1.0 => {
// Slope is greater than 1.0
// Heavy operation
let base = coefficients.intercept;
let base = base.max(0.0);
let base = base.round() as u64;
let gas_per_unit = slope.round() as u64;
DependentCost::HeavyOperation { base, gas_per_unit }
}
_ => {
// Slope is negative
let cost = coefficients.try_into();
match cost {
Ok(cost) => cost,
Err(DependentCostError::NegativeSlope(slope)) => {
let warning = format!("Warning: \
Evaluating the regression on the dataset for `{name}` produced a negative slope. \
This implies a negative cost behavior and is not supported in a dependent context.", name = name);
Evaluating the regression on the dataset for `{name}` produced a negative slope: {slope}. \
This implies a negative cost behavior and is not supported in a dependent context.", slope = slope, name = name);
eprintln!("{}", warning);
let base = coefficients.intercept;
let base = base.round() as u64;
Expand All @@ -105,11 +85,24 @@ pub fn dependent_cost(
// Quadratic
let warning = format!("Warning: \
Evaluating the regression on the dataset for `{name}` produced a quadratic function({:?}). \
Quadratic behavior is not supported in a dependent context. Points: {points:?}", coefficients, name = name, points = points);
Quadratic behavior is not supported in a dependent context. Points: {points:?}. Defaulting to linear model", coefficients, name = name, points = points);
eprintln!("{}", warning);
DependentCost::HeavyOperation {
base: 0,
gas_per_unit: 0,
let coefficients = linear_regression(&points);
let cost = coefficients.try_into();
match cost {
Ok(cost) => cost,
Err(DependentCostError::NegativeSlope(slope)) => {
let warning = format!("Warning: \
Evaluating the regression on the dataset for `{name}` produced a negative slope: {slope}. \
This implies a negative cost behavior and is not supported in a dependent context.", slope = slope, name = name);
eprintln!("{}", warning);
let base = coefficients.intercept;
let base = base.round() as u64;
DependentCost::HeavyOperation {
base,
gas_per_unit: 0,
}
}
}
}
Model::Other => {
Expand All @@ -127,3 +120,45 @@ pub fn dependent_cost(
};
Ok(cost)
}

#[derive(Debug)]
pub enum DependentCostError {
NegativeSlope(f64),
}

impl TryFrom<LinearCoefficients> for DependentCost {
type Error = DependentCostError;

fn try_from(coefficients: LinearCoefficients) -> Result<Self, Self::Error> {
match coefficients.slope {
slope if slope > 0.0 && slope < 1.0 => {
// Slope is between (0.0, 1.0)
// Light operation
let base = coefficients.intercept;
let base = base.max(0.0);
let base = base.round() as u64;
let inverse_slope = 1.0 / slope;
let units_per_gas = inverse_slope.round() as u64;
let cost = DependentCost::LightOperation {
base,
units_per_gas,
};
Ok(cost)
}
slope if slope >= 1.0 => {
// Slope is greater than 1.0
// Heavy operation
let base = coefficients.intercept;
let base = base.max(0.0);
let base = base.round() as u64;
let gas_per_unit = slope.round() as u64;
let cost = DependentCost::HeavyOperation { base, gas_per_unit };
Ok(cost)
}
slope => {
// Slope is negative
Err(DependentCostError::NegativeSlope(slope))
}
}
}
}

0 comments on commit be4d09c

Please sign in to comment.