fn process_bound<FI, FO: From<FI> + Ord + Zero + One + Clone>(
    bound_type: BoundType<FI>,
    variable: &mut ShiftedVariable<FO>,
) -> Result<(bool, bool), Inconsistency> {
    match bound_type {
        BoundType::LowerContinuous(value) => {
            replace_existing_with(&mut variable.lower_bound, value.into(), Ordering::Greater);
            Ok((false, false))
        },
        BoundType::UpperContinuous(value) => {
            // The implied zero lower bound gets filled in only if no other lower bound is present.
            // This behavior is copied from GLPK.
            replace_existing_with(&mut variable.upper_bound, value.into(), Ordering::Less);
            Ok((true, false))
        },
        BoundType::Fixed(value) => {
            let converted: FO = value.into();
            replace_existing_with(&mut variable.lower_bound, converted.clone(), Ordering::Greater);
            replace_existing_with(&mut variable.upper_bound, converted, Ordering::Less);
            Ok((false, false))
        }
        BoundType::Free => {
            // This check is not enough, because these bounds might be set later. The caller checks
            // as well after.
            if variable.lower_bound.is_some() || variable.upper_bound.is_some() {
                return Err(Inconsistency::new("Variable can't be bounded and free"))
            }
            Ok((false, true))
        },
        // Infinity bounds only say which sign a variable should have; the implied zero bound is
        // taken as an explicit one (it doesn't matter if another bound is present as well).
        BoundType::LowerMinusInfinity => {
            // Lower bound minus infinity is implied by variable.lower_bound.is_none()
            replace_existing_with(&mut variable.upper_bound, FO::zero(), Ordering::Less);
            Ok((false, false))
        },
        BoundType::UpperInfinity => {
            replace_existing_with(&mut variable.lower_bound, FO::zero(), Ordering::Greater);
            // Upper bound infinity is implied by variable.upper_bound.is_none()
            Ok((false, false))
        },
        BoundType::Binary => {
            replace_existing_with(&mut variable.lower_bound, FO::zero(), Ordering::Greater);
            replace_existing_with(&mut variable.upper_bound, FO::one(), Ordering::Less);
            variable.variable_type = VariableType::Integer;
            Ok((false, false))
        }
        BoundType::LowerInteger(value) => {
            replace_existing_with(&mut variable.lower_bound, value.into(), Ordering::Greater);
            variable.variable_type = VariableType::Integer;
            Ok((false, false))
        },
        BoundType::UpperInteger(value) => {
            replace_existing_with(&mut variable.upper_bound, value.into(), Ordering::Less);
            variable.variable_type = VariableType::Integer;
            Ok((true, false))
        },
        BoundType::SemiContinuous(_, _) => unimplemented!(),
    }
}
/// Update the variable with this bound.
///
/// Variables start out completely unconstrained and repeated calling of this method constrains them
/// increasingly.
///
/// # Arguments
///
/// * `bound_type`: One of 8 or so bound types that the MPS describes.
/// * `variable`: Variable to which this bound will be applied.
///
/// # Return value
///
/// Whether the variable is free, and whether the bound still needs a default zero lower bound.
///
/// # Errors
///
/// Inconsistency error if this variable is no longer be feasible after adding the bound.
/// TODO(CORRECTNESS): Consider changing this into an "this LP is infeasible" return type
Update the variable with this bound.
Variables start out completely unconstrained and repeated calling of this method constrains them
increasingly.
Update the variable with this bound . Variables start out completely unconstrained and repeated calling of this method constrains them increasingly .
fn process_bound<FI, FO: From<FI> + Ord + Zero + One + Clone>(
    bound_type: BoundType<FI>,
    variable: &mut ShiftedVariable<FO>,
) -> Result<(bool, bool), Inconsistency> {
    match bound_type {
        BoundType::LowerContinuous(value) => {
            replace_existing_with(&mut variable.lower_bound, value.into(), Ordering::Greater);
            Ok((false, false))
        },
        BoundType::UpperContinuous(value) => {
            // The implied zero lower bound gets filled in only if no other lower bound is present.
            // This behavior is copied from GLPK.
            replace_existing_with(&mut variable.upper_bound, value.into(), Ordering::Less);
            Ok((true, false))
        },
        BoundType::Fixed(value) => {
            let converted: FO = value.into();
            replace_existing_with(&mut variable.lower_bound, converted.clone(), Ordering::Greater);
            replace_existing_with(&mut variable.upper_bound, converted, Ordering::Less);
            Ok((false, false))
        }
        BoundType::Free => {
            // This check is not enough, because these bounds might be set later. The caller checks
            // as well after.
            if variable.lower_bound.is_some() || variable.upper_bound.is_some() {
                return Err(Inconsistency::new("Variable can't be bounded and free"))
            }
            Ok((false, true))
        },
        // Infinity bounds only say which sign a variable should have; the implied zero bound is
        // taken as an explicit one (it doesn't matter if another bound is present as well).
        BoundType::LowerMinusInfinity => {
            // Lower bound minus infinity is implied by variable.lower_bound.is_none()
            replace_existing_with(&mut variable.upper_bound, FO::zero(), Ordering::Less);
            Ok((false, false))
        },
        BoundType::UpperInfinity => {
            replace_existing_with(&mut variable.lower_bound, FO::zero(), Ordering::Greater);
            // Upper bound infinity is implied by variable.upper_bound.is_none()
            Ok((false, false))
        },
        BoundType::Binary => {
            replace_existing_with(&mut variable.lower_bound, FO::zero(), Ordering::Greater);
            replace_existing_with(&mut variable.upper_bound, FO::one(), Ordering::Less);
            variable.variable_type = VariableType::Integer;
            Ok((false, false))
        }
        BoundType::LowerInteger(value) => {
            replace_existing_with(&mut variable.lower_bound, value.into(), Ordering::Greater);
            variable.variable_type = VariableType::Integer;
            Ok((false, false))
        },
        BoundType::UpperInteger(value) => {
            replace_existing_with(&mut variable.upper_bound, value.into(), Ordering::Less);
            variable.variable_type = VariableType::Integer;
            Ok((true, false))
        },
        BoundType::SemiContinuous(_, _) => unimplemented!(),
    }
}
fn process_bound < FI , FO : From < FI > + Ord + Zero + One + Clone > ( bound_type : BoundType < FI > , variable : & mut ShiftedVariable < FO > , ) -> Result < ( bool , bool ) , Inconsistency > { match bound_type { BoundType :: LowerContinuous ( value ) => { replace_existing_with ( & mut variable . lower_bound , value . into ( ) , Ordering :: Greater ) ; Ok ( ( false , false ) ) } , BoundType :: UpperContinuous ( value ) => { // The implied zero lower bound gets filled in only if no other lower bound is present. // This behavior is copied from GLPK. replace_existing_with ( & mut variable . upper_bound , value . into ( ) , Ordering :: Less ) ; Ok ( ( true , false ) ) } , BoundType :: Fixed ( value ) => { let converted : FO = value . into ( ) ; replace_existing_with ( & mut variable . lower_bound , converted . clone ( ) , Ordering :: Greater ) ; replace_existing_with ( & mut variable . upper_bound , converted , Ordering :: Less ) ; Ok ( ( false , false ) ) } BoundType :: Free => { // This check is not enough, because these bounds might be set later. The caller checks // as well after. if variable . lower_bound . is_some ( ) || variable . upper_bound . is_some ( ) { return Err ( Inconsistency :: new ( " " ) ) } Ok ( ( false , true ) ) } , // Infinity bounds only say which sign a variable should have; the implied zero bound is // taken as an explicit one (it doesn't matter if another bound is present as well). BoundType :: LowerMinusInfinity => { // Lower bound minus infinity is implied by variable.lower_bound.is_none() replace_existing_with ( & mut variable . upper_bound , FO :: zero ( ) , Ordering :: Less ) ; Ok ( ( false , false ) ) } , BoundType :: UpperInfinity => { replace_existing_with ( & mut variable . lower_bound , FO :: zero ( ) , Ordering :: Greater ) ; // Upper bound infinity is implied by variable.upper_bound.is_none() Ok ( ( false , false ) ) } , BoundType :: Binary => { replace_existing_with ( & mut variable . lower_bound , FO :: zero ( ) , Ordering :: Greater ) ; replace_existing_with ( & mut variable . upper_bound , FO :: one ( ) , Ordering :: Less ) ; variable . variable_type = VariableType :: Integer ; Ok ( ( false , false ) ) } BoundType :: LowerInteger ( value ) => { replace_existing_with ( & mut variable . lower_bound , value . into ( ) , Ordering :: Greater ) ; variable . variable_type = VariableType :: Integer ; Ok ( ( false , false ) ) } , BoundType :: UpperInteger ( value ) => { replace_existing_with ( & mut variable . upper_bound , value . into ( ) , Ordering :: Less ) ; variable . variable_type = VariableType :: Integer ; Ok ( ( true , false ) ) } , BoundType :: SemiContinuous ( _ , _ ) => unimplemented ! ( ) , } }
Update the variable with this bound.
Update the variable with this bound .
bound_type
BoundType<FI>
variable
&mut ShiftedVariable<FO>
bound_type
BoundType<FI>
variable
&mut ShiftedVariable<FO>
return value
Whether the variable is free, and whether the bound still needs a default zero lower bound.
Whether the variable is free and whether the bound still needs a default zero lower bound .
errors
Inconsistency error if this variable is no longer be feasible after adding the bound.
TODO(CORRECTNESS): Consider changing this into an "this LP is infeasible" return type
Inconsistency error if this variable is no longer be feasible after adding the bound . TODO ( CORRECTNESS ) : Consider changing this into an " this LP is infeasible " return type