Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitVariablesForOperationPeriodTask ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const constcontent PeriodTaskOperations userperiodtasks, 
 | 
  const LibOpt_Scope scope 
 | 
) const 
 | 
{ 
 | 
  Description: 'Initialize all variables related to period task operation, including lot sizes, campaign, etc' 
 | 
  TextBody: 
 | 
  [* 
 | 
    // create period task related variables for operations 
 | 
    // 1. Init variables for all period tasks, freeze the lowerbounds for operations with a min quantity or feedback. 
 | 
    // 2. Freeze the user period tasks 
 | 
     
 | 
    start := OS::PrecisionCounter();  
 | 
    runcontext := this.GetRunContextConst();  
 | 
    mycount := 0;  
 | 
    // Operation: Init variables for all period tasks 
 | 
    traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation ) 
 | 
    { 
 | 
      periods := this.GetPeriodsForOperation( scope, operation ); 
 | 
      periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand 
 | 
      unit := operation.Unit(); 
 | 
     
 | 
      iscapacitytypetime := unit.HasCapacityTypeTime(); 
 | 
       
 | 
      traverse( periods, Elements, period ) 
 | 
      { 
 | 
        // PTQty variable UoM: Unit 
 | 
        var := program.PTQtyVariables().New( operation, period ); 
 | 
        var.VariableType( 'Continuous' ); 
 | 
        mycount++;  
 | 
     
 | 
        if ( runcontext.UseOneTimeCost() and operation.HasOneTimeCost()  )  
 | 
        { 
 | 
          isusedvar := program.PTIsUsedVariables().New( operation, period ); 
 | 
          this.SetStartSolutionPTIsUsedVar( isusedvar, operation, period );  
 | 
        } 
 | 
        if( unit.HasToolOperations() and iscapacitytypetime ) 
 | 
        { 
 | 
          unitperiod := UnitPeriod::FindUnitPeriodTypeIndex( unit.ID(), period.Start(), period.End() );  
 | 
           
 | 
          traverse( unitperiod, ToolInUnitPeriod.Tool, t) 
 | 
          {        
 | 
            if ( isnull( program.UnitPeriodToolIsUsedVariables().Find( unitperiod, t) )) 
 | 
            { 
 | 
              toolvar := program.UnitPeriodToolIsUsedVariables().New( unitperiod, t); 
 | 
              this.SetStartSolutionToolIsUsedVar( toolvar, unitperiod, t );  
 | 
            } 
 | 
          } 
 | 
        }   
 | 
     
 | 
        // Slack variables for the blending constraint 
 | 
        if( runcontext.UseBlending() and operation.IsBlending() ) 
 | 
        { 
 | 
          program.BlendingMaxOverVariables().New( operation, period ); 
 | 
          program.BlendingMinUnderVariables().New( operation, period ); 
 | 
        } 
 | 
         
 | 
        // Maximum quantity on operation 
 | 
        if( runcontext.UseProcessMaximumQuantity() 
 | 
            and operation.HasMaximumQuantity() ) 
 | 
        { 
 | 
          // MaxPTQtyOver variable UoM: Unit 
 | 
          program.MaxPTQtyOverVariables().New( operation, period );   // Penalty of overloading the process maximum quantity 
 | 
        } 
 | 
     
 | 
        // Lot size 
 | 
        if( ( runcontext.UseLotSize() or runcontext.UseLotCost() ) 
 | 
              and operation.HasLotSize() 
 | 
              and period.IsWithinLotSizeHorizon() ) 
 | 
        { 
 | 
          // PTNrOfLots variable UoM: Number 
 | 
          ptnroflotsvar := program.PTNrOfLotsVariables().New( operation, period ); 
 | 
     
 | 
          // If this is a sliding windows run and the period is not in the sliding window, then relax the integer variable 
 | 
          if( runcontext.IsSlidingWindowsRun() 
 | 
              and not period.GetIsInSlidingWindow( scope ) ) 
 | 
          { 
 | 
            ptnroflotsvar.VariableType( 'Continuous' ); 
 | 
          } 
 | 
           
 | 
          // PTLotSizeUnder variable UoM: Unit 
 | 
          program.PTLotSizeUnderVariables().New( operation, period );     // Additional quantity required to reach the multiples of lot size 
 | 
          // PTLotSizeOver variable UoM: Unit 
 | 
          program.PTLotSizeOverVariables().New( operation, period );     // Quantity to be reduced in order to reach the multiples of lot size 
 | 
     
 | 
        } 
 | 
     
 | 
        // OperationInputSet slack variables UoM: Unit 
 | 
        traverse( operation, OperationInputSet, set ) 
 | 
        { 
 | 
          program.OperationInputSetOverVariables().New( set, period ); 
 | 
          program.OperationInputSetUnderVariables().New( set, period ); 
 | 
        } 
 | 
     
 | 
        traverse( operation, OperationInput, input, input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) 
 | 
        { 
 | 
          // OperationInputGroup slack variables UoM: Unit 
 | 
          if ( not isnull( input.OperationInputGroup() ) )  
 | 
          { 
 | 
            program.OperationInputGroupOverVariables().New( input, period ); 
 | 
            program.OperationInputGroupUnderVariables().New( input, period ); 
 | 
          } 
 | 
        } 
 | 
               
 | 
        // create variables for dependent demand 
 | 
        // Only include inputs where the product is included. 
 | 
        if ( operation.HasLeadTime() and not this.GetPeriodsFromPeriodTaskOperation() ) // case when we can use period tasks is below (for efficiency) 
 | 
        { 
 | 
          traverse( operation, OperationInput, input, input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) 
 | 
          { 
 | 
            // Dependent demand that spans multiple periods when relative duration < 1 
 | 
             
 | 
            // Traverse over all operation dependent demand periods 
 | 
            // If any of these periods would be frozen or outside the horizon, the SelectPeriodsForOperation would not have included this operation/period combination 
 | 
            pispipperiods := construct( Period_MPs, constcontent ); 
 | 
            CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &pispipperiods, this.GetPeriodsFromPeriodTaskOperation() ); 
 | 
             
 | 
            traverse( pispipperiods, Elements, pispipperiod ) 
 | 
            { 
 | 
              // PartialOperationDemandQty variable UoM: Input PISP 
 | 
              program.PartialOperationDemandQtyVariables().New( input, pispipperiod, period );     // identify by: input, the dd period, and pt period 
 | 
            } 
 | 
          } 
 | 
        } 
 | 
     
 | 
       // Campaign, only define the PTQtyCampaign variable if this period is within the campaign type period related to this unit 
 | 
       // and there is a campaign period of the related campaign in this period 
 | 
        contextisusecampaign := runcontext.UseCampaign();  
 | 
        ismanualcampaignsequence := not runcontext.UseCampaignSequenceOptimizer() 
 | 
        if ( ismanualcampaignsequence and contextisusecampaign and period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) )  
 | 
        { 
 | 
          traverse( operation,  
 | 
                    OperationInCampaign,  
 | 
                    oic, 
 | 
                    exists( oic, Campaign_MP.PlanningCampaignPeriod, cperiod, 
 | 
                                cperiod.UnitPeriod().Period_MP() = period ) ) 
 | 
          { 
 | 
            // PTQtyCampaign variable UoM: Unit 
 | 
            ptcampaignqtyvar := program.PTCampaignQtyVariables().New( oic, period ); 
 | 
       
 | 
            // oceaned 09/02/2016 
 | 
            // Freeze if corresponding PTiC has user set quantity 
 | 
            ptcampaign := select( oic,  
 | 
                                  PeriodTaskInCampaign,  
 | 
                                  ptic, 
 | 
                                  guard( ptic.CampaignPeriod_MP().UnitPeriod().Period_MP() = period, false ) 
 | 
                                  and ptic.HasQuantitySetByUser() ); 
 | 
            if( not( isnull( ptcampaign ) ) ) 
 | 
            { 
 | 
              this.FixVariableStyleGuide( ptcampaignqtyvar, ptcampaign.Quantity() ); 
 | 
            } 
 | 
          } 
 | 
           
 | 
           
 | 
          traverse( operation,  
 | 
                    OperationInTransitionType.OperationInTransition,  
 | 
                    oit,  
 | 
                    exists( oit, Transition_MP.TransitionPeriod_MP, tperiod, tperiod.UnitPeriod().Period_MP() = period ) ) 
 | 
          { 
 | 
            pttransvar := program.PTTransitionQtyVariables().New( oit, period );  
 | 
            pttrans := select(  oit,  
 | 
                                PeriodTaskInTransition,  
 | 
                                ptit,  
 | 
                                guard( ptit.TransitionPeriod_MP().UnitPeriod().Period_MP() = period, false )  
 | 
                                and ptit.HasQuantitySetByUser() );  
 | 
                                 
 | 
            if ( not ( isnull( pttrans ) ) )  
 | 
            { 
 | 
              this.FixVariableStyleGuide( pttransvar, pttrans.Quantity() );  
 | 
            }                         
 | 
          } 
 | 
           
 | 
           
 | 
        } 
 | 
     
 | 
        // Consider all relevant periods for the dependent demand 
 | 
        if ( not this.GetPeriodsFromPeriodTaskOperation() )  
 | 
        { 
 | 
          CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // simply adding to periodsfordd - nonunique 
 | 
        } 
 | 
      } // end traverse over period 
 | 
     
 | 
       
 | 
      if ( this.GetPeriodsFromPeriodTaskOperation() ) // instead of above (more expensive method)  
 | 
      { 
 | 
        traverse( operation, PeriodTaskOperationInScope.DependentDemand, dd )  
 | 
        { 
 | 
          periodsfordd.Add( dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP() );  
 | 
        } 
 | 
      } 
 | 
       
 | 
      periodsfordd := periodsfordd.Unique(); 
 | 
      traverse( periodsfordd, Elements, ddperiod ) 
 | 
      { 
 | 
        // create variables for dependent demand 
 | 
        // Only include those inputs where the product is included. 
 | 
        traverse( operation, OperationInput, input, input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) 
 | 
        { 
 | 
          this.InitVariablesForOperationPeriodTask_AddDemandVar( program, runcontext, scope, input, ddperiod );  
 | 
        } 
 | 
      } // end travere over periodfordd 
 | 
       
 | 
      // create variables for dependent demand in case we can use period tasks ( efficiency) - case where we cannot use periodtasks is above 
 | 
      // Only include inputs where the product is included. 
 | 
      if ( operation.HasLeadTime() and this.GetPeriodsFromPeriodTaskOperation() )  
 | 
      { 
 | 
        traverse( operation, PeriodTaskOperationInScope.DependentDemand, dd )  
 | 
        { 
 | 
          input := dd.ProcessInput().astype( OperationInput );  
 | 
          if ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) 
 | 
          { 
 | 
            pispipperiod := dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP();  
 | 
             
 | 
            // PartialOperationDemandQty variable UoM: Input PISP 
 | 
            program.PartialOperationDemandQtyVariables().New( input, pispipperiod,  dd.PeriodTask_MP().UnitPeriod().Period_MP() );     // identify by: input, the dd period, and pt period 
 | 
          } 
 | 
        } 
 | 
      } //end if  
 | 
    } //end operation traverse 
 | 
     
 | 
     
 | 
    end := OS::PrecisionCounter();  
 | 
    durationptoinit := (end - start) /OS::PrecisionCounterFrequency();  
 | 
    debuginfo( '========>> number of pt vars = ', mycount );  
 | 
    debuginfo(  'Duration pto init =', durationptoinit ); 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |