Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitConstraintsSequentialAtEnd ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const RunContextForCapacityPlanning runcontext, 
 | 
  const LibOpt_Scope scope, 
 | 
  const constcontent ProductInStockingPointInPeriodPlanningLeafs leafplanningpispips 
 | 
) const 
 | 
{ 
 | 
  Description: 'method to be executed after parallel cplex constraint init has taken places ( used for initialzing items that need data from multiple threads)' 
 | 
  TextBody: 
 | 
  [* 
 | 
     
 | 
    // Define the goals for each level 
 | 
    this.InitConstraintsForGoalsForLevelGoal( program,runcontext, scope ); // lkeep last because for meta we obtain values from existing plan before this 
 | 
     
 | 
    if ( runcontext.IsMetaIteration()  
 | 
         and this.FocusLevel() > 0  
 | 
         and this.GetRunContextMeta().OptionFixDemandSlackVar()  
 | 
         and this.DoLevelCollapse( runcontext ) ) 
 | 
    { 
 | 
      traverse( leafplanningpispips, Elements, pispip )  
 | 
      { 
 | 
        boundforvar := pispip.DependentDemandUnfulfilledQuantity() 
 | 
        this.FreezeSlackVariableMeta( program, pispip, boundforvar, program.DemandSlackVariables().Get( pispip ), program.TotalSlackConstraints().Get() ); 
 | 
      }  
 | 
       
 | 
      if( runcontext.GetConsiderTotalUserSupply( scope ) ) 
 | 
      { 
 | 
        pispipsforconstraint := runcontext.GetPISPISPForUserSupplyConstraint( scope, leafplanningpispips );  
 | 
         
 | 
        traverse( pispipsforconstraint, Elements.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispip )  
 | 
        { 
 | 
          // constr constraint UoM: PISP 
 | 
          constr := program.TotalSlackUserSupplyConstraints().Get();  
 | 
          varover := program.UserTotalSupplyOverVariables().Get( pispip );  
 | 
          varunder := program.UserTotalSupplyUnderVariables().Get( pispip );  
 | 
          oversupply := maxvalue( 0.0, pispip.SupplyQuantity()  - pispip.TotalSupplyUser() );  
 | 
          undersupply := maxvalue( 0.0, pispip.TotalSupplyUser() - pispip.SupplyQuantity() );  
 | 
          this.FreezeSlackVariableMeta( program, pispip, oversupply, varover, constr ); 
 | 
          this.FreezeSlackVariableMeta( program, pispip, undersupply, varunder, constr ); 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
    if ( runcontext.UseCampaignSequenceOptimizer() and runcontext.RunWithDebugCampaignCombis() )  
 | 
    { 
 | 
      // for running with manual fixed combis (debugging) it easy not to have selected a combi for a unit period, so we add a slack variable to safeguard against it 
 | 
      level_zero := select(  this, MacroPlan.StrategyMacroPlan.StrategyLevelMacroPlan, slm, true, slm.Level() = 0 );  
 | 
      traverse( scope.GetUnitPeriodInOptimizerRunConst(), Elements.OptCampaignUnitSubPeriod, ocusp ) 
 | 
      { 
 | 
        constr := program.CalcDurationOfOptCampaignUnitSubPeriodConstraints().Get( ocusp ); 
 | 
        debuginfo( 'Warning - running with fixed campaign combis. Adding slack variable ', constr.Name() );   
 | 
        slackvar := program.SlackDebugCampaignCombisVariables().New( ocusp );  
 | 
        c := program.GoalConstraints().Get( level_zero );   
 | 
        c.NewTerm( -1000.0, slackvar );  
 | 
        constr.NewTerm( 1.0, slackvar );    
 | 
      } 
 | 
    } 
 | 
     
 | 
    // Define PosInvPastLast variable in case inventory holding needs to be computed 
 | 
    if ( runcontext.IsMetaIteration() and this.GetInitializeFinancialConstraints( runcontext ) )  
 | 
    { 
 | 
        constname :=  typeof( MPDefinePosInvPastLastConstraint ); 
 | 
     
 | 
        scalefactor_posinvpastlast_const := this.ScaleConstraintTerm( typeof( MPPosInvQtyPastLastVariable ), constname ); 
 | 
        scalefactor_invqty_const := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), constname ); 
 | 
        scalefactor_rhs_constr := this.ScaleConstraintRHS( constname, 1.0 ); 
 | 
     
 | 
      traverse( scope.GetProductInStockingPointInOptimizerRunConst(), Elements, pisp )  
 | 
      { 
 | 
     
 | 
     
 | 
     
 | 
        last := pisp.LatestPISPIPInScope();  
 | 
        current := guard( last.Next().astype(  ProductInStockingPointInPeriodPlanningLeaf ), null(  ProductInStockingPointInPeriodPlanningLeaf ) );  
 | 
         
 | 
        while ( not isnull( current ) )  
 | 
        { 
 | 
          var := program.PosInvQtyPastLastVariables().Get( current );  
 | 
           
 | 
          // PosInvPastLast_current >= current.InventoryLevelEnd + (InvQty_last - last.InventoryLevelEnd )  
 | 
          // 
 | 
          // example: if we decrease the inventory of last by 5 this says PosInvPastLast_current >= current.InventoryLevelEnd - 5.  
 | 
          //          meaning if current.InventoryLevelEnd is <= 5, we can avoid inventory holding cost 
 | 
          // similarly if we increase by 5, posInvPastLast_current >= current.InventoryLevelEnd + 5 and we collect inventory holding cost in case previous inventory was bigger than 5 
 | 
           
 | 
          c := program.DefinePosInvPastLastConstraints().New( current );  
 | 
          c.Sense( '>=' );  
 | 
          c.RHSValue( ( current.InventoryLevelEnd() - last.InventoryLevelEnd() ) * scalefactor_rhs_constr );   
 | 
          c.NewTerm( 1.0 * scalefactor_posinvpastlast_const, var ); 
 | 
          c.NewTerm( -1.0 * scalefactor_invqty_const, program.InvQtyVariables().Get( last ) );   
 | 
           
 | 
          this.FilterCPLEXNoise( c, 1.0 );  
 | 
           
 | 
          current := current.NextPlanningPISPIP().astype(  ProductInStockingPointInPeriodPlanningLeaf );  
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
    traverse( runcontext, UserPeriodTask, pt, pt.HasUserQuantity() and pt.HasDependentDemandUserQuantity() ) // deal with potential infeasible manual fixed planning, where both  
 | 
    {                                                                                                        // periodtask dependent demand and new supply quantity are set 
 | 
      slackconstr := program.TotalSlackConstraints().Get();  
 | 
      period := pt.UnitPeriod().Period_MP();  
 | 
       
 | 
      constddqtyname := typeof( MPOperationDependentDemandQtyConstraint ); 
 | 
      constddpartialname := typeof( MPPartialOperationDependentDemandQtyConstraint ); 
 | 
      constslack := typeof( MPTotalSlackConstraint );  
 | 
     
 | 
      scalefactor_slack_constpartial := this.ScaleConstraintTerm( typeof( MPPartialOperationDependentDemandQtySlackNegVariable ), constddpartialname ); 
 | 
      scalefactor_partialslack_slackconst := this.ScaleConstraintTerm( typeof( MPPartialOperationDependentDemandQtySlackNegVariable ), constslack ); 
 | 
      scalefactor_slack_slackconst := this.ScaleConstraintTerm( typeof( MPOperationDependentDemandQtySlackNegVariable ), constslack ); 
 | 
      scalefactor_slack_constdd := this.ScaleConstraintTerm( typeof( MPOperationDependentDemandQtySlackNegVariable ), constddqtyname ); 
 | 
     
 | 
     
 | 
      traverse( pt, DependentDemand, dd, dd.HasUserQuantity() ) 
 | 
      { 
 | 
        pispipperiod := dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP();  
 | 
        input := dd.ProcessInput().astype( OperationInput );  
 | 
        if ( pt.Operation().HasLeadTime() )  
 | 
        { 
 | 
          c := program.PartialOperationDependentDemandQtyConstraints().Find( input, pispipperiod, period ); 
 | 
          if ( not isnull( c ) )  
 | 
          { 
 | 
            slacknegvar := program.PartialOperationDependentDemandQtySlackNegVariables().New( input, pispipperiod, period );  
 | 
            slackposvar := program.PartialOperationDependentDemandQtySlackPosVariables().New( input, pispipperiod, period );  
 | 
            c.NewTerm( 1.0 * scalefactor_slack_constpartial, slackposvar );  
 | 
            c.NewTerm( -1.0 * scalefactor_slack_constpartial, slacknegvar );  
 | 
             
 | 
            slackconstr.NewTerm( -1.0 * scalefactor_partialslack_slackconst, slacknegvar );  
 | 
            slackconstr.NewTerm( -1.0 * scalefactor_partialslack_slackconst, slackposvar );  
 | 
          } 
 | 
        }  
 | 
        else 
 | 
        { 
 | 
          c := program.OperationDependentDemandQtyConstraints().Find( input, period ); 
 | 
          if ( not isnull( c ) )  
 | 
          { 
 | 
            slackposvar := program.OperationDependentDemandQtySlackPosVariables().New( input, period );  
 | 
            slacknegvar := program.OperationDependentDemandQtySlackNegVariables().New( input, period );  
 | 
            c.NewTerm( 1.0 * scalefactor_slack_constdd, slackposvar );  
 | 
            c.NewTerm( -1.0 * scalefactor_slack_constdd, slacknegvar );  
 | 
             
 | 
            slackconstr.NewTerm( -1.0 * scalefactor_slack_slackconst, slacknegvar );  
 | 
            slackconstr.NewTerm( -1.0 * scalefactor_slack_slackconst, slackposvar );  
 | 
          } 
 | 
        }  
 | 
      }     
 | 
    } 
 | 
     
 | 
    program.GenerateNames(); // need to otherwise .sav files are anonymized 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |