Skip to content

Commit

Permalink
feat: Adding method to extract constraints
Browse files Browse the repository at this point in the history
  • Loading branch information
dandxy89 committed Nov 11, 2023
1 parent 75e3fe0 commit d7b827d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 47 deletions.
8 changes: 6 additions & 2 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
use crate::Rule;
use pest::iterators::Pair;

pub trait IsNumeric {
pub trait Filterable {
fn is_numeric(&self) -> bool;
fn is_cmp(&self) -> bool;
}

impl IsNumeric for Rule {
impl Filterable for Rule {
fn is_numeric(&self) -> bool {
matches!(self, Self::FLOAT | Self::PLUS | Self::MINUS | Self::POS_INFINITY | Self::NEG_INFINITY)
}
fn is_cmp(&self) -> bool {
matches!(self, Self::GT | Self::LT | Self::EQ | Self::GTE | Self::LTE | Self::CMP)
}
}

pub trait AsFloat {
Expand Down
15 changes: 7 additions & 8 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ use std::collections::HashMap;
use pest::iterators::Pairs;

use crate::{
common::{AsFloat, IsNumeric},
common::{AsFloat, Filterable},
Rule,
};

#[derive(Debug, Default)]
pub enum VariableType {
#[default]
Unbounded,
Bounded(f64, f64),
Free,
Bounded(f64, f64),
Integer,
Binary,
}
Expand All @@ -25,7 +24,7 @@ pub struct Objective {

#[derive(Debug)]
pub struct Coefficient {
pub name: String,
pub var_name: String,
pub coefficient: f64,
}

Expand All @@ -34,19 +33,19 @@ impl TryFrom<Pairs<'_, Rule>> for Coefficient {

#[allow(clippy::unreachable, clippy::wildcard_enum_match_arm)]
fn try_from(values: Pairs<'_, Rule>) -> anyhow::Result<Self> {
let (mut value, mut name) = (1.0, String::new());
let (mut value, mut var_name) = (1.0, String::new());
for item in values {
match item.as_rule() {
r if r.is_numeric() => {
value *= item.as_float()?;
}
Rule::VARIABLE => {
name = item.as_str().to_string();
var_name = item.as_str().to_string();
}
_ => unreachable!(),
_ => unreachable!("Unexpected rule encountered"),
}
}
Ok(Self { name, coefficient: value })
Ok(Self { var_name, coefficient: value })
}
}

Expand Down
66 changes: 29 additions & 37 deletions src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::{
};

use crate::{
common::Filterable,
model::{Constraint, LPDefinition, Objective, Sense},
LParser, Rule,
};
Expand Down Expand Up @@ -32,46 +33,54 @@ pub fn parse_lp_file(contents: &str) -> anyhow::Result<LPDefinition> {
};
let mut parsed_contents = LPDefinition::default();
for pair in pair.clone().into_inner() {
parsed_contents = build(pair, parsed_contents)?;
parsed_contents = compose(pair, parsed_contents)?;
}

Ok(dbg!(parsed_contents))
Ok(parsed_contents)
}

#[allow(clippy::unwrap_used)]
fn build_objective(pair: Pair<'_, Rule>) -> anyhow::Result<Objective> {
let mut components = pair.into_inner();
let name = components.next().unwrap().as_str().to_string();
let coefficients: anyhow::Result<Vec<_>> = components.map(|p| p.into_inner().try_into()).collect();
fn compose_objective(pair: Pair<'_, Rule>) -> anyhow::Result<Objective> {
let mut parts = pair.into_inner();
let name = parts.next().unwrap().as_str().to_string();
let coefficients: anyhow::Result<Vec<_>> = parts.map(|p| p.into_inner().try_into()).collect();
Ok(Objective { name, coefficients: coefficients? })
}

fn build_constraint(_pair: Pair<'_, Rule>) -> anyhow::Result<Constraint> {
// pub name: String,
// pub coefficients: Vec<Coefficient>,
// pub sense: String,
// pub rhs: f64,
unimplemented!()
#[allow(clippy::unwrap_used)]
fn compose_constraint(pair: Pair<'_, Rule>) -> anyhow::Result<Constraint> {
let mut parts = pair.into_inner();
let name = parts.next().unwrap().as_str().to_string();
let mut coefficients: Vec<_> = vec![];
while let Some(p) = parts.peek() {
if p.as_rule().is_cmp() {
break;
}
coefficients.push(parts.next().unwrap());
}
let coefficients: anyhow::Result<Vec<_>> = coefficients.into_iter().map(|p| p.into_inner().try_into()).collect();
let sense = parts.next().unwrap().as_str().to_string();
let rhs = parts.next().unwrap().as_str().parse()?;
Ok(Constraint { name, coefficients: coefficients?, sense, rhs })
}

#[allow(clippy::wildcard_enum_match_arm)]
fn build(pair: Pair<'_, Rule>, mut parsed: LPDefinition) -> anyhow::Result<LPDefinition> {
fn compose(pair: Pair<'_, Rule>, mut parsed: LPDefinition) -> anyhow::Result<LPDefinition> {
match pair.as_rule() {
// Problem sense
Rule::MIN_SENSE => Ok(parsed.with_sense(Sense::Minimize)),
Rule::MAX_SENSE => Ok(parsed.with_sense(Sense::Maximize)),
// Problem Objectives
Rule::OBJECTIVES => {
let objectives: anyhow::Result<Vec<Objective>> = pair.into_inner().map(|inner_pair| build_objective(inner_pair)).collect();
let objectives: anyhow::Result<Vec<Objective>> = pair.into_inner().map(|inner_pair| compose_objective(inner_pair)).collect();
parsed.add_objective(objectives?);
Ok(parsed)
}
// Problem Constraints
// Rule::CONSTRAINTS => {
// let constraints: anyhow::Result<Vec<Constraint>> = pair.into_inner().map(|inner_pair| build_constraint(inner_pair)).collect();
// parsed.add_constraints(constraints?);
// Ok(parsed)
// }
Rule::CONSTRAINTS => {
let constraints: anyhow::Result<Vec<Constraint>> = pair.into_inner().map(|inner_pair| compose_constraint(inner_pair)).collect();
parsed.add_constraints(constraints?);
Ok(parsed)
}
// Problem Bounds
// Problem Integers
// Problem Generals
Expand All @@ -80,10 +89,6 @@ fn build(pair: Pair<'_, Rule>, mut parsed: LPDefinition) -> anyhow::Result<LPDef
}
}

// Rule::CONSTRAINT_EXPR => todo!(),
// Rule::CONSTRAINT_NAME => todo!(),
// Rule::CONSTRAINT => todo!(),
// Rule::CONSTRAINTS => todo!(),
// // Problem Bounds
// Rule::BOUND_PREFIX => todo!(),
// Rule::BOUND => todo!(),
Expand All @@ -99,12 +104,6 @@ fn build(pair: Pair<'_, Rule>, mut parsed: LPDefinition) -> anyhow::Result<LPDef
// Rule::BINARIES => todo!(),
// // Other
// Rule::WHITESPACE => todo!(),
// Rule::POS_INFINITY => todo!(),
// Rule::NEG_INFINITY => todo!(),
// Rule::FLOAT => todo!(),
// Rule::PLUS => todo!(),
// Rule::MINUS => todo!(),
// Rule::OPERATOR => todo!(),
// Rule::COLON => todo!(),
// Rule::ASTERIX => todo!(),
// Rule::FREE => todo!(),
Expand All @@ -115,10 +114,3 @@ fn build(pair: Pair<'_, Rule>, mut parsed: LPDefinition) -> anyhow::Result<LPDef
// Rule::VALID_CHARS => todo!(),
// Rule::CONSTRAINT_PREFIX => todo!(),
// Rule::VARIABLE => todo!(),
// Rule::GT => todo!(),
// Rule::GTE => todo!(),
// Rule::LT => todo!(),
// Rule::LTE => todo!(),
// Rule::EQ => todo!(),
// Rule::CMP => todo!(),
// Rule::EOF => todo!(),
1 change: 1 addition & 0 deletions tests/test_from_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ fn afiro() {
let result = read_file_from_resources("afiro.lp").unwrap();
assert_eq!(result.problem_sense, Sense::Minimize);
assert_eq!(result.objectives.len(), 3);
assert_eq!(result.constraints.len(), 27);
}

#[test]
Expand Down

0 comments on commit d7b827d

Please sign in to comment.