| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsForDependentDemandsInPISPIP ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun, | 
|   const constcontent ProductInTrips pitinrun, | 
|   Number threadnr | 
| ) const | 
| { | 
|   Description: 'Initialize the constraint to compute the total dependent demands in a pispip, also adding a slack (if utilize, penalize high cost) to prevent infeasibility when balancing the demands and supplies' | 
|   TextBody: | 
|   [* | 
|     constname := typeof( MPDependentDemandInPISPIPConstraint ); | 
|      | 
|     scalefactor_dependentdemandinpispip_const := this.ScaleConstraintTerm( typeof( MPDependentDemandInPISPIPVariable ), constname ); | 
|     scalefactor_operationdemandqty_const := this.ScaleConstraintTerm( typeof( MPOperationDemandQtyVariable ), constname ); | 
|     scalefactor_tripdemandqty_const := this.ScaleConstraintTerm( typeof( MPTripDemandQtyVariable ), constname ); | 
|     scalefactor_rhs_const := this.ScaleConstraintRHS( constname, 1.0 ); | 
|     ispostprocessing := runcontext.IsPostProcessing();  | 
|      | 
|     getperiodsfromptop := this.GetPeriodsFromPeriodTaskOperation();  | 
|      | 
|     // To calculate the total dependent demand quantity in a pispip | 
|     traverse( leafpispipsinrun, Elements, pispip, CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr  ) | 
|     { | 
|       // const constraint UoM: PISP | 
|       const := program.DependentDemandInPISPIPConstraints().New( pispip ); | 
|       const.Sense( '=' ); | 
|      | 
|       // Inventory supply that is greater than 0. If the supply is less than 0, it will be treated as a "must be fulfilled" demands | 
|       supplyquantity := ifexpr( pispip.InventorySupplyQuantity() < 0, pispip.InventorySupplyQuantity(), 0 ); | 
|      | 
|       // RHS UoM: PISP | 
|       const.RHSValue( supplyquantity * scalefactor_rhs_const ); | 
|       // term UoM: PISP | 
|       const.NewTerm( -1.0 * scalefactor_dependentdemandinpispip_const, | 
|                      program.DependentDemandInPISPIPVariables().Get( pispip ) ); | 
|      | 
|        | 
|       // Dependent demands for operations | 
|       if ( not getperiodsfromptop ) // for performance if we know periodtasks are there we can traverse those and add to the constraints | 
|       { | 
|         period := pispip.Period_MP();  | 
|         traverse( pispip, ProductInStockingPoint_MP.OperationInputAvailableForOptimization, input, | 
|                   scope.Contains( input.Operation().OperationInOptimizerRun() )  | 
|                   and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( ispostprocessing ) ) | 
|         { | 
|           operationdemandqtyvar := program.OperationDemandQtyVariables().Find( input, period ) | 
|           // If the variable does not exists, it indicates that this operation-period combination is not included in the optimizer run | 
|           // Therefore, this variable should then also not be added to this constraint | 
|           if( not isnull( operationdemandqtyvar ) ) | 
|           { | 
|             // Term UoM: PISP | 
|             const.NewTerm( scalefactor_operationdemandqty_const, operationdemandqtyvar ); | 
|           } | 
|         } | 
|       } | 
|     } | 
|      | 
|     if ( getperiodsfromptop )  | 
|     { | 
|       traverse(  scope.GetPeriodTaskOperationInOptimizerRunConst(), Elements.DependentDemand, dd )  | 
|       { | 
|         pispip := dd.ProductInStockingPointInPeriodPlanningLeaf();  | 
|         if ( CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr  )  | 
|         { | 
|           input := dd.ProcessInput().astype( OperationInput );  | 
|           if ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( ispostprocessing ) ) | 
|           { | 
|             period := pispip.Period_MP();  | 
|             operationdemandqtyvar := program.OperationDemandQtyVariables().Get( input, period ) | 
|             { | 
|               const := program.DependentDemandInPISPIPConstraints().Get( pispip ); | 
|               // Term UoM: PISP | 
|               if ( const.Term( operationdemandqtyvar ).Coefficient() = 0 )  | 
|               { | 
|                 const.NewTerm( scalefactor_operationdemandqty_const, operationdemandqtyvar ); | 
|               }  | 
|             } | 
|           } | 
|         } | 
|       }     | 
|     } | 
|      | 
|     traverse( pitinrun, Elements, pit )  | 
|     { | 
|       pispip := pit.DeparturePISPIP();  | 
|       if ( CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr )  | 
|       { | 
|         const := program.DependentDemandInPISPIPConstraints().Get( pispip ); | 
|         const.NewTerm( scalefactor_tripdemandqty_const, program.TripDemandQtyVariables().Get( pit ) ); | 
|       } | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |