Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method InitConstraintsForBalance ( 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program, 
 | 
  const constcontent ProductInStockingPointInPeriods smartplanpispips, 
 | 
  const RunContextForCapacityPlanning runcontext, 
 | 
  const LibOpt_Scope scope, 
 | 
  const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun, 
 | 
  const constcontent ProductInStockingPoint_MPs pispsinrun, 
 | 
  Number threadnr 
 | 
) const 
 | 
{ 
 | 
  Description: 
 | 
  [* 
 | 
    To balance the demands and supply in pispip 
 | 
    Dependent demands must be fulfilled in full quantity. Sales demands can be fulfilled halfly. 
 | 
  *] 
 | 
  TextBody: 
 | 
  [* 
 | 
    //If we only want to plan 1 step up stream we need to find the intermediate products of the involved routings. 
 | 
    //They are needed so we can remove the slack from those intermediate making sure the violations if any are created on the input. 
 | 
     
 | 
     
 | 
    balance_constname :=  typeof( MPBalanceConstraint ); 
 | 
     
 | 
    scalefactor_demandslack_const := this.ScaleConstraintTerm( typeof( MPDemandSlackVariable ), balance_constname ); 
 | 
    scalefactor_tripnewsupply_const := this.ScaleConstraintTerm( typeof( MPTripNewSupplyVariable ), balance_constname ); 
 | 
    scalefactor_invqty_const := this.ScaleConstraintTerm( typeof( MPInvQtyVariable ), balance_constname ); 
 | 
    scalefactor_salesdemandqty_const := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), balance_constname ); 
 | 
    scalefactor_dependentdemandinpispip_const := this.ScaleConstraintTerm( typeof( MPDependentDemandInPISPIPVariable ), balance_constname ); 
 | 
    scalefactor_delayedsalesdemandqty_const := this.ScaleConstraintTerm( typeof( MPDelayedSalesDemandQtyVariable ), balance_constname ); 
 | 
    scalefactor_periodtaskqty_const := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), balance_constname ); 
 | 
    scalefactor_expired_const := this.ScaleConstraintTerm( typeof( MPExpiredVariable ), balance_constname ); 
 | 
     
 | 
    scalefactor_rhs_constr := this.ScaleConstraintRHS( balance_constname, 1.0 ); 
 | 
     
 | 
    intermediatepisps := construct( ProductInStockingPoint_MPs, constcontent );  
 | 
    if ( runcontext.IsOnlyPlanOneStepUpstream() )  
 | 
    { 
 | 
      intermediatepisps := selectset( scope.GetRoutingOfSmartPlanPISPIPsConst(), Elements.OperationInput.ProductInStockingPoint_MP, pisp,  
 | 
                                           exists( scope.GetRoutingOfSmartPlanPISPIPsConst(), Elements.OperationOutput.ProductInStockingPoint_MP, pisp2, pisp2 = pisp ) ); 
 | 
        
 | 
      // we need the unsplit balance equation always. For this small planning case we dont spread over threads  
 | 
      if ( threadnr = 0 )  
 | 
      { 
 | 
        traverse( leafpispipsinrun, Elements, pispip )  
 | 
        { 
 | 
          this.InitConstraintsForBalanceNoShelfLife( program,  
 | 
                                                     smartplanpispips,  
 | 
                                                     intermediatepisps,  
 | 
                                                     pispip,  
 | 
                                                     runcontext,  
 | 
                                                     scope,  
 | 
                                                     scalefactor_demandslack_const,  
 | 
                                                     scalefactor_tripnewsupply_const,  
 | 
                                                     scalefactor_invqty_const,  
 | 
                                                     scalefactor_salesdemandqty_const,  
 | 
                                                     scalefactor_dependentdemandinpispip_const,  
 | 
                                                     scalefactor_delayedsalesdemandqty_const,  
 | 
                                                     scalefactor_periodtaskqty_const,  
 | 
                                                     scalefactor_expired_const,  
 | 
                                                     scalefactor_rhs_constr );  
 | 
        } 
 | 
      } 
 | 
    } 
 | 
    else 
 | 
    { 
 | 
      // right now pispip.PreThreadNr is 0, 1, ..., 999. We use thread param to balance the workload  
 | 
     
 | 
      // we need the unsplit balance equation always 
 | 
      traverse( leafpispipsinrun, Elements, pispip, CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr )  
 | 
      { 
 | 
        this.InitConstraintsForBalanceNoShelfLife( program,  
 | 
                                                   smartplanpispips,  
 | 
                                                   intermediatepisps,  
 | 
                                                   pispip,  
 | 
                                                   runcontext,  
 | 
                                                   scope,  
 | 
                                                   scalefactor_demandslack_const,  
 | 
                                                   scalefactor_tripnewsupply_const,  
 | 
                                                   scalefactor_invqty_const,  
 | 
                                                   scalefactor_salesdemandqty_const,  
 | 
                                                   scalefactor_dependentdemandinpispip_const,  
 | 
                                                   scalefactor_delayedsalesdemandqty_const,  
 | 
                                                   scalefactor_periodtaskqty_const,  
 | 
                                                   scalefactor_expired_const,  
 | 
                                                   scalefactor_rhs_constr );  
 | 
      } 
 | 
    } 
 | 
     
 | 
     
 | 
    if ( threadnr = 0 ) // put all in thread 'A'  
 | 
    { 
 | 
      // if shelf life is active we also need to create balances that are split per incoming lead time  
 | 
      traverse( pispsinrun, Elements, pisp, pisp.IsOptShelfLife() )  
 | 
      { 
 | 
        pispips := pisp.GetPISPIPForShelfLifeOptimizer( scope ); // this includes extra periods prior to the optimizer scope spanning at least the shelf life (this is a super set of what is in algorithmrun.PISPIPInOptimizerRun) 
 | 
         
 | 
        firststart := DateTime::MinDateTime(); // set in method call - will be the first pispip.start from among 'pispips' 
 | 
        laststart := DateTime::MinDateTime(); // set in method call - will be the last pispip.start from among 'pispips' 
 | 
        firstafteractualstart := DateTime::MinDateTime(); // set in method call - will be the first pispip.start after the last actual (if any) 
 | 
        pisp.GetScopeShelfLifeForPISP( pispips, firststart, laststart, firstafteractualstart ); // set above three variables  
 | 
        firstpispipforbalancestart := maxvalue( firststart, firstafteractualstart ); // we will initialize the split balance constraint after the last actual, or for any of the elements of 'pispips' if there are no actuals 
 | 
        traverse( pispips, Elements.astype( ProductInStockingPointInPeriodPlanningLeaf ), pispip )  
 | 
        {    
 | 
            if ( pispip.Start() >= firstpispipforbalancestart )  
 | 
            { 
 | 
              this.InitConstraintsForBalanceSplitShelfLife( program,  
 | 
                                                            smartplanpispips,  
 | 
                                                            intermediatepisps,  
 | 
                                                            pispip,  
 | 
                                                            firstpispipforbalancestart,  
 | 
                                                            laststart,  
 | 
                                                            runcontext,  
 | 
                                                            scope, 
 | 
                                                            scalefactor_demandslack_const,  
 | 
                                                            scalefactor_tripnewsupply_const,  
 | 
                                                            scalefactor_invqty_const,  
 | 
                                                            scalefactor_salesdemandqty_const,  
 | 
                                                            scalefactor_dependentdemandinpispip_const,  
 | 
                                                            scalefactor_delayedsalesdemandqty_const,  
 | 
                                                            scalefactor_periodtaskqty_const,  
 | 
                                                            scalefactor_expired_const,  
 | 
                                                            scalefactor_rhs_constr ); // additional split balance constraint in case shelf life is optimized 
 | 
            } 
 | 
            this.InitConstraintsForShelfLifeSumConstraints( program,  
 | 
                                                            smartplanpispips,  
 | 
                                                            intermediatepisps,  
 | 
                                                            pispip,  
 | 
                                                            firststart,  
 | 
                                                            laststart,  
 | 
                                                            scope,  
 | 
                                                            scalefactor_invqty_const,  
 | 
                                                            scalefactor_rhs_constr ); // sum constraints taking care of consisteny between split and unsplit versions of a variable 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |