Quintiq file version 2.0
|
#parent: #root
|
Method InitConstraintsForMaturation (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const RunContextForCapacityPlanning runcontext,
|
const LibOpt_Scope scope,
|
const constcontent ProductInStockingPoint_MPs pispsinrun
|
) const
|
{
|
TextBody:
|
[*
|
cpconstname := typeof( MPCumulativeDemandMaturationConstraint );
|
scalefactor_mass := this.ScaleConstraintTerm( typeof( MPCumulativeDemandMaturationVariable ), cpconstname ); // just use same scaling everywhere
|
scalefactor_rhs_const := this.ScaleConstraintRHS( cpconstname, 1.0 );
|
|
traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() )
|
{
|
initpispips := pisp.GetPISPIPForShelfLifeOptimizer( scope );
|
datecutoffhistorical := pisp.GetCutOffDateHistoricalForOptimizerShelfLife();
|
traverse( initpispips, Elements, pispip )
|
{
|
ishistorical := pispip.IsPeriodFrozen();
|
previouspispip := pispip.PreviousPlanningPISPIP();
|
// define CumulativeDemandMaturation
|
traverse( pispip, ProductInStockingPoint_MP.OutgoingShelfLifeDay, oslday )
|
{
|
constr := program.CumulativeDemandMaturationConstraints().New( pispip, oslday );
|
constr.NewTerm( -1.0 * scalefactor_mass, program.CumulativeDemandMaturationVariables().Get( pispip, oslday ) );
|
|
|
var := program.CumulativeDemandMaturationVariables().Find( previouspispip, oslday );
|
isfirstpispip := isnull( var );
|
if ( not isfirstpispip ) //we assume we always have enough historical periods for maturation duration - for the very first period we can ignore what is before then
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, var );
|
}
|
|
// now add all outgoing trips
|
if ( oslday.ShelfLifeDays() > 0 or oslday.IsZeroShelfLifeDaysForTrips() )
|
{
|
computeonlynewfromprevious := not isfirstpispip;
|
newoutgoingtrips := pispip.GetOutgoingProductInTripsForMaturation( computeonlynewfromprevious, oslday ) // these are all trips departing up to current pispip with oslday leadtime for shelf life
|
|
// next add the variables for each outgoing trip once
|
traverse( newoutgoingtrips,
|
Elements,
|
outgoingtrip,
|
not ( ishistorical and outgoingtrip.Trip().Departure().Date() <= datecutoffhistorical ) ) // exclude demand prior to actual)
|
{
|
if ( scope.Contains( outgoingtrip.ProductInTripInOptimizerRun() ) )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass,
|
program.TripDemandQtyVariables().Get( outgoingtrip ) );
|
}
|
else
|
{
|
demandfromtrip := outgoingtrip.DependentDemand().Quantity();
|
constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * demandfromtrip );
|
}
|
}
|
}
|
|
// sales and non trip dependent demand applicable for CP(pispip, *)
|
if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() )
|
{
|
if ( not ishistorical or pispip.Start().Date() > datecutoffhistorical )
|
{
|
traverse( pispip.GetLeafSalesDemandInPeriod(), Elements, lsdip )
|
{
|
if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent to scope.Contains( pispip.PISPIPInOptimizerRun() ) )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, program.SalesDemandQtyVariables().Get( lsdip ) );
|
}
|
else
|
{
|
constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * lsdip.FulfilledQuantity() );
|
}
|
}
|
// non trip dependent demand
|
traverse( pispip,
|
ProductInStockingPoint_MP.OperationInputAvailableForOptimization,
|
input,
|
guard( scope.Contains( input.Operation().OperationInOptimizerRun() ), false )
|
and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
|
{
|
operationdemandqtyvar := program.OperationDemandQtyVariables().Find( input, pispip.Period_MP() )
|
|
// If the variable does not exists, it indicates that this operation-period combination is not included in the optimizer run
|
// Therefore, this variable should then also not be added to this constraint
|
if( not isnull( operationdemandqtyvar ) )
|
{
|
constr.NewTerm( 1.0 * scalefactor_mass, operationdemandqtyvar );
|
}
|
}
|
|
// non trip dependent demand in case pispip is not in run but part of extra pispips prior to horizon
|
traverse( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).DependentDemand, dd )
|
{
|
if ( dd.IsDependentDemandOfOperation()
|
and ( isnull( dd.PeriodTaskOperation().UnitPeriodWhenInScope() ) ) )
|
{
|
constr.RHSValue( constr.RHSValue() - scalefactor_rhs_const * dd.Quantity() );
|
}
|
}
|
}
|
} // endif oslday = 0
|
|
// Define maturation slack [pispip, oslday]
|
// sum all smaller oslday 'o' CDMat[pispip, o ] <= 'production that has arrived' + mat slack [ pispip, oslday]
|
//
|
matconstr := program.MaturationSlackConstraints().New( pispip, oslday );
|
matconstr.NewTerm( -1.0 * scalefactor_mass, program.MaturationSlackVariables().Get( pispip, oslday ) );
|
|
osldayatmost := selectset( pisp, OutgoingShelfLifeDay,
|
osld,
|
true,
|
osld.ShelfLifeDays() <= oslday.ShelfLifeDays()
|
and osld.IsZeroShelfLifeDaysForTrips() = oslday.IsZeroShelfLifeDaysForTrips() );
|
traverse( osldayatmost, Elements, osltoaddd )
|
{
|
matconstr.NewTerm( 1.0 * scalefactor_mass, program.CumulativeDemandMaturationVariables().Get( pispip, osltoaddd ) );
|
}
|
|
ismaturationforarrival := true;
|
this.AddProductionTermMaturationSlackConstraint( program, matconstr, pisp, pispip, oslday, scalefactor_mass, scalefactor_rhs_const, ismaturationforarrival );
|
} // traverse oslday
|
} // traverse pispip
|
} // traverse pisp
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|