Min and max in builder

This commit is contained in:
Guillaume Pinot
2021-09-09 16:56:27 +02:00
committed by Guillaume P
parent 04196f41d3
commit 8c5a66a03f
2 changed files with 68 additions and 7 deletions
+36 -7
View File
@@ -92,7 +92,7 @@ impl CpModelBuilder {
self.add_eq_by_ref(&lhs.into(), &rhs.into()) self.add_eq_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_eq_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_eq_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([val, val]); cst.domain.extend([val, val]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
@@ -104,7 +104,7 @@ impl CpModelBuilder {
self.add_ge_by_ref(&lhs.into(), &rhs.into()) self.add_ge_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_ge_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_ge_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([val, i64::MAX]); cst.domain.extend([val, i64::MAX]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
@@ -116,7 +116,7 @@ impl CpModelBuilder {
self.add_le_by_ref(&lhs.into(), &rhs.into()) self.add_le_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_le_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_le_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([i64::MIN, val]); cst.domain.extend([i64::MIN, val]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
@@ -128,7 +128,7 @@ impl CpModelBuilder {
self.add_gt_by_ref(&lhs.into(), &rhs.into()) self.add_gt_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_gt_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_gt_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([val + 1, i64::MAX]); cst.domain.extend([val + 1, i64::MAX]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
@@ -140,7 +140,7 @@ impl CpModelBuilder {
self.add_lt_by_ref(&lhs.into(), &rhs.into()) self.add_lt_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_lt_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_lt_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([i64::MIN, val - 1]); cst.domain.extend([i64::MIN, val - 1]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
@@ -152,10 +152,30 @@ impl CpModelBuilder {
self.add_ne_by_ref(&lhs.into(), &rhs.into()) self.add_ne_by_ref(&lhs.into(), &rhs.into())
} }
pub fn add_ne_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint { pub fn add_ne_by_ref(&mut self, lhs: &LinearExpr, rhs: &LinearExpr) -> Constraint {
let (mut cst, val) = create_linear_proto(lhs, rhs); let (mut cst, val) = create_linear_cst_proto(lhs, rhs);
cst.domain.extend([i64::MIN, val - 1, val + 1, i64::MAX]); cst.domain.extend([i64::MIN, val - 1, val + 1, i64::MAX]);
self.add_cst(CstEnum::Linear(cst)) self.add_cst(CstEnum::Linear(cst))
} }
pub fn add_min_eq(
&mut self,
target: impl Into<LinearExpr>,
exprs: impl IntoIterator<Item = impl Into<LinearExpr>>,
) -> Constraint {
self.add_cst(CstEnum::LinMin(proto::LinearArgumentProto {
target: Some(target.into().into()),
exprs: exprs.into_iter().map(|e| e.into().into()).collect(),
}))
}
pub fn add_max_eq(
&mut self,
target: impl Into<LinearExpr>,
exprs: impl IntoIterator<Item = impl Into<LinearExpr>>,
) -> Constraint {
self.add_cst(CstEnum::LinMax(proto::LinearArgumentProto {
target: Some(target.into().into()),
exprs: exprs.into_iter().map(|e| e.into().into()).collect(),
}))
}
fn add_cst(&mut self, cst: CstEnum) -> Constraint { fn add_cst(&mut self, cst: CstEnum) -> Constraint {
let index = self.proto.constraints.len(); let index = self.proto.constraints.len();
self.proto.constraints.push(proto::ConstraintProto { self.proto.constraints.push(proto::ConstraintProto {
@@ -338,8 +358,17 @@ where
self self
} }
} }
impl From<LinearExpr> for proto::LinearExpressionProto {
fn from(expr: LinearExpr) -> Self {
proto::LinearExpressionProto {
vars: expr.vars,
coeffs: expr.coeffs,
offset: expr.constant,
}
}
}
fn create_linear_proto( fn create_linear_cst_proto(
left: &LinearExpr, left: &LinearExpr,
right: &LinearExpr, right: &LinearExpr,
) -> (proto::LinearConstraintProto, i64) { ) -> (proto::LinearConstraintProto, i64) {
+32
View File
@@ -0,0 +1,32 @@
use cp_sat::builder::CpModelBuilder;
use cp_sat::proto::CpSolverStatus;
#[test]
fn min() {
let mut model = CpModelBuilder::default();
let x = model.new_int_var([(0, 10)]);
let y = model.new_int_var([(5, 15)]);
let m = model.new_int_var([(-100, 100)]);
model.add_min_eq(m, [x, y]);
model.maximize(m);
println!("{:#?}", model.proto());
let response = model.solve();
assert_eq!(response.status(), CpSolverStatus::Optimal);
assert_eq!(10., response.objective_value);
}
#[test]
fn max() {
let mut model = CpModelBuilder::default();
let x = model.new_int_var([(0, 10)]);
let y = model.new_int_var([(5, 15)]);
let m = model.new_int_var([(-100, 100)]);
model.add_max_eq(m, [x, y]);
model.minimize(m);
println!("{:#?}", model.proto());
let response = model.solve();
assert_eq!(response.status(), CpSolverStatus::Optimal);
assert_eq!(5., response.objective_value);
}