Quintiq file version 2.0
|
#parent: #root
|
Method InitConstraintsForShelfLifeCumulativeDemand (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const ProductInStockingPointInPeriodPlanning pispip,
|
DateTime lastpispipstart,
|
DateTime firstafteractualstart,
|
const IncomingShelfLifeDay islday,
|
const LibOpt_Scope scope
|
) const
|
{
|
Description: 'Initialize the constraints that are related to shelf life'
|
TextBody:
|
[*
|
cdconstname := typeof( MPCumulativeDemandConstraint );
|
scalefactor_mass := this.ScaleConstraintTerm( typeof( MPSalesDemandQtyVariable ), cdconstname );
|
scalefactor_rhs_constr := this.ScaleConstraintRHS( cdconstname, 1.0 );
|
|
previouspispip := pispip.PreviousPlanningPISPIP();
|
|
constr := program.CumulativeDemandConstraints().New( pispip, islday );
|
constr.RHSValue( 0.0 );
|
constr.Sense( '=' );
|
|
var := program.CumulativeDemandVariables().Find( previouspispip, islday );
|
isfirstpispip := isnull( var );
|
|
if ( not isfirstpispip ) // once var = null then we are at the 1st period of extra pispip prior to opt horizon (for which we make sure we always have enough via method ShelfLifeExtendHistoricalPeriods
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass,
|
program.CumulativeDemandVariables().Get( previouspispip, islday ) );
|
}
|
|
// sales and dependent demand applicable for CP(pispip, *)
|
pispipstoconsider := pispip.GetNextPISPIPWithinShelfLife( lastpispipstart ); // included pispip - still need to check for precise shelf life condition
|
product := pispip.ProductInStockingPoint_MP().Product_MP();
|
|
traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )
|
{
|
traverse( pispipstoconsider,
|
Elements,
|
pispipnext,
|
CapacityPlanningSuboptimizer::ShelfLifeFilterArrivedForDemand( pispip, pispipnext, islday )
|
and CapacityPlanningSuboptimizer::GetIsUsableInTargetPeriod( product, pispip.Period_MP(), pispipnext.GetTargetPeriod( oslday ) )
|
and ( isfirstpispip or not CapacityPlanningSuboptimizer::GetIsUsableInTargetPeriod( product, pispip.PreviousPlanningPISPIP().Period_MP(), pispipnext.GetTargetPeriod( oslday ) ) ) // only add what is new
|
and ( pispipnext.Start() >= firstafteractualstart ) ) // exclude sales, dep. demand prior to actual if it exists )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, program.DependentDemandInPISPIPShelfLifeVariables().Get( pispipnext, islday, oslday ) );
|
if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() ) // the dependent demand var does not include sales demand so add separately (considered as outgoing lead time 0
|
{
|
traverse( pispipnext.GetLeafSalesDemandInPeriod(),
|
Elements,
|
lsdip,
|
not lsdip.IsPostponed() )
|
{
|
svar := program.SalesDemandQtyVariables().Find( lsdip );
|
if ( not isnull( svar ) )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, svar );
|
}
|
else
|
{
|
constr.RHSValue( constr.RHSValue() - scalefactor_rhs_constr * lsdip.FulfilledQuantity() );
|
}
|
}
|
|
// Postponed demands which are postponed to this period
|
previouspispip := pispipnext.PreviousPlanningPISPIP();
|
|
maxnumberofpostponement := pispipnext.ProductInStockingPoint_MP().OptimizerMaxPostponementPeriod(); // set in init instance for performance
|
for( i := 1;
|
i <= maxnumberofpostponement // within the maximum number of postponement periods
|
and not isnull( previouspispip ); // the previous pispip exists
|
i++ )
|
{
|
traverse( previouspispip.astype( ProductInStockingPointInPeriodPlanningLeaf ), PlanningBaseSalesDemandInPeriodForOptimizationPostponable, sd )
|
{
|
delayedvar := sd.GetDelayedSalesDemandShelfLifeQtyVariable( program, pispipnext.Period_MP(), islday );
|
if ( not isnull( delayedvar ) )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, delayedvar );
|
}
|
}
|
previouspispip := previouspispip.PreviousPlanningPISPIP();
|
}
|
}
|
}
|
}
|
constr.NewTerm( -1.0 * scalefactor_mass,
|
program.CumulativeDemandVariables().Get( pispip, islday ));
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|