Quintiq file version 2.0
|
#parent: #root
|
Method SetKPILowerBounds (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const RunContextForCapacityPlanning runcontext,
|
Boolean scopefrompreprod
|
) const
|
{
|
TextBody:
|
[*
|
if ( runcontext.IsMetaIteration() and not this.IsFullPlanMetaPriorFocus() )
|
{
|
message := '';
|
debuginfo( ifexpr( scopefrompreprod, 'Also fixing focus level because scope produced by pre-production selector', '' ) );
|
rcm := this.GetRunContextMeta();
|
if ( rcm.OptionCPLEXFixModelBoundsForGoals() )
|
{
|
size := counter( this, MacroPlan.StrategyMacroPlan.StrategyLevelMacroPlan, slm, true, slm.Level() >= 1 ); // exclude 0 level for slack
|
bounds := RealVector::Construct( size );
|
usage := BooleanVector::Construct( size );
|
|
traverse( this,
|
MacroPlan.StrategyMacroPlan.StrategyLevelMacroPlan,
|
level,
|
1 <= level.Level()
|
and level.Level() <= this.FocusLevel() )
|
{
|
level_TotalBoundFromPlan := program.RetrieveReal( 'collect_values_model_TotalBoundFromPlan' + [String] level.Level() ); // workaround because cannot write to attribute
|
|
// workaround for not being able to use attributes
|
level_SetCPLEXBoundFromPlan := program.RetrieveReal( 'collect_values_model_SetCPLEXBoundFromPlan' + [String] level.Level() ) > 0.5;
|
level_TotalBoundFromPlan := program.RetrieveReal( 'collect_values_model_TotalBoundFromPlan' + [String] level.Level() );
|
|
bounds.Set( level.Level() - 1, level_TotalBoundFromPlan );
|
if ( level_SetCPLEXBoundFromPlan and level.Level() < this.FocusLevel() + ifexpr( scopefrompreprod or runcontext.UseCampaignSequenceOptimizer(), 1, 0 ) ) // if scope is made by pre production selector then we also fix focus level
|
{ // for campaign sequence optimizer we also fix, because the campaign level gets reoptimized each time
|
message := message + 'Setting bound for level=' +[String] level.Level() + 'kpi >= '+ [String] level_TotalBoundFromPlan + String::NewLine();
|
|
usage.Set( level.Level() - 1, true );
|
goalvar := program.GoalForLevelVariables().Get( level );
|
totallotsizevar := program.TotalLotSizeVariables().Get();
|
totalspipcapvar := program.TotalStockingPointCapacityVariables().Get();
|
totalblendingvar := program.TotalBlendingVariables().Get();
|
|
constr := program.GoalLevelBoundForMetaConstraints().New( level );
|
constr.Sense( '>=' );
|
constr.RHSValue( level_TotalBoundFromPlan );
|
if ( level.NeedsMetaGoalSlack( this.FocusLevel() ) )
|
{
|
|
goalslackvar := program.GoalLevelSlackVariables().Get( level );
|
scalefactorforslackdefconstraint := this.ScaleConstraintTerm( typeofexpression( goalslackvar ), typeof( MPTotalSlackConstraint ) );
|
goalslackvar.UpperBound( 0.01 );
|
constr.NewTerm( 1.0, program.GoalLevelSlackVariables().Get( level ) ); // deliberately omitting scale factor.
|
slackdefconstraint := program.TotalSlackConstraints().Get();
|
slackdefconstraint.NewTerm( -1.0 * scalefactorforslackdefconstraint, goalslackvar );
|
}
|
|
this.FilterCPLEXNoise( constr, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate
|
goalcons := program.GoalConstraints().Get( level );
|
traverse( goalcons.Terms(),
|
Elements,
|
t,
|
not t.Variable() = goalvar
|
and not typeofexpression( t.Variable() ) = typeof (MPGoalLevelSlackVariable )
|
and not typeofexpression( t.Variable() ) = typeof( MPTotalStockingPointCapacityMetaVariable ) )
|
{
|
if ( t.Variable() = totallotsizevar )
|
{
|
c := program.UpperBoundForTotalLotSizeMetaConstraints().New();
|
value_collect_values_model_TotalLotSizeVariables := program.RetrieveReal( 'collect_values_model_TotalLotSizeVariables' ); // workaround for attribute
|
c.RHSValue( value_collect_values_model_TotalLotSizeVariables );
|
c.Sense( '<=' );
|
c.NewTerm( 1.0, totallotsizevar );
|
this.FilterCPLEXNoise( c, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate
|
message := message + 'Setting upper bound total lot size = ' + [String] c.RHSValue() + String::NewLine();
|
}
|
else if ( t.Variable() = totalspipcapvar )
|
{
|
totalstockingpointviolation := program.RetrieveReal( 'collect_values_model_TotalStockingPointCapacityVariables' );
|
c := program.UpperBoundForTotalSPIPCapacityMetaConstraints().New();
|
c.RHSValue( totalstockingpointviolation );
|
c.Sense( '<=' );
|
c.NewTerm( 1.0, totalspipcapvar );
|
this.FilterCPLEXNoise( c, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate
|
message := message + 'Setting upper bound for spip cap variable = ' + [String] c.RHSValue() + String::NewLine();
|
}
|
else if ( t.Variable() = totalblendingvar )
|
{
|
value_collectvalues_model_TotalBlendingViolation := program.RetrieveReal( 'collectvalues_model_TotalBlendingViolation' );
|
c := program.UpperBoundForTotalBlendingMetaConstraints().New();
|
c.RHSValue( value_collectvalues_model_TotalBlendingViolation );
|
c.Sense( '<=' );
|
c.NewTerm( 1.0, totalblendingvar );
|
this.FilterCPLEXNoise( c, 1.0 ); // this constraint is excluded from the parallel init, so need to do the filtering separate
|
message := message + 'Setting upper bound total blending = ' + [String] c.RHSValue() + String::NewLine();
|
}
|
else
|
{
|
constr.NewTerm( t.Coefficient(), t.Variable() );
|
}
|
}
|
}
|
}
|
}
|
debuginfo( message );
|
program.StoreString( 'message_kpilowerbound', message ); // workaround because method needs to be const
|
}
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|