use color_eyre::{eyre::eyre, Result};
use fast_float2::FastFloat;
#[cfg(feature = "serde")]
use serde::Serialize;
cfg_if::cfg_if! {
if #[cfg(feature = "trace")] {
use nom_locate::LocatedSpan;
use nom_tracable::TracableInfo;
pub type Span<'a> = LocatedSpan<&'a str, TracableInfo>;
} else {
pub type Span<'a> = &'a str;
}
}
#[derive(Debug, Default, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct Parser<'a, T: FastFloat> {
pub name: &'a str,
pub objective_sense: Option<ObjectiveSense>,
pub objective_name: Option<&'a str>,
pub reference_row: Option<&'a str>,
pub rows: Rows<'a>,
pub columns: Columns<'a, T>,
pub rhs: Option<Rhs<'a, T>>,
pub ranges: Option<Ranges<'a, T>>,
pub bounds: Option<Bounds<'a, T>>,
pub user_cuts: Option<UserCuts<'a>>,
pub special_ordered_sets: Option<SpecialOrderedSets<'a, T>>,
pub quadratic_objective: Option<QuadraticObjective<'a, T>>,
pub quadratic_constraints: Option<QuadraticConstraints<'a, T>>,
pub indicators: Option<Indicators<'a>>,
pub lazy_constraints: Option<LazyConstraints<'a>>,
pub cone_constraints: Option<ConeConstraints<'a, T>>,
pub branch_priorities: Option<BranchPriorities<'a>>,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RowLine<'a> {
pub row_type: RowType,
pub row_name: &'a str,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum RowType {
#[default]
Eq,
Leq,
Geq,
Nr,
}
impl TryFrom<char> for RowType {
type Error = color_eyre::Report;
fn try_from(c: char) -> Result<Self> {
match c {
'E' => Ok(RowType::Eq),
'L' => Ok(RowType::Leq),
'G' => Ok(RowType::Geq),
'N' => Ok(RowType::Nr),
_ => Err(eyre!("invalid row type")),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum ObjectiveSense {
Min,
Max,
}
pub type Rows<'a> = Vec<RowLine<'a>>;
pub type Columns<'a, T> = Vec<WideLine<'a, T>>;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct RowValuePair<'a, T> {
pub row_name: &'a str,
pub value: T,
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct WideLine<'a, T> {
pub name: &'a str,
pub first_pair: RowValuePair<'a, T>,
pub second_pair: Option<RowValuePair<'a, T>>,
}
pub type Rhs<'a, T> = Vec<WideLine<'a, T>>;
pub type Ranges<'a, T> = Vec<WideLine<'a, T>>;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct BoundsLine<'a, T> {
pub bound_type: BoundType,
pub bound_name: &'a str,
pub column_name: &'a str,
pub value: Option<T>,
}
pub type Bounds<'a, T> = Vec<BoundsLine<'a, T>>;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum BoundType {
#[default]
Lo, Up, Fx, Fr, Mi, Pl, Bv, Li, Ui, Sc, }
impl TryFrom<&str> for BoundType {
type Error = color_eyre::Report;
fn try_from(s: &str) -> Result<Self> {
match s {
"LO" => Ok(BoundType::Lo),
"UP" => Ok(BoundType::Up),
"FX" => Ok(BoundType::Fx),
"FR" => Ok(BoundType::Fr),
"MI" => Ok(BoundType::Mi),
"PL" => Ok(BoundType::Pl),
"BV" => Ok(BoundType::Bv),
"LI" => Ok(BoundType::Li),
"UI" => Ok(BoundType::Ui),
"SC" => Ok(BoundType::Sc),
_ => Err(eyre!("invalid bound type")),
}
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum RangeType {
#[default]
_Le, _Ge, _Ep, _Em, _Ez, }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct IndicatorLine<'a> {
pub binary_var: &'a str,
pub trigger_value: u8,
pub constraint_name: &'a str,
}
pub type Indicators<'a> = Vec<IndicatorLine<'a>>;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct LazyConstraintLine<'a> {
pub priority: Option<i32>,
pub row_name: &'a str,
}
pub type LazyConstraints<'a> = Vec<LazyConstraintLine<'a>>;
pub type UserCuts<'a> = Vec<RowLine<'a>>;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct QuadraticObjectiveTerm<'a, T: FastFloat> {
pub var1: &'a str,
pub var2: &'a str,
pub coefficient: T,
}
pub type QuadraticObjective<'a, T> = Vec<QuadraticObjectiveTerm<'a, T>>;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum SOSType {
S1,
S2,
}
impl TryFrom<&str> for SOSType {
type Error = color_eyre::Report;
fn try_from(s: &str) -> Result<Self> {
match s {
"S1" => Ok(SOSType::S1),
"S2" => Ok(SOSType::S2),
_ => Err(eyre!("invalid SOS type: {}", s)),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct SOSLine<'a, T: FastFloat> {
pub sos_type: SOSType,
pub set_name: &'a str,
pub members: Vec<SOSMember<'a, T>>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct SOSMember<'a, T: FastFloat> {
pub var_name: &'a str,
pub weight: T,
}
pub type SpecialOrderedSets<'a, T> = Vec<SOSLine<'a, T>>;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct QuadraticConstraint<'a, T: FastFloat> {
pub row_name: &'a str,
pub terms: Vec<QuadraticTerm<'a, T>>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct QuadraticTerm<'a, T: FastFloat> {
pub var1: &'a str,
pub var2: &'a str,
pub coefficient: T,
}
pub type QuadraticConstraints<'a, T> = Vec<QuadraticConstraint<'a, T>>;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum ConeType {
Quad,
RQuad,
}
impl TryFrom<&str> for ConeType {
type Error = color_eyre::Report;
fn try_from(s: &str) -> Result<Self> {
match s {
"QUAD" => Ok(ConeType::Quad),
"RQUAD" => Ok(ConeType::RQuad),
_ => Err(eyre!("invalid cone type: {}", s)),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ConeConstraint<'a, T: FastFloat> {
pub cone_name: &'a str,
pub cone_type: ConeType,
pub members: Vec<ConeMember<'a, T>>,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct ConeMember<'a, T: FastFloat> {
pub var_name: &'a str,
pub coefficient: Option<T>,
}
pub type ConeConstraints<'a, T> = Vec<ConeConstraint<'a, T>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub enum BranchDirection {
Up,
Down,
Rounding,
ClosestBound,
Auto,
}
impl TryFrom<&str> for BranchDirection {
type Error = color_eyre::Report;
fn try_from(s: &str) -> Result<Self> {
match s {
"UP" => Ok(BranchDirection::Up),
"DN" => Ok(BranchDirection::Down),
"RD" => Ok(BranchDirection::Rounding),
"CB" => Ok(BranchDirection::ClosestBound),
"" => Ok(BranchDirection::Auto),
_ => Err(eyre!("invalid branch direction: {}", s)),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
pub struct BranchPriority<'a> {
pub var_name: &'a str,
pub priority: i32,
pub direction: BranchDirection,
}
pub type BranchPriorities<'a> = Vec<BranchPriority<'a>>;