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