Quintiq file version 2.0 
 | 
#parent: #root 
 | 
Method SetPTQtyVariableProperties ( 
 | 
  const LibOpt_Scope scope, 
 | 
  const RunContextForCapacityPlanning runcontext, 
 | 
  const Operation operation, 
 | 
  const Period_MP period, 
 | 
  MPVariable var, 
 | 
  Boolean setstart, 
 | 
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program 
 | 
) const 
 | 
{ 
 | 
  TextBody: 
 | 
  [* 
 | 
    lowerbound := 0.0; 
 | 
    var.LowerBound( -100.0 );  
 | 
    var.LowerBound( lowerbound );  
 | 
    var.UpperBound( Real::MaxReal() ); 
 | 
     
 | 
    // Minimum quantity on operation 
 | 
    if( runcontext.UseProcessMinimumQuantity() 
 | 
        and operation.HasMinimumQuantity() 
 | 
        and period.IsWithinLotSizeHorizon() 
 | 
        and ( not runcontext.IsSlidingWindowsRun() 
 | 
              or period.GetIsInSlidingWindow( scope ) ) ) 
 | 
    { 
 | 
      lowerbound := operation.MinimumQuantity() / operation.QuantityToProcessFactor();   // If PeriodTask.Quantity > 0, it must fulfill: PeriodTask.Quantity * Operation.QuantityToProcessFactor >= Operation.MinimumQuantity 
 | 
     
 | 
      if ( lowerbound > 0 )  
 | 
      { 
 | 
        scalefactor_timeconstbigm_rhs := this.ScaleConstraintRHS( typeof(  MPProcessMinQtyBIGMTimeConstraint ), 1.0 );  
 | 
        scalefactor_quantityconstbigm_rhs := this.ScaleConstraintRHS( typeof(  MPProcessMinQtyBIGMQuantityConstraint ), 1.0 );  
 | 
         
 | 
        scalefactor_ptqty_bigmtime_const := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), typeof( MPProcessMinQtyBIGMTimeConstraint )  ); 
 | 
        scalefactor_ptqty_bigmquantity_const := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), typeof( MPProcessMinQtyBIGMQuantityConstraint )  ); 
 | 
     
 | 
        unitperiod := UnitPeriod::FindUnitPeriodTypeIndex( operation.UnitID(), period.Start(), period.End() );  
 | 
         
 | 
        quantitycurrent := guard(  PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( unitperiod.Start(), operation.ID() ).Quantity(), 0.0 );  
 | 
        bigM := CapacityPlanningSuboptimizer::GetBigMProcessMinQty( operation, unitperiod, lowerbound, quantitycurrent );  // for time based capacity this is an upper bound on number of hours, for Quantity based an upper bound on quantity 
 | 
     
 | 
        iszerovar := program.PTQtyIsZero_MinProcessBigMVariables().New( operation, period );  
 | 
        iszerovar.StartValue( ifexpr( quantitycurrent = 0.0, 1.0, 0.0 ) );  
 | 
        var.LowerBound( 0.0 ); // PTQY needs to be >= 0  
 | 
     
 | 
          //      
 | 
          // scaledlowerbound <= ptqty + scaledlowerbound * iszerovar 
 | 
          // 
 | 
          c := program.ProcessMinQtyEnforceQuantityConstraints().New( operation, period );  
 | 
          scalefactor_scaledforcplex := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeofexpression( var ) );  
 | 
          scaledlowerbound := lowerbound / scalefactor_scaledforcplex;  
 | 
          c.Sense( '<=' );  
 | 
          c.RHSValue( -scaledlowerbound );  
 | 
          c.NewTerm(  -1.0, var );  
 | 
          c.NewTerm(  -1.0 * scaledlowerbound, iszerovar ); // no restriction if iszerovar=1, otherwise need to be at least lower bound 
 | 
          this.FilterCPLEXNoise( c, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate    
 | 
     
 | 
        if ( operation.Unit().HasCapacityTypeTime() )  
 | 
        { 
 | 
          capusqageperqty := operation.GetCapacityUsagePerQuantity( unitperiod ); 
 | 
     
 | 
          d := program.ProcessMinQtyBIGMTimeConstraints().New( operation, period );  
 | 
          d.Sense( '<=' );  
 | 
          d.RHSValue( bigM * scalefactor_timeconstbigm_rhs );  
 | 
          d.NewTerm( 1.0 * scalefactor_ptqty_bigmtime_const * capusqageperqty, var );  
 | 
          d.NewTerm( 1.0 * bigM * scalefactor_timeconstbigm_rhs, iszerovar );    
 | 
           
 | 
          this.FilterCPLEXNoise( d, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate 
 | 
        } 
 | 
        else 
 | 
        { 
 | 
          // 
 | 
          // ptyqty <= bigM - bigM*iszerovar 
 | 
          // 
 | 
          d := program.ProcessMinQtyBIGMQuantityConstraints().New( operation, period );  
 | 
          d.Sense( '<=' );  
 | 
          d.RHSValue( bigM * scalefactor_quantityconstbigm_rhs );  
 | 
          d.NewTerm( 1.0 * scalefactor_ptqty_bigmquantity_const, var );  
 | 
          d.NewTerm( 1.0 * bigM * scalefactor_quantityconstbigm_rhs, iszerovar );    
 | 
           
 | 
          this.FilterCPLEXNoise( d, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
     // Set feedback bounds that apply to the variable 
 | 
    if( operation.FeedbackPeriodTaskOperation( relsize ) > 0 ) 
 | 
    { 
 | 
      feedbackset := selectset(  operation,  
 | 
                                 FeedbackPeriodTaskOperation,  
 | 
                                 feedback, 
 | 
                                 true,  
 | 
                                 feedback.GetIsValidFeedback() and feedback.UnitPeriod().Period_MP() = period );  
 | 
                    
 | 
      feedbackqty := sum( feedbackset, Elements, feedback, true, feedback.FeedbackQuantity() ); 
 | 
     
 | 
      pto := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() );  
 | 
     
 | 
      islockedfeedback := guard( pto.IsFeedbackLocked(),  
 | 
                                 exists( feedbackset, Elements, fb, true, fb.IsLocked() ) );  
 | 
         
 | 
      lowerboundfixedsofar := lowerbound;  
 | 
     
 | 
      if( feedbackqty > 0  
 | 
          or islockedfeedback ) // if it is not locked setting lower bound >=0 & making continuous interfers with process min qty 
 | 
      { 
 | 
        iszerovar := program.FindVariable(  'PTQtyIsZero', operation, period );  
 | 
        if ( not isnull( iszerovar ) )  
 | 
        { 
 | 
          var.UpperBound( 0.0 );  
 | 
          constr := program.ProcessMinQtyEnforceQuantityConstraints().Get( operation, period );  
 | 
          constr.Enabled( false );  
 | 
          if ( operation.Unit().HasCapacityTypeQuantity() )  
 | 
          { 
 | 
            constr2 := program.ProcessMinQtyBIGMQuantityConstraints().Get( operation, period );  
 | 
            constr2.Enabled( false ); 
 | 
          } 
 | 
          else if ( operation.Unit().HasCapacityTypeTime() )  
 | 
          { 
 | 
            constr2 := program.ProcessMinQtyBIGMTimeConstraints().Get( operation, period );  
 | 
            constr2.Enabled( false );  
 | 
          }  
 | 
        } 
 | 
        if ( islockedfeedback )  
 | 
        { 
 | 
          this.FreezeVariableLowerUpperBound( var, feedbackqty, feedbackqty );  
 | 
        } 
 | 
        else 
 | 
        { 
 | 
          this.FreezeVariableLowerBound( var, maxvalue(  feedbackqty, lowerboundfixedsofar ) );  
 | 
        } 
 | 
      } 
 | 
    } 
 | 
     
 | 
    // set start value for semi continuous variables 
 | 
    if ( setstart and var.VariableType() = 'SemiContinuous' )  
 | 
    { 
 | 
      periodtask := select(  operation, PeriodTaskOperation, pto, true, pto.UnitPeriod().Period_MP() = period );  
 | 
      startval := 0.0;  
 | 
      if ( not isnull( periodtask )  ) 
 | 
      { 
 | 
        startval := periodtask.Quantity();  
 | 
      } 
 | 
      var.StartValue( startval  );  
 | 
    } 
 | 
     
 | 
    contextisusecampaign := runcontext.UseCampaign();  
 | 
    ismanualcampaignsequence := not runcontext.UseCampaignSequenceOptimizer() 
 | 
    if ( ismanualcampaignsequence and contextisusecampaign and period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) )  
 | 
    { 
 | 
      unit := operation.Unit();  
 | 
      up := select(  operation, Unit.UnitPeriod, uperiod, true, uperiod.Period_MP() = period );  
 | 
      iscampaignunit := unit.Campaign_MP( relsize ) > 0;  
 | 
       
 | 
      if ( iscampaignunit  
 | 
           and operation.OperationInCampaignType( relsize ) + operation.OperationInTransitionType( relsize ) = 0  // operation not in campaign or transition 
 | 
           and up.Period_MP().GetIsInCampaignTypeHorizonUnit( up.Unit() ) )                     // but it is in the campaign horizon  
 | 
      {    
 | 
         // set upper bound = 0 (for user period tasks exception is possible because set below) 
 | 
        debuginfo(  'Setting = 0', operation.ID(), period.Start() ) ; 
 | 
        ptqtyvar := program.PTQtyVariables().Get( operation, period );   
 | 
        ptqtyvar.UpperBound( 0.0 );  
 | 
        ptqtyvar.LowerBound( 0.0 ); 
 | 
      } 
 | 
    } 
 | 
  *] 
 | 
  InterfaceProperties { Accessibility: 'Module' } 
 | 
} 
 |