From 1bf18fe8e10a495d845acf1d6da468a20987ad1e Mon Sep 17 00:00:00 2001 From: Jeremy Saklad Date: Tue, 28 Sep 2021 17:05:06 -0500 Subject: [PATCH] Add BoneMarketModel.AddDivisionMultiplicationEquality This method combines two common operations, avoiding the need for intermediate variables at the call site. --- bonemarketsolver/objects/bone_market_model.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/bonemarketsolver/objects/bone_market_model.py b/bonemarketsolver/objects/bone_market_model.py index ff62701..a39a0b5 100644 --- a/bonemarketsolver/objects/bone_market_model.py +++ b/bonemarketsolver/objects/bone_market_model.py @@ -33,6 +33,24 @@ Each parameter is interpreted as a BoundedLinearExpression, and a layer of indir super().AddDivisionEquality(intermediate_target, intermediate_num, intermediate_denom) return (target_constraint, num_constraint, denom_constraint) + def AddDivisionMultiplicationEquality(self, target, num, denom, multiple = None): + """Adds `target == (num // denom) * multiple`. + +Each parameter is interpreted as a BoundedLinearExpression, and a layer of indirection is applied such that each Constraint in the returned tuple can accept an enforcement literal. + +`multiple` defaults to the same value as `denom` if unspecified.""" + quotient = self.NewIntVar(f'{repr(target)} == ({repr(num)} // {repr(denom)}) * {repr(multiple)}: quotient') + intermediate_num, num_constraint = self.NewIntermediateIntVar(num, f'{repr(target)} == ({repr(num)} // {repr(denom)}) * {repr(multiple)}: num', lb = 0) + intermediate_denom, denom_constraint = self.NewIntermediateIntVar(denom, f'{repr(target)} == ({repr(num)} // {repr(denom)}) * {repr(multiple)}: denom', lb = 0) + intermediate_target, target_constraint = self.NewIntermediateIntVar(target, f'{repr(target)} == ({repr(num)} // {repr(denom)}) * {repr(multiple)}: target') + if multiple: + intermediate_multiple, multiple_constraint = self.NewIntermediateIntVar(multiple, f'{repr(target)} == ({repr(num)} // {repr(denom)}) * {repr(multiple)}: multiple') + + super().AddDivisionEquality(quotient, intermediate_num, intermediate_denom) + super().AddMultiplicationEquality(intermediate_target, (quotient, intermediate_multiple if multiple else intermediate_denom)) + + return (num_constraint, denom_constraint, target_constraint, *((multiple_constraint,) if multiple else ())) + def AddIf(self, variable, *constraints): """Add constraints to the model, only enforced if the specified variable is true.