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' } 
 | 
} 
 |