| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsForDependentDemandsInPISPIPForShelfLife ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInStockingPoint_MPs pispsinrun | 
| ) const | 
| { | 
|   Description: 'Initialize the constraint to compute the total dependent demands in a pispip for shelflife, 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 ); | 
|      | 
|     // To calculate the total dependent demand quantity in a pispip | 
|     traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() or pisp.IsOptShelfLife() )  | 
|     {  | 
|       pispipsforstockingpoint_shelflifeormaturation := pisp.PISPInOptimizerRun().GetPISPIPForShelfLifeOptimizer( scope ); // included extra pispips prior to optimizer scope  | 
|       traverse( pispipsforstockingpoint_shelflifeormaturation, Elements, pispip )  | 
|       {  | 
|         traverse( pisp, OutgoingShelfLifeDay, oslday )  | 
|         { | 
|           // Defining DD(pispip, oslday). Note we don't have a variable for this but we use sum_i DD(pispip, i, osld) and this is what we want to constrain | 
|           // const constraint UoM: PISP | 
|           const := program.DependentDemandInPISPIPShelfLifeConstraints().New( pispip, oslday ); | 
|           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. This is considered to have outgoing leadtime 0 | 
|           supplyquantity := ifexpr( pispip.InventorySupplyQuantity() < 0 and oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips(), pispip.InventorySupplyQuantity(), 0 ); | 
|          | 
|           // RHS UoM: PISP | 
|           const.RHSValue( supplyquantity * scalefactor_rhs_const ); | 
|           // term UoM: PISP | 
|           traverse( pisp, IncomingShelfLifeDay, islday )  | 
|           { | 
|             const.NewTerm( -1.0 * scalefactor_dependentdemandinpispip_const, | 
|                            program.DependentDemandInPISPIPShelfLifeVariables().Get( pispip, islday, oslday ) ); | 
|           }     | 
|           // Dependent demands for operations - considered outgoing leadtime 0. Note we distinguish between 0 outgoing leadtime for operations and trips using the attribute IsZeroShelfLifeDaysForTrips | 
|           if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() )  | 
|           { | 
|             if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent to scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|             { | 
|               ispostprocessing := runcontext.IsPostProcessing();  | 
|               traverse( pispip, ProductInStockingPoint_MP.OperationInputAvailableForOptimization, input, | 
|                         guard( scope.Contains( input.Operation().OperationInOptimizerRun() ), false ) | 
|                         and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( ispostprocessing ) ) | 
|               { | 
|                 operationdemandqtyvar := program.OperationDemandQtyVariables().Find( input, pispip.Period_MP() ) | 
|              | 
|                 // 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( 1.0 * scalefactor_operationdemandqty_const, operationdemandqtyvar ); | 
|                 } | 
|               } | 
|             } | 
|             else // we have pispips prior to the optimizer scope where we just want to set constant values from the model   | 
|             { | 
|               operationdemandfulfilled := pispip.DependentDemandNonTripFulfilledQuantity();  | 
|               const.RHSValue( const.RHSValue() - scalefactor_rhs_const * operationdemandfulfilled );  | 
|             } | 
|           } | 
|          | 
|           // Dependent demands for trips | 
|           // Only consider those productintrips that are part of the optimizer run | 
|           if ( oslday.ShelfLifeDays() > 0 or oslday.IsZeroShelfLifeDaysForTrips() ) | 
|           { | 
|             if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|             { | 
|               traverse( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).DependentDemand.ProductInTrip, productintrip, | 
|                         scope.Contains( productintrip.ProductInTripInOptimizerRun() )  | 
|                         and productintrip.Trip().GetShelfLifeAgeToAdd() = oslday.ShelfLifeDays() | 
|                        ) | 
|               { | 
|                 // Term UoM: PISP | 
|                 const.NewTerm( 1.0 * scalefactor_tripdemandqty_const, program.TripDemandQtyVariables().Get( productintrip ) ); | 
|               } | 
|             } | 
|             else | 
|             { | 
|               ddoutgoingtrip := sum( pispip,  | 
|                                      Demand_MP.astype( DependentDemand ),  | 
|                                      dd,  | 
|                                      guard( dd.ProductInTrip().Trip().GetShelfLifeAgeToAdd() = oslday.ShelfLifeDays(), false ), dd.Quantity() );  | 
|               const.RHSValue( const.RHSValue() - scalefactor_rhs_const * ddoutgoingtrip );  | 
|             } | 
|           } | 
|         } | 
|       } | 
|     } | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |