use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
use super::terms::TermDto;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OptimizationDirection {
Maximize,
Minimize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConstraintOperator {
Le,
Ge,
Eq,
}
impl ConstraintOperator {
pub fn as_str(&self) -> &'static str {
match self {
Self::Le => "<=",
Self::Ge => ">=",
Self::Eq => "=",
}
}
}
impl Serialize for ConstraintOperator {
fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.serialize_str(self.as_str())
}
}
impl<'de> Deserialize<'de> for ConstraintOperator {
fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let s = String::deserialize(d)?;
match s.as_str() {
"<=" => Ok(Self::Le),
">=" => Ok(Self::Ge),
"=" => Ok(Self::Eq),
other => Err(serde::de::Error::custom(format!(
"unexpected constraint operator: {other}"
))),
}
}
}
pub type LinearExpression = BTreeMap<String, f64>;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct VariableBounds {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub min: Option<f64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LinearConstraint {
pub coefficients: LinearExpression,
pub op: ConstraintOperator,
pub rhs: f64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ObjectiveFunction {
pub direction: OptimizationDirection,
pub coefficients: LinearExpression,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LinearProgramDefinition {
pub objective: ObjectiveFunction,
#[serde(default)]
pub constraints: Vec<LinearConstraint>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub bounds: BTreeMap<String, VariableBounds>,
}
#[derive(Debug, Clone, Default)]
pub struct SolveOptions {
pub timeout_ms: Option<u64>,
pub max_depth: Option<u32>,
pub cleanup: Option<bool>,
}
#[derive(Debug, Clone)]
pub enum OptimizationResult {
Optimal {
variables: BTreeMap<String, f64>,
objective_value: f64,
solve_time_ms: u64,
},
Infeasible {
solve_time_ms: u64,
},
}
#[derive(Debug, Clone)]
pub struct KBVariableSpec {
pub sort: String,
pub name_feature: String,
}
#[derive(Debug, Clone)]
pub struct KBObjectiveSpec {
pub direction: OptimizationDirection,
pub coefficient_feature: String,
}
#[derive(Debug, Clone)]
pub struct KBResourceConstraint {
pub cost_feature: String,
pub op: Option<ConstraintOperator>,
pub capacity: f64,
pub label: Option<String>,
}
#[derive(Debug, Clone)]
pub struct KBOptimizationConfig {
pub variables: KBVariableSpec,
pub objective: KBObjectiveSpec,
pub resource_constraints: Vec<KBResourceConstraint>,
pub non_negative: bool,
pub additional_constraints: Vec<LinearConstraint>,
}
#[derive(Debug, Clone)]
pub struct KBOptimizationResult {
pub result: OptimizationResult,
pub generated_problem: LinearProgramDefinition,
pub discovered_terms: Vec<TermDto>,
}