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