| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsForServiceLevel ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun | 
| ) const | 
| { | 
|   Description: 'Initialize constraints forservice level' | 
|   TextBody: | 
|   [* | 
|     eis := this.MacroPlan().OptimizerMetaEIS();   | 
|     if ( ( runcontext.IsMetaIteration()  | 
|          and ( eis.ServiceLevelWeight() > 0 or eis.FulfillmentTargetWeight() > 0  ) )  | 
|          or not runcontext.IsMetaIteration()  | 
|          or this.IsFullPlanMetaPriorFocus() ) // for performance don't define if we don't have the kpi's in the strategy | 
|     { | 
|       constfromtargetname := typeof( MPServiceLevelFromTargetConstraint ); | 
|       constfromsddetname := typeof( MPFulfillmentTargetFromSDQtyConstraint ); | 
|       constfromsdstoname := typeof( MPServiceLevelFromSDQtyConstraint ); | 
|        | 
|       scalefactor_servicelevelqty_constfromtarget := this.ScaleConstraintTerm( typeof( MPFulfillmentTargetVariable ), constfromtargetname ); | 
|       scalefactor_servicelevelqty_constfromsd_det := this.ScaleConstraintTerm( typeof( MPFulfillmentTargetVariable ), constfromsddetname ); | 
|       scalefactor_servicelevelqty_constfromsd_sto := this.ScaleConstraintTerm( typeof( MPServiceLevelQtyVariable ), constfromsdstoname ); | 
|       scalefactor_salesdemandqty_constfromsd_det := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), constfromsddetname ); | 
|       scalefactor_salesdemandqty_constfromsd_sto := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), constfromsdstoname ); | 
|        | 
|       scalefactor_rhs_constfromtarget := this.ScaleConstraintRHS( constfromtargetname, 1.0 ); | 
|       scalefactor_rhs_constfromsddet := this.ScaleConstraintRHS( constfromsddetname, 1.0 );  | 
|       scalefactor_rhs_constfromsdsto := this.ScaleConstraintRHS( constfromsdstoname, 1.0 );  | 
|        | 
|       // | 
|       // step 1: created constraints | 
|       // | 
|       slbases := selectset(  this,  | 
|                              MacroPlan.AllServiceLevelBase,  | 
|                              sl,  | 
|                              sl.GetIsInOptimizerRun( scope ) );  | 
|       traverse( slbases, Elements, sl ) | 
|       { | 
|         vardummy := program.NewVariable( 'OptimizerConstantTerm', sl ); // workaround for const - cant use attribute | 
|         vardummy.Enabled( false );   | 
|         this.StoreValueInVariable( vardummy, 0.0 );  | 
|      | 
|         // If this is a fulfillment goal related service level then add the related constraints | 
|         if( sl.IsUsedForPlanningFulfillmentSystem() ) | 
|         { | 
|           // two constraints are added:  | 
|           // | 
|           // constfromtarget, which specifies the fulfilled quantity(sl) is <= target% * total demand qty (sl)              (*) | 
|           // | 
|           // constfromsd, which specifies fulfilled quantity (sl) <= total demand qty ( sl) | 
|        | 
|           // constraints to calculate fulfilled part of the fulfillmentgoal | 
|           // plannedservicelevel <= target% * sum of sd.Quantity | 
|           // const constraint UoM: Default | 
|           constfromtarget := program.ServiceLevelFromTargetConstraints().New( sl );  | 
|           constfromtarget.Sense( '<=' ); | 
|        | 
|           // Term UoM: Default | 
|           constfromtarget.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromtarget, program.FulfillmentTargetVariables().Get( sl ) ); | 
|        | 
|           // ServiceLevel <= sum of SalesDemandQty | 
|           // const constraint UoM: Default | 
|           constfromsd := program.FulfillmentTargetFromSDQtyConstraints().New( sl ); | 
|           constfromsd.Sense( '<=' ); | 
|           constfromsd.RHSValue( 0.0 ); | 
|            | 
|           // Term UoM: Default | 
|           constfromsd.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromsd_det, program.FulfillmentTargetVariables().Get( sl ) ); | 
|           constfromsd.Enabled( false ); // enable once we add a term | 
|         } | 
|         // Else, if this is a inventory optimization related service level, add the related constraints | 
|         else if( sl.IsUsedForSafetyStockCalculation() ) | 
|         { | 
|           // ServiceLevel <= SUM( SalesDemandQty ) + SUM ( DisaggregatedSalesDemandQty ) | 
|           // const constraint UoM: Default | 
|           constr := program.ServiceLevelFromSDQtyConstraints().New( sl ); | 
|           constr.Sense( '<=' ); | 
|           constr.RHSValue( 0.0 ); | 
|            | 
|           // Term UoM: Default | 
|           constr.NewTerm( 1.0 * scalefactor_servicelevelqty_constfromsd_sto , program.ServiceLevelQtyVariables().Get( sl ) ); | 
|           constr.Enabled( false ); // enable once we add a term | 
|         } | 
|       } | 
|        | 
|       //  | 
|       // step 2: add terms to constraint | 
|       // | 
|       //bsdips := selectset(  this, MacroPlan.SalesDemand.AsMasterSalesDemand, bsdip, true, true );  | 
|       bsdips := selectset(  leafpispipsinrun,  | 
|                             Elements.PlanningBaseSalesDemandInPeriodForOptimization, | 
|                             bsdip,  | 
|                             true,  | 
|                             not bsdip.MasterSalesDemand().IsExcludedFromFulfillmentKPI() );   | 
|       this.AddTermsToServiceLevelConstraints( program, | 
|                                               bsdips, | 
|                                               scalefactor_salesdemandqty_constfromsd_det, | 
|                                               scalefactor_salesdemandqty_constfromsd_sto, | 
|                                               scope ); | 
|       // step 3: set computed rhs for constraint | 
|       traverse( slbases, Elements, sl )  | 
|       { | 
|         opt_constant_term := program.Variable( 'OptimizerConstantTerm', sl ).UpperBound(); // workaround because cannot write to attribute  | 
|         outofscopequantity := sl.TotalFulfilledQuantity() - opt_constant_term; // latter term set in AddTermsToServiceLevelConstraint | 
|         if( sl.IsUsedForPlanningFulfillmentSystem() ) | 
|         { | 
|           constfromtarget := program.ServiceLevelFromTargetConstraints().Get( sl );  | 
|           desiredservicelevelpercentage := sl.TargetPercentage(); | 
|           rhsfromtarget := maxvalue( 0.0, sl.TotalDemandQuantity() * ( desiredservicelevelpercentage / 100.0 ) );   //prevent negative goal | 
|           // RHS UoM: Default | 
|           constfromtarget.RHSValue( rhsfromtarget * scalefactor_rhs_constfromtarget ); // poses the upper bound mentioned in (*)  | 
|            | 
|           constrfromsd := program.FulfillmentTargetFromSDQtyConstraints().Get( sl );  | 
|      | 
|           newrhs := this.GetConstraintRHS( constrfromsd, scalefactor_rhs_constfromsddet ) + outofscopequantity; // variable is added on the right, so we *add* constantterm to the RHS | 
|           constrfromsd.RHSValue( newrhs * scalefactor_rhs_constfromsddet ); | 
|         } | 
|         else | 
|         { | 
|           constr := program.ServiceLevelFromSDQtyConstraints().Get( sl );  | 
|           newrhs := this.GetConstraintRHS( constr, scalefactor_rhs_constfromsdsto ) + outofscopequantity; // variable is added on the right, so we *add* constantterm to the RHS | 
|           constr.RHSValue( newrhs * scalefactor_rhs_constfromsdsto ); | 
|         } | 
|       } | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |