Quintiq file version 2.0
|
#parent: #root
|
Method InitConstraintsGoalsForTotalSlacks (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const RunContextForCapacityPlanning runcontext,
|
const LibOpt_Scope scope,
|
const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun,
|
const constcontent ProductInStockingPoint_MPs pispsinrun
|
) const
|
{
|
Description: 'The constraint to compute the total slacks used in the algorithm.'
|
TextBody:
|
[*
|
// calculate penalty of using slack
|
// slackconst constraint UoM: Default
|
slackconst := program.TotalSlackConstraints().New();
|
slackconst.Sense( '=' );
|
slackconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( slackconst ), 0.0 ) );
|
// Term UoM: Default
|
|
slackconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalSlackVariable ), typeofexpression( slackconst ) ), program.TotalSlackVariables().Get() );
|
|
// TotalSupplyUser slack
|
// Currently, a higher weight than the demandslack is used, which will always force the optimizer to fulfill the user defined total supply
|
// Term UoM: Default
|
slackconst.NewTerm( -2.0 * this.ScaleConstraintTerm( typeof( MPTotalSlackUserSupplyVariable ), typeofexpression( slackconst ) )
|
, program.TotalSlackUserSupplyVariables().Get() );
|
|
targetuom := this.MacroPlan().DefaultUnitOfMeasure();
|
|
scalefactor_demandslack_const := this.ScaleConstraintTerm( typeof( MPDemandSlackVariable ), typeofexpression( slackconst ) );
|
scalefactor_invpriorspec_const := this.ScaleConstraintTerm( typeof( MPInvQtySpecPriorToHorizonSlackVariable ), typeofexpression( slackconst ) );
|
scalefactor_spinvoutofscope_const := this.ScaleConstraintTerm( typeof( MPSPInvOutOfScopeSlackVariable ), typeofexpression( slackconst ) );
|
scalefactor_liminv_const := this.ScaleConstraintTerm( typeof( MPMetaLimitMaxInventoryPastHorizonSlackVariable ), typeofexpression( slackconst ) );
|
scalefactor_maturationslack_const := this.ScaleConstraintTerm( typeof( MPMaturationSlackVariable ), typeofexpression( slackconst ) );
|
scalefactor_operationinputgroupover_const := this.ScaleConstraintTerm( typeof( MPOperationInputGroupOverVariable ), typeofexpression( slackconst ) );
|
scalefactor_operationinputgroupunder_const := this.ScaleConstraintTerm( typeof( MPOperationInputGroupUnderVariable ), typeofexpression( slackconst ) );
|
scalefactor_operationinputsetover_const := this.ScaleConstraintTerm( typeof( MPOperationInputSetOverVariable ), typeofexpression( slackconst ) );
|
scalefactor_operationinputsetunder_const := this.ScaleConstraintTerm( typeof( MPOperationInputSetUnderVariable ), typeofexpression( slackconst ) );
|
scalefactor_shiftdurationslack_constr := this.ScaleConstraintTerm( typeof( MPShiftPatternDurationSlackVariable ), typeofexpression( slackconst ) );
|
|
|
if( runcontext.UseCampaignSequenceOptimizer() and runcontext.UseCampaign() )
|
{
|
vartotalcombislack := program.TotalCampaignSequencingCombiSlackVariables().Get();
|
slackconst.NewTerm( -1.0 * CapacityPlanningSuboptimizer::OptCampaignCombiSlackWeight(), vartotalcombislack ); // take absolute penalty of 1000 per combi sequence or coverage problem
|
|
scalefactor_overloadedvar_const := this.ScaleConstraintTerm( typeof( MPCampaignElementTypePeriodOverloadedStartVariable ), typeofexpression( slackconst ) );
|
|
traverse( scope.GetUnitPeriodInOptimizerRunConst(), Elements.OptCampaignUnitSubPeriod, ocusp )
|
{
|
traverse( ocusp, OptCampaignCombiElement.OptCampaignElementType, ocet )
|
{
|
varperiodoverloadstart := program.CampaignElementTypePeriodOverloadedStartVariables().Get( ocet, ocusp );
|
varperiodoverloadmid := program.CampaignElementTypePeriodOverloadedMidVariables().Get( ocet, ocusp );
|
varperiodoverloadend := program.CampaignElementTypePeriodOverloadedEndVariables().Get( ocet, ocusp );
|
|
slackconst.NewTerm( -1.0 * scalefactor_overloadedvar_const, varperiodoverloadstart );
|
slackconst.NewTerm( -1.0 * scalefactor_overloadedvar_const, varperiodoverloadmid );
|
slackconst.NewTerm( -1.0 * scalefactor_overloadedvar_const, varperiodoverloadend );
|
}
|
}
|
}
|
|
// Penalty for using supply slack in balance constraint
|
traverse( leafpispipsinrun, Elements, pispip )
|
{
|
uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor();
|
// Term: -uomconversion * DemandSlack variable
|
// UoM: [PISP to Default] * [PISP]
|
slackconst.NewTerm( -uomconversion * scalefactor_demandslack_const,
|
program.DemandSlackVariables().Get( pispip ) );
|
|
if ( runcontext.IsMetaIteration() )
|
{
|
slackvar := program.MetaLimitMaxInventoryPastHorizonSlackVariables().Find( pispip );
|
if ( not isnull( slackvar ) )
|
{
|
slackconst.NewTerm( -uomconversion * scalefactor_liminv_const, slackvar );
|
}
|
}
|
}
|
|
leafpispips := null( ProductInStockingPointInPeriodPlannings, constcontent, owning );
|
pispips := this.GetPISPIPsForInventorySpecifications( scope, false, &leafpispips );
|
startoptscope := runcontext.FirstPeriod_MP().Start();
|
traverse( pispips, Elements, pispip, pispip.Start() < startoptscope )
|
{
|
var := program.InvQtySpecPriorToHorizonSlackVariables().Find( pispip );
|
if ( not isnull( var ) )
|
{
|
uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor();
|
slackconst.NewTerm( -uomconversion * scalefactor_invpriorspec_const, var );
|
}
|
}
|
|
traverse( scope.GetStockingPointInPeriodInOptimizerRunConst(), Elements, spip,
|
not spip.StockingPoint_MP().IsPlannedInfinite() )
|
{
|
nextspip := spip.GetNextPlanningSPIP();
|
if ( not runcontext.IsSmartPlan()
|
and not isnull( nextspip )
|
and not scope.Contains( nextspip.SPIPInOptimizerRun() ) )
|
{
|
slackconst.NewTerm( -1.0 * scalefactor_spinvoutofscope_const, program.SPInvOutOfScopeSlackVariables().Get( spip ) );
|
}
|
}
|
|
|
// Penalty for using maturation slack in maturation constraint
|
traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() )
|
{
|
pispips := pisp.GetPISPIPForShelfLifeOptimizer( scope );
|
traverse( pispips, Elements, pispip )
|
{
|
uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor();
|
traverse( pisp, OutgoingShelfLifeDay, oslday )
|
{
|
slackconst.NewTerm( -uomconversion * scalefactor_maturationslack_const, program.MaturationSlackVariables().Get( pispip, oslday ) );
|
}
|
}
|
}
|
|
traverse( pispsinrun, Elements, pisp, pisp.IsOptShelfLife() )
|
{
|
pispips := pisp.PISPInOptimizerRun().GetPISPIPForShelfLifeOptimizer( scope );
|
traverse( pispips, Elements, pispip )
|
{
|
uomconversion := pispip.ProductInStockingPoint_MP().DefaultUOMConversionFactor();
|
traverse( pisp, IncomingShelfLifeDay, islday )
|
{
|
splitdemandslackvar := program.DemandSlackShelfLifeVariables().Get( pispip, islday );
|
slackconst.NewTerm( -uomconversion * scalefactor_demandslack_const, splitdemandslackvar );
|
}
|
}
|
}
|
|
// Penalty for violating the operation input group min/max
|
traverse( scope.GetOperationInputGroupInOptimizerRunConst(), Elements, group )
|
{
|
operation := group.Operation();
|
|
periods := this.GetPeriodsForOperation( scope, operation );
|
|
traverse( periods, Elements, period )
|
{
|
sourceuom := guard( operation.Unit().UnitOfMeasure_MP(), this.MacroPlan().DefaultUnitOfMeasure() );
|
uomconversion := guard( sourceuom.GetConversionFactor( targetuom, null( Product_MP ) ), 1.0 );
|
|
// Term: -uomconversion * OperationInputGroupOver/Under variable
|
// UoM: [Unit to Default] * [Unit]
|
traverse( group, OperationInput, input,
|
input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() )
|
)
|
{
|
slackconst.NewTerm( -uomconversion * scalefactor_operationinputgroupover_const,
|
program.OperationInputGroupOverVariables().Get( input, period ) );
|
slackconst.NewTerm( -uomconversion * scalefactor_operationinputgroupunder_const,
|
program.OperationInputGroupUnderVariables().Get( input, period ) );
|
}
|
}
|
}
|
|
// Penalty for violating the operation input set min/max
|
|
traverse( scope.GetOperationInputSetInOptimizerRunConst(), Elements, set )
|
{
|
operation := set.Operation();
|
sourceuom := guard( set.UnitOfMeasure_MP(), this.MacroPlan().DefaultUnitOfMeasure() );
|
periods := this.GetPeriodsForOperation( scope, operation );
|
|
traverse( periods, Elements, period)
|
{
|
uomconversion := guard( sourceuom.GetConversionFactor( targetuom, null( Product_MP ) ), 1.0 );
|
|
// Term: -uomconversion * OperationInputGroupOver/Under variable
|
// UoM: [Input Set to Default] * [Unit]
|
slackconst.NewTerm( -uomconversion * scalefactor_operationinputsetover_const, program.OperationInputSetOverVariables().Get( set, period ) );
|
slackconst.NewTerm( -uomconversion * scalefactor_operationinputsetunder_const, program.OperationInputSetUnderVariables().Get( set, period ) );
|
}
|
}
|
|
// Penalty for violating the minimum shift pattern duration constraint
|
if( runcontext.UseShiftOptimization() )
|
{
|
traverse( scope.GetUnitInOptimizerRunConst(), Elements, unit, unit.GetUseShiftOptimization() )
|
{
|
traverse( unit.GetUnitForShiftOptimization(), Elements.UnitPeriod.astype( UnitPeriodTime ), up )
|
{
|
traverse( up, Unit.UnitShiftPatternAllowed.ShiftPattern, sp )
|
{
|
slackconst.NewTerm( -1.0 * scalefactor_shiftdurationslack_constr, program.ShiftPatternDurationSlackVariables().Get( sp, up ) );
|
}
|
}
|
}
|
}
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|