Quintiq file version 2.0
|
#parent: #root
|
Method InitVariablesForOperationPeriodTask (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const constcontent PeriodTaskOperations userperiodtasks,
|
const LibOpt_Scope scope
|
) const
|
{
|
Description: 'Initialize all variables related to period task operation, including lot sizes, campaign, etc'
|
TextBody:
|
[*
|
// create period task related variables for operations
|
// 1. Init variables for all period tasks, freeze the lowerbounds for operations with a min quantity or feedback.
|
// 2. Freeze the user period tasks
|
|
start := OS::PrecisionCounter();
|
runcontext := this.GetRunContextConst();
|
mycount := 0;
|
// Operation: Init variables for all period tasks
|
traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation )
|
{
|
periods := this.GetPeriodsForOperation( scope, operation );
|
periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand
|
unit := operation.Unit();
|
|
iscapacitytypetime := unit.HasCapacityTypeTime();
|
|
traverse( periods, Elements, period )
|
{
|
// PTQty variable UoM: Unit
|
var := program.PTQtyVariables().New( operation, period );
|
var.VariableType( 'Continuous' );
|
mycount++;
|
|
if ( runcontext.UseOneTimeCost() and operation.HasOneTimeCost() )
|
{
|
isusedvar := program.PTIsUsedVariables().New( operation, period );
|
this.SetStartSolutionPTIsUsedVar( isusedvar, operation, period );
|
}
|
if( unit.HasToolOperations() and iscapacitytypetime )
|
{
|
unitperiod := UnitPeriod::FindUnitPeriodTypeIndex( unit.ID(), period.Start(), period.End() );
|
|
traverse( unitperiod, ToolInUnitPeriod.Tool, t)
|
{
|
if ( isnull( program.UnitPeriodToolIsUsedVariables().Find( unitperiod, t) ))
|
{
|
toolvar := program.UnitPeriodToolIsUsedVariables().New( unitperiod, t);
|
this.SetStartSolutionToolIsUsedVar( toolvar, unitperiod, t );
|
}
|
}
|
}
|
|
// Slack variables for the blending constraint
|
if( runcontext.UseBlending() and operation.IsBlending() )
|
{
|
program.BlendingMaxOverVariables().New( operation, period );
|
program.BlendingMinUnderVariables().New( operation, period );
|
}
|
|
// Maximum quantity on operation
|
if( runcontext.UseProcessMaximumQuantity()
|
and operation.HasMaximumQuantity() )
|
{
|
// MaxPTQtyOver variable UoM: Unit
|
program.MaxPTQtyOverVariables().New( operation, period ); // Penalty of overloading the process maximum quantity
|
}
|
|
// Lot size
|
if( ( runcontext.UseLotSize() or runcontext.UseLotCost() )
|
and operation.HasLotSize()
|
and period.IsWithinLotSizeHorizon() )
|
{
|
// PTNrOfLots variable UoM: Number
|
ptnroflotsvar := program.PTNrOfLotsVariables().New( operation, period );
|
|
// If this is a sliding windows run and the period is not in the sliding window, then relax the integer variable
|
if( runcontext.IsSlidingWindowsRun()
|
and not period.GetIsInSlidingWindow( scope ) )
|
{
|
ptnroflotsvar.VariableType( 'Continuous' );
|
}
|
|
// PTLotSizeUnder variable UoM: Unit
|
program.PTLotSizeUnderVariables().New( operation, period ); // Additional quantity required to reach the multiples of lot size
|
// PTLotSizeOver variable UoM: Unit
|
program.PTLotSizeOverVariables().New( operation, period ); // Quantity to be reduced in order to reach the multiples of lot size
|
|
}
|
|
// OperationInputSet slack variables UoM: Unit
|
traverse( operation, OperationInputSet, set )
|
{
|
program.OperationInputSetOverVariables().New( set, period );
|
program.OperationInputSetUnderVariables().New( set, period );
|
}
|
|
traverse( operation, OperationInput, input, input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
|
{
|
// OperationInputGroup slack variables UoM: Unit
|
if ( not isnull( input.OperationInputGroup() ) )
|
{
|
program.OperationInputGroupOverVariables().New( input, period );
|
program.OperationInputGroupUnderVariables().New( input, period );
|
}
|
}
|
|
// create variables for dependent demand
|
// Only include inputs where the product is included.
|
if ( operation.HasLeadTime() and not this.GetPeriodsFromPeriodTaskOperation() ) // case when we can use period tasks is below (for efficiency)
|
{
|
traverse( operation, OperationInput, input, input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
|
{
|
// Dependent demand that spans multiple periods when relative duration < 1
|
|
// Traverse over all operation dependent demand periods
|
// If any of these periods would be frozen or outside the horizon, the SelectPeriodsForOperation would not have included this operation/period combination
|
pispipperiods := construct( Period_MPs, constcontent );
|
CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &pispipperiods, this.GetPeriodsFromPeriodTaskOperation() );
|
|
traverse( pispipperiods, Elements, pispipperiod )
|
{
|
// PartialOperationDemandQty variable UoM: Input PISP
|
program.PartialOperationDemandQtyVariables().New( input, pispipperiod, period ); // identify by: input, the dd period, and pt period
|
}
|
}
|
}
|
|
// Campaign, only define the PTQtyCampaign variable if this period is within the campaign type period related to this unit
|
// and there is a campaign period of the related campaign in this period
|
contextisusecampaign := runcontext.UseCampaign();
|
ismanualcampaignsequence := not runcontext.UseCampaignSequenceOptimizer()
|
if ( ismanualcampaignsequence and contextisusecampaign and period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) )
|
{
|
traverse( operation,
|
OperationInCampaign,
|
oic,
|
exists( oic, Campaign_MP.PlanningCampaignPeriod, cperiod,
|
cperiod.UnitPeriod().Period_MP() = period ) )
|
{
|
// PTQtyCampaign variable UoM: Unit
|
ptcampaignqtyvar := program.PTCampaignQtyVariables().New( oic, period );
|
|
// oceaned 09/02/2016
|
// Freeze if corresponding PTiC has user set quantity
|
ptcampaign := select( oic,
|
PeriodTaskInCampaign,
|
ptic,
|
guard( ptic.CampaignPeriod_MP().UnitPeriod().Period_MP() = period, false )
|
and ptic.HasQuantitySetByUser() );
|
if( not( isnull( ptcampaign ) ) )
|
{
|
this.FixVariableStyleGuide( ptcampaignqtyvar, ptcampaign.Quantity() );
|
}
|
}
|
|
|
traverse( operation,
|
OperationInTransitionType.OperationInTransition,
|
oit,
|
exists( oit, Transition_MP.TransitionPeriod_MP, tperiod, tperiod.UnitPeriod().Period_MP() = period ) )
|
{
|
pttransvar := program.PTTransitionQtyVariables().New( oit, period );
|
pttrans := select( oit,
|
PeriodTaskInTransition,
|
ptit,
|
guard( ptit.TransitionPeriod_MP().UnitPeriod().Period_MP() = period, false )
|
and ptit.HasQuantitySetByUser() );
|
|
if ( not ( isnull( pttrans ) ) )
|
{
|
this.FixVariableStyleGuide( pttransvar, pttrans.Quantity() );
|
}
|
}
|
|
|
}
|
|
// Consider all relevant periods for the dependent demand
|
if ( not this.GetPeriodsFromPeriodTaskOperation() )
|
{
|
CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // simply adding to periodsfordd - nonunique
|
}
|
} // end traverse over period
|
|
|
if ( this.GetPeriodsFromPeriodTaskOperation() ) // instead of above (more expensive method)
|
{
|
traverse( operation, PeriodTaskOperationInScope.DependentDemand, dd )
|
{
|
periodsfordd.Add( dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP() );
|
}
|
}
|
|
periodsfordd := periodsfordd.Unique();
|
traverse( periodsfordd, Elements, ddperiod )
|
{
|
// create variables for dependent demand
|
// Only include those inputs where the product is included.
|
traverse( operation, OperationInput, input, input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
|
{
|
this.InitVariablesForOperationPeriodTask_AddDemandVar( program, runcontext, scope, input, ddperiod );
|
}
|
} // end travere over periodfordd
|
|
// create variables for dependent demand in case we can use period tasks ( efficiency) - case where we cannot use periodtasks is above
|
// Only include inputs where the product is included.
|
if ( operation.HasLeadTime() and this.GetPeriodsFromPeriodTaskOperation() )
|
{
|
traverse( operation, PeriodTaskOperationInScope.DependentDemand, dd )
|
{
|
input := dd.ProcessInput().astype( OperationInput );
|
if ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
|
{
|
pispipperiod := dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP();
|
|
// PartialOperationDemandQty variable UoM: Input PISP
|
program.PartialOperationDemandQtyVariables().New( input, pispipperiod, dd.PeriodTask_MP().UnitPeriod().Period_MP() ); // identify by: input, the dd period, and pt period
|
}
|
}
|
} //end if
|
} //end operation traverse
|
|
|
end := OS::PrecisionCounter();
|
durationptoinit := (end - start) /OS::PrecisionCounterFrequency();
|
debuginfo( '========>> number of pt vars = ', mycount );
|
debuginfo( 'Duration pto init =', durationptoinit );
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|