| Quintiq file version 2.0 | 
| #parent: #root | 
| Method InitConstraintsGoalsForUnitPeriods ( | 
|   CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, | 
|   const RunContextForCapacityPlanning runcontext, | 
|   const LibOpt_Scope scope, | 
|   const constcontent ProductInTrips pitinrun | 
| ) const | 
| { | 
|   Description: 'Init constraints goals for unit periods' | 
|   TextBody: | 
|   [* | 
|     collectvaluesmodel := runcontext.IsMetaIteration();  | 
|      | 
|     totalminimumcapacity := 0.0;  | 
|     totalminimumcapacitysecondary := 0.0;  | 
|     totalmaximumcapacity := 0.0;  | 
|     totalmaximumcapacitysecondary := 0.0;  | 
|     totalprocesssmax := 0.0; | 
|     totallotsize := 0.0;  | 
|     totalco2emission := 0.0; | 
|     scalefactoroverloaded := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityOverloadedQuantityVariable ) );  | 
|     scalefactoroverloadedtime := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityOverloadedTimeVariable ) );  | 
|     scalefactoroverloadedsecondary := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitSecondaryCapacityOverloadedVariable ) );  | 
|     scalefactorunderloadedquantity := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityNotMetQuantityVariable ) );  | 
|     scalefactorunderloadedtime := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityNotMetTimeVariable ) );  | 
|     scalefactormaxptqtyover := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPMaxPTQtyOverVariable ) );  | 
|      | 
|     // minimum capacity | 
|     // mcconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM, | 
|     //                                  their UnitCapacityNotMet will have a different weight in the goal | 
|     mcconst := program.TotalMinUnitCapacityConstraints().New();  | 
|     mcconst.Sense( '=' ); | 
|     mcconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( mcconst ), 0.0 ) ); | 
|     // Term UoM: Unit | 
|     mcconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalMinimumUnitCapacityVariable ), typeofexpression( mcconst ) ) | 
|                      , program.TotalMinimumUnitCapacityVariables().Get()); | 
|      | 
|     // smcconst constraint UoM: TransportCapacity --> Please note that this means that if different units have a different UoM, | 
|     //                                                their UnitSecondaryCapacityNotMet will have a different weight in the goal | 
|     smcconst := program.TotalMinUnitSecondaryCapacityConstraints().New(); | 
|     smcconst.Sense( '=' ); | 
|     smcconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( smcconst ), 0.0 ) ); | 
|     // Term UoM: TransportCapacity | 
|     smcconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalMinimumUnitSecondaryCapacityVariable ) | 
|                                                       , typeofexpression( smcconst ) ), program.TotalMinimumUnitSecondaryCapacityVariables().Get()); | 
|      | 
|     // unit capacity overloaded | 
|     // ucoconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM, | 
|     //                                   their UnitCapacityOverloaded will have a different weight in the goal | 
|     ucoconst := program.TotalUnitCapacityConstraints().New(); | 
|     ucoconst.Sense( '=' ); | 
|     ucoconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( ucoconst ), 0.0 ) ); | 
|     // Term UoM: Unit | 
|     ucoconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalUnitCapacityVariable ), typeofexpression( ucoconst ) ) | 
|                       , program.TotalUnitCapacityVariables().Get()); | 
|      | 
|     // sucoconst constraint UoM: TransportCapacity --> Please note that this means if different units have a different UoM, | 
|     //                                                 their UnitSecondaryCapacityOverloaded will have a different weight in the goal | 
|     sucoconst := program.TotalUnitSecondaryCapacityConstraints().New(); | 
|     sucoconst.Sense( '=' ); | 
|     sucoconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( sucoconst ), 0.0 ) ); | 
|     // Term UoM: TransportCapacity | 
|     sucoconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalUnitSecondaryCapacityVariable ) | 
|                                                        , typeofexpression( sucoconst ) ), program.TotalUnitSecondaryCapacityVariables().Get()); | 
|      | 
|     // Maximum quantity | 
|     // maxquantityconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM, | 
|     //                                           their MaxPTQtyOver will have a different weight in the goal | 
|     maxquantityconst := program.TotalProcessMaximumQuantityConstraints().New(); | 
|     maxquantityconst.Sense( '=' ); | 
|     maxquantityconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( maxquantityconst ), 0.0 ) ); | 
|     // Term UoM: Unit | 
|     maxquantityconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalProcessMaximumQuantityVariable ), typeofexpression( maxquantityconst ) ) | 
|                                                               , program.TotalProcessMaximumQuantityVariables().Get()); | 
|      | 
|     scalefactor_unitcapacitynotmet_mcconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityNotMetQuantityVariable ), typeofexpression( mcconst ) ); | 
|     scalefactor_unitcapacitynotmettime_mcconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityNotMetTimeVariable ), typeofexpression( mcconst ) ); | 
|     scalefactor_unitcapacityoverloaded_ucoconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityOverloadedQuantityVariable ), typeofexpression( ucoconst ) ); | 
|     scalefactor_unitcapacityoverloadedtime_ucoconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityOverloadedTimeVariable ), typeofexpression( ucoconst ) ); | 
|      | 
|     scalefactor_unitsecondarycapacitynotmet_smcconst := this.ScaleConstraintTerm( typeof( MPUnitSecondaryCapacityNotMetVariable ), typeofexpression( smcconst ) ); | 
|     scalefactor_unitsecondarycapacityoverloaded_sucoconst := this.ScaleConstraintTerm( typeof( MPUnitSecondaryCapacityOverloadedVariable ), typeofexpression( sucoconst ) ); | 
|      | 
|     unitperiods := construct( UnitPeriods, constcontent ); | 
|     traverse( scope.GetUnitPeriodInOptimizerRunConst(), Elements, up ) | 
|     { | 
|       unitperiods.Add( up ); | 
|       parentunitperiods := up.GetAllParentsOfUnitDimension(); | 
|       traverse( parentunitperiods, Elements, parentup )  | 
|       {  | 
|         unitperiods.Add(  parentup );  | 
|       } | 
|     } | 
|      | 
|     unitperiods := unitperiods.Unique(); | 
|     // The variables are not defined for parent units with infinite capacity | 
|     traverse( unitperiods, Elements, unitperiod, not ( unitperiod.Unit().HasChild() and unitperiod.Unit().HasCapacityTypeInfinite() ) ) | 
|     { | 
|       // Penalty for not meeting minimum capacity | 
|       // Term UoM: Unit | 
|       coefmincap := ifexpr(  unitperiod.IsTimeBasedCapacityUsage(), scalefactor_unitcapacitynotmettime_mcconst, scalefactor_unitcapacitynotmet_mcconst );  | 
|       mcconst.NewTerm( -1.0 * coefmincap, unitperiod.GetCapacityNotMetVariable( program ) ); | 
|      | 
|       // Penalty for overloading the unit capacity | 
|       // Term UoM: Unit | 
|       coefmaxcap :=  ifexpr(  unitperiod.IsTimeBasedCapacityUsage(), scalefactor_unitcapacityoverloadedtime_ucoconst, scalefactor_unitcapacityoverloaded_ucoconst);  | 
|       coefmincapsecondary := scalefactor_unitsecondarycapacitynotmet_smcconst;  | 
|       coefmaxcapsecondary := scalefactor_unitsecondarycapacityoverloaded_sucoconst;  | 
|        | 
|       ucoconst.NewTerm( -1.0 * coefmaxcap, unitperiod.GetCapacityOverloadedVariable( program ) );  | 
|        | 
|       processsecondary := unitperiod.istype( UnitPeriodTransportQuantity ) and unitperiod.astype( UnitPeriodTransportQuantity ).HasSecondaryCapacityDefinition();  | 
|       if( processsecondary ) | 
|       { | 
|         // Penalty for not meeting minimum secondary capacity | 
|         // Term UoM: TransportCapacity | 
|         smcconst.NewTerm( -1.0 * coefmincapsecondary, program.UnitSecondaryCapacityNotMetVariables().Get( unitperiod ) ); | 
|          | 
|         // Penalty for overloading the unit secondary capacity | 
|         // Term UoM: TransportCapacity | 
|         sucoconst.NewTerm( -1.0 * coefmaxcapsecondary, program.UnitSecondaryCapacityOverloadedVariables().Get( unitperiod ) ); | 
|       } | 
|        | 
|       if ( collectvaluesmodel )  | 
|       { | 
|         factoroverloaded := ifexpr( unitperiod.IsTimeBasedCapacityUsage(), scalefactoroverloadedtime, scalefactoroverloaded );  | 
|         factorunderloaded := ifexpr(  unitperiod.IsTimeBasedCapacityUsage(), scalefactorunderloadedtime, scalefactorunderloadedquantity );  | 
|         totalmaximumcapacity := totalmaximumcapacity + coefmaxcap * (unitperiod.OverloadCapacity() ) / factoroverloaded; | 
|         totalminimumcapacity := totalminimumcapacity + coefmincap * (unitperiod.CapacityNotMet() ) / factorunderloaded;  | 
|         if (  processsecondary )  | 
|         { | 
|           totalmaximumcapacitysecondary := totalmaximumcapacitysecondary  | 
|                                            + coefmaxcapsecondary * unitperiod.astype(  UnitPeriodTransportQuantity ).SecondaryOverloadCapacity() / scalefactoroverloadedsecondary;  | 
|                                             | 
|           totalminimumcapacitysecondary := totalminimumcapacitysecondary  | 
|                                            + coefmincapsecondary * unitperiod.astype(  UnitPeriodTransportQuantity ).CapacityNotMetSecondary() / scalefactor_unitsecondarycapacitynotmet_smcconst;                                     | 
|         } | 
|       } | 
|     } | 
|      | 
|     // workaround because cannot use attribute | 
|     this.StoreValueInProgram( program, 'collect_values_model_MPTotalUnitCapacityVariable', totalmaximumcapacity );  | 
|     this.StoreValueInProgram( program, 'collect_values_model_MPTotalUnitSecondaryCapacityVariable', totalmaximumcapacitysecondary );  | 
|     this.StoreValueInProgram( program, 'collect_values_models_MPTotalMinimumUnitCapacityVariable', totalminimumcapacity );  | 
|     this.StoreValueInProgram( program, 'collect_values_models_MPTotalMinimumUnitSecondaryCapacityVariable', totalminimumcapacitysecondary );  | 
|      | 
|      | 
|      | 
|     // Penalty for overloading the campaign and transition time capacity  | 
|     ismanualcampaignsequence := not runcontext.UseCampaignSequenceOptimizer() | 
|     if( ismanualcampaignsequence and runcontext.UseCampaign() ) | 
|     { | 
|       scalefactor_campaignoverloaded_uconst := this.ScaleConstraintTerm( typeof( MPCampaignPeriodOverloadedVariable ), typeofexpression( ucoconst ) );  | 
|       traverse( scope.GetUnitInOptimizerRunConst(), Elements.CampaignType_MP, type ) | 
|       { | 
|         // Only consider this campaign if at least one of its operations is part of this optimizer run | 
|         traverse( type, Campaign_MP, campaign, | 
|                   exists( campaign, OperationInCampaign.Operation, operation, | 
|                           scope.Contains( operation.OperationInOptimizerRun() ) ) ) | 
|         { | 
|           // Only consider the campaingperiod if its unit period is part of this optimizer run | 
|           traverse( campaign, PlanningCampaignPeriod, cp, | 
|                     guard( scope.Contains( cp.UnitPeriod().UnitPeriodInOptimizerRun() ), false ) ) | 
|           { | 
|             if ( not cp.UnitPeriod().Unit().IsPlannedInfinite() )  | 
|             { | 
|               ucoconst.NewTerm( -scalefactor_campaignoverloaded_uconst, program.CampaignPeriodOverloadedVariables().Get( cp ) ); | 
|                | 
|               if ( collectvaluesmodel )  | 
|               { | 
|                 // created backlog issue 2386 for meta optimizer cmt____ := 'collect here';  | 
|               } | 
|             } | 
|           } | 
|         } | 
|       } | 
|        | 
|       scalefactor_transitionoverloaded_uconst := this.ScaleConstraintTerm( typeof( MPTransitionPeriodOverloadedVariable ), typeofexpression( ucoconst ) );  | 
|       traverse( scope.GetUnitInOptimizerRunConst(),  | 
|                 Elements.TransitionType_MP.Transition_MP.TransitionPeriod_MP,  | 
|                 tperiod,  | 
|                 exists( tperiod, Transition_MP.OperationInTransition.OperationInTransitionType.Operation, operation, scope.Contains( operation.OperationInOptimizerRun() ) ) ) | 
|       { | 
|         if ( not tperiod.UnitPeriod().Unit().IsPlannedInfinite() )  | 
|         { | 
|           ucoconst.NewTerm( -scalefactor_transitionoverloaded_uconst, program.TransitionPeriodOverloadedVariables().Get( tperiod ) );  | 
|            | 
|             if ( collectvaluesmodel )  | 
|             { | 
|               // created backlog issue 2386 for meta optimizer cmt____ := 'collect here';  | 
|             } | 
|         } | 
|       } | 
|      | 
|       // campaign + transition output | 
|       | 
|       // TotalCampaignTransitionOutput = SUM[PTTransitionQtyVariables] | 
|       transconst := program.TotalCampaignTransitionOutputConstraints().New(); | 
|       transconst.Sense( '=' ); | 
|       transconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( transconst ), 0.0 ) ); | 
|       // Term UoM: Unit | 
|       transconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCampaignTransitionOutputVariable ), typeofexpression( transconst ) ), program.TotalCampaignTransitionOutputVariables().Get()); | 
|          | 
|       traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, operation.OperationInCampaign( relsize ) + operation.OperationInTransitionType( relsize ) > 0 ) | 
|       { | 
|         periods := this.GetPeriodsForOperation( scope, operation );   | 
|         traverse( periods, Elements, period, period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) ) | 
|         { | 
|           traverse( operation,  | 
|                     OperationInTransitionType.OperationInTransition,  | 
|                     oit,  | 
|                     exists( oit, Transition_MP.TransitionPeriod_MP, tperiod, tperiod.UnitPeriod().Period_MP() = period ) ) | 
|           { | 
|             pttransvar := program.PTTransitionQtyVariables().Get( oit, period );  | 
|             transconst.NewTerm(  -1.0 * this.ScaleConstraintTerm( typeof( MPPTTransitionQtyVariable ), typeofexpression( transconst)), pttransvar );  | 
|           } | 
|         } | 
|       } | 
|        | 
|       // camconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM, | 
|       //                                   their MinCampaignQtyUnder/MaxCampaignQtyOver will have a different weight in the goal | 
|       // | 
|       // TotalCampaignVariables = SUM[MinCampaignQtyUnderVariables] + SUM[MaxCampaignQtyOverVariables] - TotalCampaignTransitionOutputVariables | 
|       // | 
|       camconst := program.TotalCampaignConstraints().New(); | 
|       camconst.Sense( '=' ); | 
|       camconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( camconst ), 0.0 ) ); | 
|       // Term UoM: Unit | 
|       camconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCampaignVariable ), typeofexpression( camconst ) ), program.TotalCampaignVariables().Get()); | 
|        | 
|       scalefactor_mincampaignqtyunder_camconst := this.ScaleConstraintTerm( typeof(  MPMinCampaignQtyUnderVariable ), typeofexpression( camconst ) ); | 
|       scalefactor_maxcampaignqtyover_camconst := this.ScaleConstraintTerm( typeof(  MPMaxCampaignQtyOverVariable ), typeofexpression( camconst ) ); | 
|      | 
|       traverse( scope.GetUnitInOptimizerRunConst(), Elements.CampaignType_MP, type ) | 
|       { | 
|         // Only consider this campaign if at least one of its operations is part of this optimizer run | 
|         traverse( type, Campaign_MP, campaign, | 
|                   exists( campaign, OperationInCampaign.Operation, operation,  | 
|                           scope.Contains( operation.OperationInOptimizerRun() ) ) ) | 
|         { | 
|           // Penalty for planning under the minimum quantity of campaign | 
|           // Term UoM: Unit | 
|           camconst.NewTerm( -1.0 * scalefactor_mincampaignqtyunder_camconst, program.MinCampaignQtyUnderVariables().Get( campaign ) ); | 
|      | 
|           // Penalty for overloading the maximum quantity of campaign | 
|           // Term UoM: Unit | 
|           camconst.NewTerm( -1.0 * scalefactor_maxcampaignqtyover_camconst, program.MaxCampaignQtyOverVariables().Get( campaign ) ); | 
|         } | 
|       } | 
|       camconst.NewTerm( this.ScaleConstraintTerm( typeof( MPTotalCampaignTransitionOutputVariable ), typeofexpression( camconst ) ), program.TotalCampaignTransitionOutputVariables().Get() );  | 
|     } | 
|      | 
|     usemaxlotsize := runcontext.UseProcessMaximumQuantity(); | 
|     uselotsize := runcontext.UseLotSize(); | 
|     needlotcost := runcontext.UseLotCost(); | 
|      | 
|     if( usemaxlotsize or uselotsize or needlotcost ) | 
|     { | 
|       // Lot size | 
|       // lotsizeconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM, | 
|       //                                       their PTLotSizeUnder and TripLotSizeUnder will have a different weight in the goal | 
|        | 
|       lotsizeconst := program.TotalLotSizeConstraints().New();  | 
|       lotsizeconst.Sense( '=' ); | 
|       lotsizeconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( lotsizeconst ), 0.0 ) ); | 
|       // Term UoM: Unit | 
|       lotsizeconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalLotSizeVariable ), typeofexpression( lotsizeconst ) ) | 
|                             , program.TotalLotSizeVariables().Get()); | 
|                            | 
|       scalefactor_maxptqtyover_maxquantityconst := this.ScaleConstraintTerm( typeof( MPMaxPTQtyOverVariable ), typeofexpression( maxquantityconst ) ); | 
|       scalefactor_ptlotsizeunder_lotsizeconst := this.ScaleConstraintTerm( typeof( MPPTLotSizeUnderVariable ), typeofexpression( lotsizeconst ) ); | 
|       scalefactor_triplotsizeunder_lotsizeconst := this.ScaleConstraintTerm( typeof( MPTripLotSizeUnderVariable ), typeofexpression( lotsizeconst ) ); | 
|       scalefactor_operationinputlotsizeunder_inputlotsizeconst := this.ScaleConstraintTerm( typeof( MPOperationInputLotSizeUnderVariable ), typeofexpression( lotsizeconst ) ); | 
|       scalefactor_lotsizeundervar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPPTLotSizeUnderVariable ) );  | 
|       scalefactor_inputlotsizeundervar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPOperationInputLotSizeUnderVariable ) );  | 
|       scalefactor_lotsizeundertripvar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPTripLotSizeUnderVariable ) );  | 
|        | 
|       // Only those operations with a maximum quantity or lotsize should be considered | 
|       traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, | 
|                 operation.HasMaximumQuantity() | 
|                 or operation.HasLotSize() | 
|                 or operation.HasInputLotSize() ) | 
|       { | 
|         periods := this.GetPeriodsForOperation( scope, operation ); | 
|         periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand. Only need these for the input lot sizes - so will not compute if we do not have those | 
|      | 
|         traverse( periods, Elements, period ) | 
|         { | 
|           pt := constnull( PeriodTaskOperation ); // for efficiency only use type index at most once in loop - but must set to null at start of each loop | 
|           coeffmaxprocess := scalefactor_maxptqtyover_maxquantityconst;  | 
|           if( usemaxlotsize | 
|               and operation.HasMaximumQuantity() ) | 
|           { | 
|             // Penalty for exceeding the maximum quantity of operation | 
|             // Term UoM: Unit | 
|             maxquantityconst.NewTerm( -1.0 * coeffmaxprocess, program.MaxPTQtyOverVariables().Get( operation, period ) ); | 
|            | 
|             if ( collectvaluesmodel )  | 
|             { | 
|               pt := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() );  | 
|               totalprocesssmax := totalprocesssmax  + coeffmaxprocess * guard( maxvalue(  operation.MinimumQuantity() - pt.Quantity(), 0.0 ), 0.0 ) / scalefactormaxptqtyover | 
|             } | 
|           } | 
|      | 
|           if( ( uselotsize or needlotcost )  | 
|                 and operation.HasLotSize() | 
|                 and period.IsWithinLotSizeHorizon() ) | 
|           { | 
|             // Penalty for having additional quantity to reach the lot size multiples | 
|             // Term UoM: Unit | 
|             coefflotsizeunderterm := scalefactor_ptlotsizeunder_lotsizeconst;  | 
|             lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.PTLotSizeUnderVariables().Get( operation, period ) ); | 
|             lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.PTLotSizeOverVariables().Get( operation, period ) ); | 
|              | 
|             if ( collectvaluesmodel )  | 
|             { | 
|               if ( isnull( pt ) ) // for efficiency checking if already set in this loop iteration (above call to type index) | 
|               { | 
|                 pt := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() ); | 
|               }  | 
|               viol := pt.GetViolationLotsizeForOptimizer( this.SmallestIntegralityTolerance() );  | 
|               totallotsize := totallotsize + coefflotsizeunderterm * viol / scalefactor_lotsizeundervar;  | 
|             } | 
|           } | 
|            | 
|           // Consider all relevant periods for the dependent demand | 
|           if ( operation.HasInputLotSize() and not this.GetPeriodsFromPeriodTaskOperation() ) //Only need periodsfordd for the input lot sizes - so will not compute if we do not have those | 
|           { | 
|             CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // membership may not be unique. Output = periodsfordd | 
|           } | 
|         } // end traverse periods | 
|          | 
|          // Calculate the additional quantity required to reach a multiple of the input lot size. | 
|         if( ( uselotsize or needlotcost ) | 
|             and operation.HasInputLotSize() ) | 
|         { | 
|           if ( this.GetPeriodsFromPeriodTaskOperation() )  | 
|           { | 
|             traverse( operation, PeriodTaskOperationInScope.DependentDemand.ProductInStockingPointInPeriodPlanningLeaf.Period_MP, ddperiod )  | 
|             { | 
|               periodsfordd.Add( ddperiod ); // not using above method CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods for performance | 
|             } | 
|           } | 
|            | 
|           periodsfordd := periodsfordd.Unique(); | 
|           traverse( periodsfordd, Elements, period, | 
|                     period.IsWithinLotSizeHorizon() ) | 
|           { | 
|             traverse( operation,  | 
|                       OperationInput,  | 
|                       input, | 
|                       input.ProductInStockingPoint_MP().HasInputLotSize() | 
|                       and ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) ) | 
|             { | 
|               // Penalty for having additional quantity to fulfil the input lot size multiples | 
|               // Term UoM: Unit | 
|               lotsizeconst.NewTerm( -1.0 * scalefactor_operationinputlotsizeunder_inputlotsizeconst, | 
|                                     program.OperationInputLotSizeUnderVariables().Get( input, period ) ); | 
|               lotsizeconst.NewTerm( -1.0 * scalefactor_operationinputlotsizeunder_inputlotsizeconst, | 
|                           program.OperationInputLotSizeOverVariables().Get( input, period ) );                                 | 
|                                      | 
|               if ( collectvaluesmodel )  | 
|               { | 
|                 inputlotsize := input.ProductInStockingPoint_MP().PISPSpecification().InputLotSize(); | 
|                 dds := selectset( input, DependentDemand, dd, true, dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP() = period );  | 
|                 quantitytotal := sum( dds, Elements, dd, true, dd.Quantity() );  | 
|                  | 
|                 requiredlot := guard( Util::Ceil( quantitytotal / inputlotsize ), 0.0 );  | 
|                 violationinput := CapacityPlanningSuboptimizer::GetLotSizeViolationForVariable( inputlotsize, requiredlot, quantitytotal, this.SmallestIntegralityTolerance() );  | 
|                 totallotsize := totallotsize + ( scalefactor_operationinputlotsizeunder_inputlotsizeconst * violationinput / scalefactor_inputlotsizeundervar );  | 
|               } | 
|             } | 
|           } | 
|         } | 
|       } | 
|      | 
|       traverse( scope.GetTripInOptimizerRun(), Elements, trip, | 
|                 trip.DepartureUnitPeriod().Period_MP().IsWithinLotSizeHorizon() ) | 
|       { | 
|         unitperiod := trip.DepartureUnitPeriod(); | 
|      | 
|         if( ( uselotsize or needlotcost ) | 
|               and guard( unitperiod.HasLotSize(), false ) ) | 
|         { | 
|           // Penalty for having additional quantity to reach the lot size multiples | 
|           // Term UoM: Unit | 
|           coefflotsizeunderterm := scalefactor_triplotsizeunder_lotsizeconst;  | 
|           lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.TripLotSizeUnderVariables().Get( trip ) ); | 
|           lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.TripLotSizeOverVariables().Get( trip ) ); | 
|           if ( collectvaluesmodel )  | 
|           { | 
|             totallotsize := totallotsize + coefflotsizeunderterm * trip.GetViolationForOptimizer( this.SmallestIntegralityTolerance() ) / scalefactor_lotsizeundertripvar;  | 
|           } | 
|         } | 
|       } | 
|     } | 
|      | 
|     // workaround because cannot write to attribute | 
|     this.StoreValueInProgram( program, 'collect_values_model_TotalLotSizeVariables', totallotsize );  | 
|     this.StoreValueInProgram( program, 'collect_values_model_TotalProcessMaximumQuantityVariables', totalprocesssmax );  | 
|      | 
|     // Calculate the total blending constraint violation | 
|     if( runcontext.UseBlending() ) | 
|     {    | 
|       blendingconstr := program.TotalBlendingConstraints().New(); | 
|       blendingconstr.Sense( '=' ); | 
|       blendingconstr.RHSValue( 0.0 ); | 
|      | 
|       // Term UoM: Unit | 
|       blendingconstr.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalBlendingVariable ), typeofexpression( blendingconstr ) ) | 
|                               , program.TotalBlendingVariables().Get()); | 
|      | 
|       scalefactor_blendingmaxover_blendingconstr := this.ScaleConstraintTerm( typeof( MPBlendingMaxOverVariable ), typeofexpression( blendingconstr ) ); | 
|       scalefactor_blendingminunder_blendingconstr := this.ScaleConstraintTerm( typeof( MPBlendingMinUnderVariable ), typeofexpression( blendingconstr ) ); | 
|        | 
|       traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, operation.IsBlending() ) | 
|       { | 
|         periods := this.GetPeriodsForOperation( scope, operation ); | 
|         traverse( periods, Elements, period ) | 
|         { | 
|           // Term UoM: Unit | 
|           blendingconstr.NewTerm( -1.0 * scalefactor_blendingmaxover_blendingconstr, program.BlendingMaxOverVariables().Get( operation, period ) ); | 
|           blendingconstr.NewTerm( -1.0 * scalefactor_blendingminunder_blendingconstr, program.BlendingMinUnderVariables().Get(  operation, period ) ); | 
|         } | 
|       } | 
|     } | 
|      | 
|     // Calculate the total CO2 emission | 
|     totalco2emissionconstr := program.TotalCO2EmissionConstraints().New(); | 
|     totalco2emissionconstr.Sense( '=' ); | 
|     totalco2emissionconstr.RHSValue( 0.0 ); | 
|      | 
|     // Term UoM: CO2 | 
|     totalco2emissionconstr.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCO2EmissionVariable ), typeofexpression( totalco2emissionconstr ) ) | 
|                                     , program.TotalCO2EmissionVariables().Get() ); | 
|      | 
|     scalefactor_ptqty_totalco2emissionconstr := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), typeofexpression( totalco2emissionconstr ) ); | 
|     scalefactor_tripnewsupply_totalco2emissionconstr := this.ScaleConstraintTerm( typeof( MPTripNewSupplyVariable ), typeofexpression( totalco2emissionconstr ) ); | 
|      | 
|     co2uom := this.MacroPlan().DefaultCO2ProcessUoM(); | 
|      | 
|     // CO2 emission for operations | 
|     traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation ) | 
|     { | 
|       uomconversionfactor := operation.Unit().UnitOfMeasure_MP().GetConversionFactor( co2uom, null( Product_MP ) ); | 
|       co2emission := operation.CO2Emission(); | 
|       coeff := uomconversionfactor * co2emission; | 
|        | 
|       periods := this.GetPeriodsForOperation( scope, operation ); | 
|        | 
|       traverse( periods, Elements, period ) | 
|       { | 
|         // Term UoM: Unit | 
|         totalco2emissionconstr.NewTerm( -1.0 * coeff * scalefactor_ptqty_totalco2emissionconstr, program.PTQtyVariables().Get( operation, period ) ); | 
|       } | 
|        | 
|       traverse( operation, PeriodTaskOperationInScope, periodtask ) | 
|       { | 
|         totalco2emission := totalco2emission + coeff * scalefactor_ptqty_totalco2emissionconstr * periodtask.Quantity(); | 
|       } | 
|     } | 
|      | 
|     // CO2 emission for trips | 
|     traverse( pitinrun, Elements, productintrip ) | 
|     { | 
|       laneleg := productintrip.Trip().LaneLeg(); | 
|        | 
|       uomconversionfactor := laneleg.Lane().Unit().UnitOfMeasure_MP().GetConversionFactor( co2uom, null( Product_MP ) ); | 
|       co2emission := laneleg.CO2Emission(); | 
|       coeff := uomconversionfactor * co2emission; | 
|        | 
|       // Term UoM: Unit | 
|       totalco2emissionconstr.NewTerm( -1.0 * uomconversionfactor * co2emission * scalefactor_tripnewsupply_totalco2emissionconstr, program.TripNewSupplyVariables().Get( productintrip ) ); | 
|        | 
|       totalco2emission := totalco2emission + coeff * scalefactor_tripnewsupply_totalco2emissionconstr * productintrip.Quantity(); | 
|     } | 
|      | 
|     // workaround because cannot use attribute | 
|     this.StoreValueInProgram( program, 'collect_values_model_MPTotalCO2EmissionVariable', totalco2emission ) | 
|   *] | 
|   InterfaceProperties { Accessibility: 'Module' } | 
| } |