Quintiq file version 2.0
|
#parent: #root
|
Method InitConstraintsGoalsForUnitPeriods (
|
CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
|
const RunContextForCapacityPlanning runcontext,
|
const LibOpt_Scope scope,
|
const constcontent ProductInTrips pitinrun
|
) const
|
{
|
Description: 'Init constraints goals for unit periods'
|
TextBody:
|
[*
|
collectvaluesmodel := runcontext.IsMetaIteration();
|
|
totalminimumcapacity := 0.0;
|
totalminimumcapacitysecondary := 0.0;
|
totalmaximumcapacity := 0.0;
|
totalmaximumcapacitysecondary := 0.0;
|
totalprocesssmax := 0.0;
|
totallotsize := 0.0;
|
totalco2emission := 0.0;
|
scalefactoroverloaded := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityOverloadedQuantityVariable ) );
|
scalefactoroverloadedtime := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityOverloadedTimeVariable ) );
|
scalefactoroverloadedsecondary := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitSecondaryCapacityOverloadedVariable ) );
|
scalefactorunderloadedquantity := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityNotMetQuantityVariable ) );
|
scalefactorunderloadedtime := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPUnitCapacityNotMetTimeVariable ) );
|
scalefactormaxptqtyover := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPMaxPTQtyOverVariable ) );
|
|
// minimum capacity
|
// mcconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM,
|
// their UnitCapacityNotMet will have a different weight in the goal
|
mcconst := program.TotalMinUnitCapacityConstraints().New();
|
mcconst.Sense( '=' );
|
mcconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( mcconst ), 0.0 ) );
|
// Term UoM: Unit
|
mcconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalMinimumUnitCapacityVariable ), typeofexpression( mcconst ) )
|
, program.TotalMinimumUnitCapacityVariables().Get());
|
|
// smcconst constraint UoM: TransportCapacity --> Please note that this means that if different units have a different UoM,
|
// their UnitSecondaryCapacityNotMet will have a different weight in the goal
|
smcconst := program.TotalMinUnitSecondaryCapacityConstraints().New();
|
smcconst.Sense( '=' );
|
smcconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( smcconst ), 0.0 ) );
|
// Term UoM: TransportCapacity
|
smcconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalMinimumUnitSecondaryCapacityVariable )
|
, typeofexpression( smcconst ) ), program.TotalMinimumUnitSecondaryCapacityVariables().Get());
|
|
// unit capacity overloaded
|
// ucoconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM,
|
// their UnitCapacityOverloaded will have a different weight in the goal
|
ucoconst := program.TotalUnitCapacityConstraints().New();
|
ucoconst.Sense( '=' );
|
ucoconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( ucoconst ), 0.0 ) );
|
// Term UoM: Unit
|
ucoconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalUnitCapacityVariable ), typeofexpression( ucoconst ) )
|
, program.TotalUnitCapacityVariables().Get());
|
|
// sucoconst constraint UoM: TransportCapacity --> Please note that this means if different units have a different UoM,
|
// their UnitSecondaryCapacityOverloaded will have a different weight in the goal
|
sucoconst := program.TotalUnitSecondaryCapacityConstraints().New();
|
sucoconst.Sense( '=' );
|
sucoconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( sucoconst ), 0.0 ) );
|
// Term UoM: TransportCapacity
|
sucoconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalUnitSecondaryCapacityVariable )
|
, typeofexpression( sucoconst ) ), program.TotalUnitSecondaryCapacityVariables().Get());
|
|
// Maximum quantity
|
// maxquantityconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM,
|
// their MaxPTQtyOver will have a different weight in the goal
|
maxquantityconst := program.TotalProcessMaximumQuantityConstraints().New();
|
maxquantityconst.Sense( '=' );
|
maxquantityconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( maxquantityconst ), 0.0 ) );
|
// Term UoM: Unit
|
maxquantityconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalProcessMaximumQuantityVariable ), typeofexpression( maxquantityconst ) )
|
, program.TotalProcessMaximumQuantityVariables().Get());
|
|
scalefactor_unitcapacitynotmet_mcconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityNotMetQuantityVariable ), typeofexpression( mcconst ) );
|
scalefactor_unitcapacitynotmettime_mcconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityNotMetTimeVariable ), typeofexpression( mcconst ) );
|
scalefactor_unitcapacityoverloaded_ucoconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityOverloadedQuantityVariable ), typeofexpression( ucoconst ) );
|
scalefactor_unitcapacityoverloadedtime_ucoconst := this.ScaleConstraintTerm( typeof( MPUnitCapacityOverloadedTimeVariable ), typeofexpression( ucoconst ) );
|
|
scalefactor_unitsecondarycapacitynotmet_smcconst := this.ScaleConstraintTerm( typeof( MPUnitSecondaryCapacityNotMetVariable ), typeofexpression( smcconst ) );
|
scalefactor_unitsecondarycapacityoverloaded_sucoconst := this.ScaleConstraintTerm( typeof( MPUnitSecondaryCapacityOverloadedVariable ), typeofexpression( sucoconst ) );
|
|
unitperiods := construct( UnitPeriods, constcontent );
|
traverse( scope.GetUnitPeriodInOptimizerRunConst(), Elements, up )
|
{
|
unitperiods.Add( up );
|
parentunitperiods := up.GetAllParentsOfUnitDimension();
|
traverse( parentunitperiods, Elements, parentup )
|
{
|
unitperiods.Add( parentup );
|
}
|
}
|
|
unitperiods := unitperiods.Unique();
|
// The variables are not defined for parent units with infinite capacity
|
traverse( unitperiods, Elements, unitperiod, not ( unitperiod.Unit().HasChild() and unitperiod.Unit().HasCapacityTypeInfinite() ) )
|
{
|
// Penalty for not meeting minimum capacity
|
// Term UoM: Unit
|
coefmincap := ifexpr( unitperiod.IsTimeBasedCapacityUsage(), scalefactor_unitcapacitynotmettime_mcconst, scalefactor_unitcapacitynotmet_mcconst );
|
mcconst.NewTerm( -1.0 * coefmincap, unitperiod.GetCapacityNotMetVariable( program ) );
|
|
// Penalty for overloading the unit capacity
|
// Term UoM: Unit
|
coefmaxcap := ifexpr( unitperiod.IsTimeBasedCapacityUsage(), scalefactor_unitcapacityoverloadedtime_ucoconst, scalefactor_unitcapacityoverloaded_ucoconst);
|
coefmincapsecondary := scalefactor_unitsecondarycapacitynotmet_smcconst;
|
coefmaxcapsecondary := scalefactor_unitsecondarycapacityoverloaded_sucoconst;
|
|
ucoconst.NewTerm( -1.0 * coefmaxcap, unitperiod.GetCapacityOverloadedVariable( program ) );
|
|
processsecondary := unitperiod.istype( UnitPeriodTransportQuantity ) and unitperiod.astype( UnitPeriodTransportQuantity ).HasSecondaryCapacityDefinition();
|
if( processsecondary )
|
{
|
// Penalty for not meeting minimum secondary capacity
|
// Term UoM: TransportCapacity
|
smcconst.NewTerm( -1.0 * coefmincapsecondary, program.UnitSecondaryCapacityNotMetVariables().Get( unitperiod ) );
|
|
// Penalty for overloading the unit secondary capacity
|
// Term UoM: TransportCapacity
|
sucoconst.NewTerm( -1.0 * coefmaxcapsecondary, program.UnitSecondaryCapacityOverloadedVariables().Get( unitperiod ) );
|
}
|
|
if ( collectvaluesmodel )
|
{
|
factoroverloaded := ifexpr( unitperiod.IsTimeBasedCapacityUsage(), scalefactoroverloadedtime, scalefactoroverloaded );
|
factorunderloaded := ifexpr( unitperiod.IsTimeBasedCapacityUsage(), scalefactorunderloadedtime, scalefactorunderloadedquantity );
|
totalmaximumcapacity := totalmaximumcapacity + coefmaxcap * (unitperiod.OverloadCapacity() ) / factoroverloaded;
|
totalminimumcapacity := totalminimumcapacity + coefmincap * (unitperiod.CapacityNotMet() ) / factorunderloaded;
|
if ( processsecondary )
|
{
|
totalmaximumcapacitysecondary := totalmaximumcapacitysecondary
|
+ coefmaxcapsecondary * unitperiod.astype( UnitPeriodTransportQuantity ).SecondaryOverloadCapacity() / scalefactoroverloadedsecondary;
|
|
totalminimumcapacitysecondary := totalminimumcapacitysecondary
|
+ coefmincapsecondary * unitperiod.astype( UnitPeriodTransportQuantity ).CapacityNotMetSecondary() / scalefactor_unitsecondarycapacitynotmet_smcconst;
|
}
|
}
|
}
|
|
// workaround because cannot use attribute
|
this.StoreValueInProgram( program, 'collect_values_model_MPTotalUnitCapacityVariable', totalmaximumcapacity );
|
this.StoreValueInProgram( program, 'collect_values_model_MPTotalUnitSecondaryCapacityVariable', totalmaximumcapacitysecondary );
|
this.StoreValueInProgram( program, 'collect_values_models_MPTotalMinimumUnitCapacityVariable', totalminimumcapacity );
|
this.StoreValueInProgram( program, 'collect_values_models_MPTotalMinimumUnitSecondaryCapacityVariable', totalminimumcapacitysecondary );
|
|
|
|
// Penalty for overloading the campaign and transition time capacity
|
ismanualcampaignsequence := not runcontext.UseCampaignSequenceOptimizer()
|
if( ismanualcampaignsequence and runcontext.UseCampaign() )
|
{
|
scalefactor_campaignoverloaded_uconst := this.ScaleConstraintTerm( typeof( MPCampaignPeriodOverloadedVariable ), typeofexpression( ucoconst ) );
|
traverse( scope.GetUnitInOptimizerRunConst(), Elements.CampaignType_MP, type )
|
{
|
// Only consider this campaign if at least one of its operations is part of this optimizer run
|
traverse( type, Campaign_MP, campaign,
|
exists( campaign, OperationInCampaign.Operation, operation,
|
scope.Contains( operation.OperationInOptimizerRun() ) ) )
|
{
|
// Only consider the campaingperiod if its unit period is part of this optimizer run
|
traverse( campaign, PlanningCampaignPeriod, cp,
|
guard( scope.Contains( cp.UnitPeriod().UnitPeriodInOptimizerRun() ), false ) )
|
{
|
if ( not cp.UnitPeriod().Unit().IsPlannedInfinite() )
|
{
|
ucoconst.NewTerm( -scalefactor_campaignoverloaded_uconst, program.CampaignPeriodOverloadedVariables().Get( cp ) );
|
|
if ( collectvaluesmodel )
|
{
|
// created backlog issue 2386 for meta optimizer cmt____ := 'collect here';
|
}
|
}
|
}
|
}
|
}
|
|
scalefactor_transitionoverloaded_uconst := this.ScaleConstraintTerm( typeof( MPTransitionPeriodOverloadedVariable ), typeofexpression( ucoconst ) );
|
traverse( scope.GetUnitInOptimizerRunConst(),
|
Elements.TransitionType_MP.Transition_MP.TransitionPeriod_MP,
|
tperiod,
|
exists( tperiod, Transition_MP.OperationInTransition.OperationInTransitionType.Operation, operation, scope.Contains( operation.OperationInOptimizerRun() ) ) )
|
{
|
if ( not tperiod.UnitPeriod().Unit().IsPlannedInfinite() )
|
{
|
ucoconst.NewTerm( -scalefactor_transitionoverloaded_uconst, program.TransitionPeriodOverloadedVariables().Get( tperiod ) );
|
|
if ( collectvaluesmodel )
|
{
|
// created backlog issue 2386 for meta optimizer cmt____ := 'collect here';
|
}
|
}
|
}
|
|
// campaign + transition output
|
|
// TotalCampaignTransitionOutput = SUM[PTTransitionQtyVariables]
|
transconst := program.TotalCampaignTransitionOutputConstraints().New();
|
transconst.Sense( '=' );
|
transconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( transconst ), 0.0 ) );
|
// Term UoM: Unit
|
transconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCampaignTransitionOutputVariable ), typeofexpression( transconst ) ), program.TotalCampaignTransitionOutputVariables().Get());
|
|
traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, operation.OperationInCampaign( relsize ) + operation.OperationInTransitionType( relsize ) > 0 )
|
{
|
periods := this.GetPeriodsForOperation( scope, operation );
|
traverse( periods, Elements, period, period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) )
|
{
|
traverse( operation,
|
OperationInTransitionType.OperationInTransition,
|
oit,
|
exists( oit, Transition_MP.TransitionPeriod_MP, tperiod, tperiod.UnitPeriod().Period_MP() = period ) )
|
{
|
pttransvar := program.PTTransitionQtyVariables().Get( oit, period );
|
transconst.NewTerm( -1.0 * this.ScaleConstraintTerm( typeof( MPPTTransitionQtyVariable ), typeofexpression( transconst)), pttransvar );
|
}
|
}
|
}
|
|
// camconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM,
|
// their MinCampaignQtyUnder/MaxCampaignQtyOver will have a different weight in the goal
|
//
|
// TotalCampaignVariables = SUM[MinCampaignQtyUnderVariables] + SUM[MaxCampaignQtyOverVariables] - TotalCampaignTransitionOutputVariables
|
//
|
camconst := program.TotalCampaignConstraints().New();
|
camconst.Sense( '=' );
|
camconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( camconst ), 0.0 ) );
|
// Term UoM: Unit
|
camconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCampaignVariable ), typeofexpression( camconst ) ), program.TotalCampaignVariables().Get());
|
|
scalefactor_mincampaignqtyunder_camconst := this.ScaleConstraintTerm( typeof( MPMinCampaignQtyUnderVariable ), typeofexpression( camconst ) );
|
scalefactor_maxcampaignqtyover_camconst := this.ScaleConstraintTerm( typeof( MPMaxCampaignQtyOverVariable ), typeofexpression( camconst ) );
|
|
traverse( scope.GetUnitInOptimizerRunConst(), Elements.CampaignType_MP, type )
|
{
|
// Only consider this campaign if at least one of its operations is part of this optimizer run
|
traverse( type, Campaign_MP, campaign,
|
exists( campaign, OperationInCampaign.Operation, operation,
|
scope.Contains( operation.OperationInOptimizerRun() ) ) )
|
{
|
// Penalty for planning under the minimum quantity of campaign
|
// Term UoM: Unit
|
camconst.NewTerm( -1.0 * scalefactor_mincampaignqtyunder_camconst, program.MinCampaignQtyUnderVariables().Get( campaign ) );
|
|
// Penalty for overloading the maximum quantity of campaign
|
// Term UoM: Unit
|
camconst.NewTerm( -1.0 * scalefactor_maxcampaignqtyover_camconst, program.MaxCampaignQtyOverVariables().Get( campaign ) );
|
}
|
}
|
camconst.NewTerm( this.ScaleConstraintTerm( typeof( MPTotalCampaignTransitionOutputVariable ), typeofexpression( camconst ) ), program.TotalCampaignTransitionOutputVariables().Get() );
|
}
|
|
usemaxlotsize := runcontext.UseProcessMaximumQuantity();
|
uselotsize := runcontext.UseLotSize();
|
needlotcost := runcontext.UseLotCost();
|
|
if( usemaxlotsize or uselotsize or needlotcost )
|
{
|
// Lot size
|
// lotsizeconst constraint UoM: Unit --> Please note that this means that if different units have a different UoM,
|
// their PTLotSizeUnder and TripLotSizeUnder will have a different weight in the goal
|
|
lotsizeconst := program.TotalLotSizeConstraints().New();
|
lotsizeconst.Sense( '=' );
|
lotsizeconst.RHSValue( this.ScaleConstraintRHS( typeofexpression( lotsizeconst ), 0.0 ) );
|
// Term UoM: Unit
|
lotsizeconst.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalLotSizeVariable ), typeofexpression( lotsizeconst ) )
|
, program.TotalLotSizeVariables().Get());
|
|
scalefactor_maxptqtyover_maxquantityconst := this.ScaleConstraintTerm( typeof( MPMaxPTQtyOverVariable ), typeofexpression( maxquantityconst ) );
|
scalefactor_ptlotsizeunder_lotsizeconst := this.ScaleConstraintTerm( typeof( MPPTLotSizeUnderVariable ), typeofexpression( lotsizeconst ) );
|
scalefactor_triplotsizeunder_lotsizeconst := this.ScaleConstraintTerm( typeof( MPTripLotSizeUnderVariable ), typeofexpression( lotsizeconst ) );
|
scalefactor_operationinputlotsizeunder_inputlotsizeconst := this.ScaleConstraintTerm( typeof( MPOperationInputLotSizeUnderVariable ), typeofexpression( lotsizeconst ) );
|
scalefactor_lotsizeundervar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPPTLotSizeUnderVariable ) );
|
scalefactor_inputlotsizeundervar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPOperationInputLotSizeUnderVariable ) );
|
scalefactor_lotsizeundertripvar := CapacityPlanningSuboptimizer::GetVariableScaleFactor( typeof( MPTripLotSizeUnderVariable ) );
|
|
// Only those operations with a maximum quantity or lotsize should be considered
|
traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation,
|
operation.HasMaximumQuantity()
|
or operation.HasLotSize()
|
or operation.HasInputLotSize() )
|
{
|
periods := this.GetPeriodsForOperation( scope, operation );
|
periodsfordd := construct( Period_MPs, constcontent ); // periods for dependent demand. Only need these for the input lot sizes - so will not compute if we do not have those
|
|
traverse( periods, Elements, period )
|
{
|
pt := constnull( PeriodTaskOperation ); // for efficiency only use type index at most once in loop - but must set to null at start of each loop
|
coeffmaxprocess := scalefactor_maxptqtyover_maxquantityconst;
|
if( usemaxlotsize
|
and operation.HasMaximumQuantity() )
|
{
|
// Penalty for exceeding the maximum quantity of operation
|
// Term UoM: Unit
|
maxquantityconst.NewTerm( -1.0 * coeffmaxprocess, program.MaxPTQtyOverVariables().Get( operation, period ) );
|
|
if ( collectvaluesmodel )
|
{
|
pt := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() );
|
totalprocesssmax := totalprocesssmax + coeffmaxprocess * guard( maxvalue( operation.MinimumQuantity() - pt.Quantity(), 0.0 ), 0.0 ) / scalefactormaxptqtyover
|
}
|
}
|
|
if( ( uselotsize or needlotcost )
|
and operation.HasLotSize()
|
and period.IsWithinLotSizeHorizon() )
|
{
|
// Penalty for having additional quantity to reach the lot size multiples
|
// Term UoM: Unit
|
coefflotsizeunderterm := scalefactor_ptlotsizeunder_lotsizeconst;
|
lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.PTLotSizeUnderVariables().Get( operation, period ) );
|
lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.PTLotSizeOverVariables().Get( operation, period ) );
|
|
if ( collectvaluesmodel )
|
{
|
if ( isnull( pt ) ) // for efficiency checking if already set in this loop iteration (above call to type index)
|
{
|
pt := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() );
|
}
|
viol := pt.GetViolationLotsizeForOptimizer( this.SmallestIntegralityTolerance() );
|
totallotsize := totallotsize + coefflotsizeunderterm * viol / scalefactor_lotsizeundervar;
|
}
|
}
|
|
// Consider all relevant periods for the dependent demand
|
if ( operation.HasInputLotSize() and not this.GetPeriodsFromPeriodTaskOperation() ) //Only need periodsfordd for the input lot sizes - so will not compute if we do not have those
|
{
|
CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &periodsfordd, this.GetPeriodsFromPeriodTaskOperation() ); // membership may not be unique. Output = periodsfordd
|
}
|
} // end traverse periods
|
|
// Calculate the additional quantity required to reach a multiple of the input lot size.
|
if( ( uselotsize or needlotcost )
|
and operation.HasInputLotSize() )
|
{
|
if ( this.GetPeriodsFromPeriodTaskOperation() )
|
{
|
traverse( operation, PeriodTaskOperationInScope.DependentDemand.ProductInStockingPointInPeriodPlanningLeaf.Period_MP, ddperiod )
|
{
|
periodsfordd.Add( ddperiod ); // not using above method CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods for performance
|
}
|
}
|
|
periodsfordd := periodsfordd.Unique();
|
traverse( periodsfordd, Elements, period,
|
period.IsWithinLotSizeHorizon() )
|
{
|
traverse( operation,
|
OperationInput,
|
input,
|
input.ProductInStockingPoint_MP().HasInputLotSize()
|
and ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) ) )
|
{
|
// Penalty for having additional quantity to fulfil the input lot size multiples
|
// Term UoM: Unit
|
lotsizeconst.NewTerm( -1.0 * scalefactor_operationinputlotsizeunder_inputlotsizeconst,
|
program.OperationInputLotSizeUnderVariables().Get( input, period ) );
|
lotsizeconst.NewTerm( -1.0 * scalefactor_operationinputlotsizeunder_inputlotsizeconst,
|
program.OperationInputLotSizeOverVariables().Get( input, period ) );
|
|
if ( collectvaluesmodel )
|
{
|
inputlotsize := input.ProductInStockingPoint_MP().PISPSpecification().InputLotSize();
|
dds := selectset( input, DependentDemand, dd, true, dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP() = period );
|
quantitytotal := sum( dds, Elements, dd, true, dd.Quantity() );
|
|
requiredlot := guard( Util::Ceil( quantitytotal / inputlotsize ), 0.0 );
|
violationinput := CapacityPlanningSuboptimizer::GetLotSizeViolationForVariable( inputlotsize, requiredlot, quantitytotal, this.SmallestIntegralityTolerance() );
|
totallotsize := totallotsize + ( scalefactor_operationinputlotsizeunder_inputlotsizeconst * violationinput / scalefactor_inputlotsizeundervar );
|
}
|
}
|
}
|
}
|
}
|
|
traverse( scope.GetTripInOptimizerRun(), Elements, trip,
|
trip.DepartureUnitPeriod().Period_MP().IsWithinLotSizeHorizon() )
|
{
|
unitperiod := trip.DepartureUnitPeriod();
|
|
if( ( uselotsize or needlotcost )
|
and guard( unitperiod.HasLotSize(), false ) )
|
{
|
// Penalty for having additional quantity to reach the lot size multiples
|
// Term UoM: Unit
|
coefflotsizeunderterm := scalefactor_triplotsizeunder_lotsizeconst;
|
lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.TripLotSizeUnderVariables().Get( trip ) );
|
lotsizeconst.NewTerm( -1.0 * coefflotsizeunderterm, program.TripLotSizeOverVariables().Get( trip ) );
|
if ( collectvaluesmodel )
|
{
|
totallotsize := totallotsize + coefflotsizeunderterm * trip.GetViolationForOptimizer( this.SmallestIntegralityTolerance() ) / scalefactor_lotsizeundertripvar;
|
}
|
}
|
}
|
}
|
|
// workaround because cannot write to attribute
|
this.StoreValueInProgram( program, 'collect_values_model_TotalLotSizeVariables', totallotsize );
|
this.StoreValueInProgram( program, 'collect_values_model_TotalProcessMaximumQuantityVariables', totalprocesssmax );
|
|
// Calculate the total blending constraint violation
|
if( runcontext.UseBlending() )
|
{
|
blendingconstr := program.TotalBlendingConstraints().New();
|
blendingconstr.Sense( '=' );
|
blendingconstr.RHSValue( 0.0 );
|
|
// Term UoM: Unit
|
blendingconstr.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalBlendingVariable ), typeofexpression( blendingconstr ) )
|
, program.TotalBlendingVariables().Get());
|
|
scalefactor_blendingmaxover_blendingconstr := this.ScaleConstraintTerm( typeof( MPBlendingMaxOverVariable ), typeofexpression( blendingconstr ) );
|
scalefactor_blendingminunder_blendingconstr := this.ScaleConstraintTerm( typeof( MPBlendingMinUnderVariable ), typeofexpression( blendingconstr ) );
|
|
traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, operation.IsBlending() )
|
{
|
periods := this.GetPeriodsForOperation( scope, operation );
|
traverse( periods, Elements, period )
|
{
|
// Term UoM: Unit
|
blendingconstr.NewTerm( -1.0 * scalefactor_blendingmaxover_blendingconstr, program.BlendingMaxOverVariables().Get( operation, period ) );
|
blendingconstr.NewTerm( -1.0 * scalefactor_blendingminunder_blendingconstr, program.BlendingMinUnderVariables().Get( operation, period ) );
|
}
|
}
|
}
|
|
// Calculate the total CO2 emission
|
totalco2emissionconstr := program.TotalCO2EmissionConstraints().New();
|
totalco2emissionconstr.Sense( '=' );
|
totalco2emissionconstr.RHSValue( 0.0 );
|
|
// Term UoM: CO2
|
totalco2emissionconstr.NewTerm( 1.0 * this.ScaleConstraintTerm( typeof( MPTotalCO2EmissionVariable ), typeofexpression( totalco2emissionconstr ) )
|
, program.TotalCO2EmissionVariables().Get() );
|
|
scalefactor_ptqty_totalco2emissionconstr := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), typeofexpression( totalco2emissionconstr ) );
|
scalefactor_tripnewsupply_totalco2emissionconstr := this.ScaleConstraintTerm( typeof( MPTripNewSupplyVariable ), typeofexpression( totalco2emissionconstr ) );
|
|
co2uom := this.MacroPlan().DefaultCO2ProcessUoM();
|
|
// CO2 emission for operations
|
traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation )
|
{
|
uomconversionfactor := operation.Unit().UnitOfMeasure_MP().GetConversionFactor( co2uom, null( Product_MP ) );
|
co2emission := operation.CO2Emission();
|
coeff := uomconversionfactor * co2emission;
|
|
periods := this.GetPeriodsForOperation( scope, operation );
|
|
traverse( periods, Elements, period )
|
{
|
// Term UoM: Unit
|
totalco2emissionconstr.NewTerm( -1.0 * coeff * scalefactor_ptqty_totalco2emissionconstr, program.PTQtyVariables().Get( operation, period ) );
|
}
|
|
traverse( operation, PeriodTaskOperationInScope, periodtask )
|
{
|
totalco2emission := totalco2emission + coeff * scalefactor_ptqty_totalco2emissionconstr * periodtask.Quantity();
|
}
|
}
|
|
// CO2 emission for trips
|
traverse( pitinrun, Elements, productintrip )
|
{
|
laneleg := productintrip.Trip().LaneLeg();
|
|
uomconversionfactor := laneleg.Lane().Unit().UnitOfMeasure_MP().GetConversionFactor( co2uom, null( Product_MP ) );
|
co2emission := laneleg.CO2Emission();
|
coeff := uomconversionfactor * co2emission;
|
|
// Term UoM: Unit
|
totalco2emissionconstr.NewTerm( -1.0 * uomconversionfactor * co2emission * scalefactor_tripnewsupply_totalco2emissionconstr, program.TripNewSupplyVariables().Get( productintrip ) );
|
|
totalco2emission := totalco2emission + coeff * scalefactor_tripnewsupply_totalco2emissionconstr * productintrip.Quantity();
|
}
|
|
// workaround because cannot use attribute
|
this.StoreValueInProgram( program, 'collect_values_model_MPTotalCO2EmissionVariable', totalco2emission )
|
*]
|
InterfaceProperties { Accessibility: 'Module' }
|
}
|