| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsForMaturation ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInStockingPoint_MPs pispsinrun | 
| ) const | 
| { | 
|   TextBody: | 
|   [* | 
|     cpconstname := typeof( MPCumulativeDemandMaturationConstraint ); | 
|     scalefactor_mass := this.ScaleConstraintTerm( typeof( MPCumulativeDemandMaturationVariable ), cpconstname ); // just use same scaling everywhere | 
|     scalefactor_rhs_const := this.ScaleConstraintRHS( cpconstname, 1.0 ); | 
|      | 
|     traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() )  | 
|     { | 
|       initpispips := pisp.GetPISPIPForShelfLifeOptimizer( scope );  | 
|       datecutoffhistorical := pisp.GetCutOffDateHistoricalForOptimizerShelfLife();  | 
|       traverse( initpispips, Elements, pispip ) | 
|       { | 
|         ishistorical := pispip.IsPeriodFrozen();  | 
|         previouspispip := pispip.PreviousPlanningPISPIP();  | 
|         // define CumulativeDemandMaturation | 
|         traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )  | 
|         { | 
|           constr := program.CumulativeDemandMaturationConstraints().New( pispip, oslday );  | 
|           constr.NewTerm( -1.0 * scalefactor_mass, program.CumulativeDemandMaturationVariables().Get( pispip, oslday )  );  | 
|           | 
|            | 
|           var := program.CumulativeDemandMaturationVariables().Find( previouspispip, oslday );  | 
|           isfirstpispip := isnull( var );       | 
|           if ( not isfirstpispip ) //we assume we always have enough historical periods for maturation duration - for the very first period we can ignore what is before then  | 
|           { | 
|              constr.NewTerm( 1.0 * scalefactor_mass, var );  | 
|           } | 
|            | 
|           // now add all outgoing trips  | 
|           if ( oslday.ShelfLifeDays() > 0 or oslday.IsZeroShelfLifeDaysForTrips() )  | 
|           { | 
|             computeonlynewfromprevious := not isfirstpispip;  | 
|             newoutgoingtrips := pispip.GetOutgoingProductInTripsForMaturation( computeonlynewfromprevious, oslday ) // these are all trips departing up to current pispip with oslday leadtime for shelf life | 
|              | 
|             // next add the variables for each outgoing trip once | 
|             traverse( newoutgoingtrips,  | 
|                       Elements,  | 
|                       outgoingtrip,  | 
|                       not ( ishistorical and outgoingtrip.Trip().Departure().Date() <= datecutoffhistorical ) )  // exclude demand prior to actual)  | 
|             { | 
|               if ( scope.Contains( outgoingtrip.ProductInTripInOptimizerRun() ) )  | 
|               { | 
|                 constr.NewTerm( 1.0 * scalefactor_mass, | 
|                                program.TripDemandQtyVariables().Get( outgoingtrip ) );   | 
|               } | 
|               else | 
|               { | 
|                 demandfromtrip := outgoingtrip.DependentDemand().Quantity();  | 
|                 constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * demandfromtrip );  | 
|               } | 
|             } | 
|           } | 
|            | 
|           // sales and non trip dependent demand applicable for CP(pispip, *)  | 
|           if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() )  | 
|           { | 
|             if ( not ishistorical or pispip.Start().Date() > datecutoffhistorical )  | 
|             { | 
|               traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip ) | 
|               { | 
|                 if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent to scope.Contains( pispip.PISPIPInOptimizerRun() ) )  | 
|                 { | 
|                   constr.NewTerm( 1.0 * scalefactor_mass, program.SalesDemandQtyVariables().Get( lsdip ) ); | 
|                 } | 
|                 else | 
|                 { | 
|                   constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * lsdip.FulfilledQuantity() );  | 
|                 } | 
|               } | 
|               // non trip dependent demand  | 
|               traverse( pispip,  | 
|                         ProductInStockingPoint_MP.OperationInputAvailableForOptimization,  | 
|                         input, | 
|                         guard( scope.Contains( input.Operation().OperationInOptimizerRun() ), false ) | 
|                         and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.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 ) ) | 
|                 { | 
|                   constr.NewTerm( 1.0 * scalefactor_mass, operationdemandqtyvar ); | 
|                 } | 
|               } | 
|                | 
|               // non trip dependent demand in case pispip is not in run but part of extra pispips prior to horizon | 
|               traverse( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).DependentDemand, dd )  | 
|               { | 
|                 if ( dd.IsDependentDemandOfOperation() | 
|                     and ( isnull( dd.PeriodTaskOperation().UnitPeriodWhenInScope() ) ) )  | 
|                 {           | 
|                   constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * dd.Quantity() );  | 
|                 } | 
|               } | 
|             } | 
|           } // endif oslday = 0 | 
|            | 
|           // Define maturation slack [pispip, oslday]  | 
|           // sum all smaller oslday 'o' CDMat[pispip, o ] <= 'production that has arrived' + mat slack [ pispip, oslday]  | 
|           // | 
|           matconstr := program.MaturationSlackConstraints().New( pispip, oslday );  | 
|           matconstr.NewTerm( -1.0 * scalefactor_mass, program.MaturationSlackVariables().Get( pispip, oslday ) );  | 
|            | 
|           osldayatmost := selectset( pisp, OutgoingShelfLifeDay,  | 
|                                      osld,  | 
|                                      true,  | 
|                                      osld.ShelfLifeDays() <= oslday.ShelfLifeDays()  | 
|                                      and osld.IsZeroShelfLifeDaysForTrips() = oslday.IsZeroShelfLifeDaysForTrips() );  | 
|           traverse( osldayatmost, Elements, osltoaddd )  | 
|           { | 
|             matconstr.NewTerm( 1.0 * scalefactor_mass, program.CumulativeDemandMaturationVariables().Get( pispip, osltoaddd ) );  | 
|           } | 
|            | 
|           ismaturationforarrival := true;  | 
|           this.AddProductionTermMaturationSlackConstraint( program, matconstr, pisp, pispip, oslday, scalefactor_mass, scalefactor_rhs_const, ismaturationforarrival );  | 
|         } // traverse oslday | 
|       } // traverse pispip | 
|     } // traverse pisp | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |