| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsGoalsForTotalSlacks ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun, | 
|   const constcontent ProductInStockingPoint_MPs pispsinrun | 
| ) const | 
| { | 
|   Description: 'The constraint to compute the total slacks used in the algorithm.' | 
|   TextBody: | 
|   [* | 
|     // calculate penalty of using slack | 
|     // slackconst constraint UoM: Default | 
|     slackconst := program.TotalSlackConstraints().New(); | 
|     slackconst.Sense( '=' ); | 
|     slackconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( slackconst ), 0.0 ) ); | 
|     // Term UoM: Default | 
|      | 
|     slackconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalSlackVariable ), typeofexpression( slackconst ) ), program.TotalSlackVariables().Get() ); | 
|      | 
|     // TotalSupplyUser slack | 
|     // Currently, a higher weight than the demandslack is used, which will always force the optimizer to fulfill the user defined total supply | 
|     // Term UoM: Default | 
|     slackconst.NewTerm( -2.0 * this.ScaleConstraintTerm( typeof( MPTotalSlackUserSupplyVariable ), typeofexpression( slackconst ) ) | 
|                         , program.TotalSlackUserSupplyVariables().Get() ); | 
|      | 
|     targetuom := this.MacroPlan().DefaultUnitOfMeasure(); | 
|            | 
|     scalefactor_demandslack_const := this.ScaleConstraintTerm( typeof( MPDemandSlackVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_invpriorspec_const := this.ScaleConstraintTerm( typeof( MPInvQtySpecPriorToHorizonSlackVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_spinvoutofscope_const := this.ScaleConstraintTerm( typeof( MPSPInvOutOfScopeSlackVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_liminv_const := this.ScaleConstraintTerm( typeof( MPMetaLimitMaxInventoryPastHorizonSlackVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_maturationslack_const := this.ScaleConstraintTerm( typeof( MPMaturationSlackVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_operationinputgroupover_const := this.ScaleConstraintTerm( typeof( MPOperationInputGroupOverVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_operationinputgroupunder_const := this.ScaleConstraintTerm( typeof( MPOperationInputGroupUnderVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_operationinputsetover_const := this.ScaleConstraintTerm( typeof( MPOperationInputSetOverVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_operationinputsetunder_const := this.ScaleConstraintTerm( typeof( MPOperationInputSetUnderVariable ), typeofexpression( slackconst ) ); | 
|     scalefactor_shiftdurationslack_constr := this.ScaleConstraintTerm( typeof( MPShiftPatternDurationSlackVariable ), typeofexpression( slackconst ) ); | 
|      | 
|      | 
|     if( runcontext.UseCampaignSequenceOptimizer() and runcontext.UseCampaign() ) | 
|     { | 
|       vartotalcombislack := program.TotalCampaignSequencingCombiSlackVariables().Get();  | 
|       slackconst.NewTerm( -1.0 * CapacityPlanningSuboptimizer::OptCampaignCombiSlackWeight(), vartotalcombislack );  // take absolute penalty of 1000 per combi sequence or coverage problem                                             | 
|      | 
|       scalefactor_overloadedvar_const := this.ScaleConstraintTerm( typeof( MPCampaignElementTypePeriodOverloadedStartVariable ), typeofexpression( slackconst ) );  | 
|        | 
|       traverse( scope.GetUnitPeriodInOptimizerRunConst(), Elements.OptCampaignUnitSubPeriod, ocusp ) | 
|       { | 
|         traverse( ocusp, OptCampaignCombiElement.OptCampaignElementType, ocet ) | 
|         { | 
|           varperiodoverloadstart := program.CampaignElementTypePeriodOverloadedStartVariables().Get( ocet, ocusp ); | 
|           varperiodoverloadmid := program.CampaignElementTypePeriodOverloadedMidVariables().Get( ocet, ocusp ); | 
|           varperiodoverloadend := program.CampaignElementTypePeriodOverloadedEndVariables().Get( ocet, ocusp ); | 
|            | 
|           slackconst.NewTerm(  -1.0 * scalefactor_overloadedvar_const, varperiodoverloadstart ); | 
|           slackconst.NewTerm(  -1.0 * scalefactor_overloadedvar_const, varperiodoverloadmid ); | 
|           slackconst.NewTerm(  -1.0 * scalefactor_overloadedvar_const, varperiodoverloadend ); | 
|         } | 
|       } | 
|     } | 
|      | 
|     // Penalty for using supply slack in balance constraint | 
|     traverse( leafpispipsinrun, Elements, pispip ) | 
|     { | 
|       uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor(); | 
|       // Term: -uomconversion  * DemandSlack variable | 
|       // UoM:  [PISP to Default] *        [PISP] | 
|       slackconst.NewTerm( -uomconversion * scalefactor_demandslack_const, | 
|                           program.DemandSlackVariables().Get( pispip ) ); | 
|      | 
|       if ( runcontext.IsMetaIteration() )  | 
|       {                                            | 
|         slackvar := program.MetaLimitMaxInventoryPastHorizonSlackVariables().Find( pispip ); | 
|         if ( not isnull( slackvar ) )  | 
|         { | 
|         slackconst.NewTerm( -uomconversion * scalefactor_liminv_const, slackvar );   | 
|         } | 
|       } | 
|     } | 
|      | 
|     leafpispips := null( ProductInStockingPointInPeriodPlannings, constcontent, owning ); | 
|     pispips := this.GetPISPIPsForInventorySpecifications( scope, false, &leafpispips ); | 
|     startoptscope := runcontext.FirstPeriod_MP().Start();  | 
|     traverse( pispips, Elements, pispip, pispip.Start() < startoptscope )  | 
|     { | 
|       var := program.InvQtySpecPriorToHorizonSlackVariables().Find( pispip );  | 
|       if ( not isnull( var ) ) | 
|       { | 
|         uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor(); | 
|         slackconst.NewTerm( -uomconversion * scalefactor_invpriorspec_const, var );  | 
|       } | 
|     } | 
|      | 
|     traverse( scope.GetStockingPointInPeriodInOptimizerRunConst(), Elements, spip,  | 
|               not spip.StockingPoint_MP().IsPlannedInfinite() ) | 
|     { | 
|       nextspip :=  spip.GetNextPlanningSPIP();  | 
|       if ( not runcontext.IsSmartPlan()  | 
|            and not isnull( nextspip )  | 
|            and not scope.Contains( nextspip.SPIPInOptimizerRun() ) )  | 
|       { | 
|         slackconst.NewTerm( -1.0 * scalefactor_spinvoutofscope_const, program.SPInvOutOfScopeSlackVariables().Get( spip ) ); | 
|       } | 
|     } | 
|      | 
|      | 
|     // Penalty for using maturation slack in maturation constraint | 
|     traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() )  | 
|     { | 
|       pispips := pisp.GetPISPIPForShelfLifeOptimizer( scope );  | 
|       traverse( pispips, Elements, pispip )  | 
|       { | 
|         uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor(); | 
|         traverse( pisp, OutgoingShelfLifeDay, oslday )  | 
|         { | 
|           slackconst.NewTerm( -uomconversion * scalefactor_maturationslack_const, program.MaturationSlackVariables().Get( pispip, oslday ) );  | 
|         } | 
|       } | 
|     } | 
|      | 
|     traverse( pispsinrun, Elements, pisp, pisp.IsOptShelfLife() )  | 
|     { | 
|       pispips := pisp.PISPInOptimizerRun().GetPISPIPForShelfLifeOptimizer( scope );  | 
|       traverse( pispips, Elements, pispip )  | 
|       { | 
|         uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor(); | 
|         traverse( pisp, IncomingShelfLifeDay, islday )  | 
|         { | 
|           splitdemandslackvar := program.DemandSlackShelfLifeVariables().Get( pispip, islday );  | 
|           slackconst.NewTerm( -uomconversion * scalefactor_demandslack_const, splitdemandslackvar );  | 
|         } | 
|       } | 
|     } | 
|      | 
|     // Penalty for violating the operation input group min/max | 
|     traverse( scope.GetOperationInputGroupInOptimizerRunConst(), Elements, group )  | 
|     { | 
|       operation := group.Operation(); | 
|      | 
|       periods := this.GetPeriodsForOperation( scope, operation ); | 
|      | 
|       traverse( periods, Elements, period ) | 
|       { | 
|         sourceuom := guard( operation.Unit().UnitOfMeasure_MP(), this.MacroPlan().DefaultUnitOfMeasure() ); | 
|         uomconversion := guard( sourceuom.GetConversionFactor( targetuom, null( Product_MP ) ), 1.0 ); | 
|      | 
|         // Term: -uomconversion   * OperationInputGroupOver/Under variable | 
|         // UoM: [Unit to Default] *           [Unit] | 
|         traverse( group, OperationInput, input, | 
|                   input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() )  | 
|                   ) | 
|         { | 
|           slackconst.NewTerm( -uomconversion * scalefactor_operationinputgroupover_const, | 
|                               program.OperationInputGroupOverVariables().Get( input, period ) ); | 
|           slackconst.NewTerm( -uomconversion * scalefactor_operationinputgroupunder_const, | 
|                               program.OperationInputGroupUnderVariables().Get( input, period ) ); | 
|         } | 
|       } | 
|     } | 
|      | 
|     // Penalty for violating the operation input set min/max | 
|      | 
|     traverse( scope.GetOperationInputSetInOptimizerRunConst(), Elements, set ) | 
|     { | 
|       operation := set.Operation(); | 
|       sourceuom := guard( set.UnitOfMeasure_MP(), this.MacroPlan().DefaultUnitOfMeasure() ); | 
|       periods := this.GetPeriodsForOperation( scope, operation ); | 
|      | 
|       traverse( periods, Elements, period) | 
|       { | 
|         uomconversion := guard( sourceuom.GetConversionFactor( targetuom, null( Product_MP ) ), 1.0 ); | 
|      | 
|         // Term: -uomconversion    * OperationInputGroupOver/Under variable | 
|         // UoM: [Input Set to Default]  *           [Unit] | 
|         slackconst.NewTerm( -uomconversion * scalefactor_operationinputsetover_const, program.OperationInputSetOverVariables().Get( set, period ) ); | 
|         slackconst.NewTerm( -uomconversion * scalefactor_operationinputsetunder_const, program.OperationInputSetUnderVariables().Get( set, period ) ); | 
|       } | 
|     } | 
|      | 
|     // Penalty for violating the minimum shift pattern duration constraint | 
|     if( runcontext.UseShiftOptimization() ) | 
|     { | 
|       traverse( scope.GetUnitInOptimizerRunConst(), Elements, unit, unit.GetUseShiftOptimization() ) | 
|       { | 
|         traverse( unit.GetUnitForShiftOptimization(), Elements.UnitPeriod.astype( UnitPeriodTime ), up ) | 
|         { | 
|           traverse( up, Unit.UnitShiftPatternAllowed.ShiftPattern, sp ) | 
|           { | 
|             slackconst.NewTerm( -1.0 * scalefactor_shiftdurationslack_constr, program.ShiftPatternDurationSlackVariables().Get( sp, up ) ); | 
|           } | 
|         } | 
|       } | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |