haorenhui
2023-10-30 6d6cc10d9e8e242661da7fd655dec155a09d676c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForCampaignPTQtyTransitionTotal (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const LibOpt_Scope scope
) const
{
  TextBody:
  [*
    totalptconstname := typeof( MPPTQtyCampaignsTotalConstraint );
    
    scalefactor_periodtaskqty_totalptconst := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), totalptconstname );
    scalefactor_PTQtyInCampaignElementTypeStart_totalptconst := this.ScaleConstraintTerm( typeof( MPPTQtyInCampaignElementTypeStartVariable ), totalptconstname );
    scalefactor_PTQtyInCampaignElementTypeMid_totalptconst := this.ScaleConstraintTerm( typeof( MPPTQtyInCampaignElementTypeMidVariable ), totalptconstname );
    scalefactor_PTQtyInCampaignElementTypeEnd_totalptconst := this.ScaleConstraintTerm( typeof( MPPTQtyInCampaignElementTypeEndVariable ), totalptconstname );
    scalefactor_PTQtyInCampaignSlack_totalptconst := this.ScaleConstraintTerm( typeof( MPPTQtyInCampaignSlackVariable ), totalptconstname );
    
    scalefactor_rhs_totalptconst := this.ScaleConstraintRHS( totalptconstname, 1.0 );
    
    nrlogged := 0; // keep upper bound on log info
    nrcreatedslackvar := 0; 
    traverse( scope.GetUnitInOptimizerRunConst(), Elements.Operation, operation,
              operation.OperationInCampaignType( relsize ) > 0 
              or operation.OperationInTransitionType( relsize ) > 0 )
    {
      // Only select those periods that are relevant for this operation for the optimizer run
      periods := this.GetPeriodsForOperation( scope, operation );
    
      traverse( periods, Elements, period,
                period.GetIsInCampaignTypeHorizonUnit( operation.Unit() ) )
      {
        // total quantity planned in different campaign (pt in campaign) and transitions ( pt in transition) must match period task quantity
        // Totalptconst constraint UoM: Unit
        totalptconst := program.PTQtyCampaignsTotalConstraints().New( operation, period );
        totalptconst.Sense( '=' );
        totalptconst.RHSValue( 0.0 * scalefactor_rhs_totalptconst );
    
        // Term UoM: Unit
        varptqty := program.PTQtyVariables().Find( operation, period ); 
        if ( not isnull( varptqty ) ) 
        {
          totalptconst.NewTerm( -1.0 * scalefactor_periodtaskqty_totalptconst, program.PTQtyVariables().Get( operation, period ) );
        }
        else
        {
          newrhsval := guard( PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() ).Quantity(), 0.0 )
          totalptconst.RHSValue( scalefactor_rhs_totalptconst * newrhsval );  
        }
        
        nrtripletermsadded := 0; 
        traverse( period, UnitPeriod.OptCampaignUnitSubPeriod, optsubperiod, guard( optsubperiod.UnitPeriod().GetIsWithinCampaignHorizonConstraint(), false ) and optsubperiod.UnitPeriod().Unit() = operation.Unit() )
        {
          traverse( optsubperiod, OptCampaignCombiElementActive.OptCampaignElementType.OptCampaignOperationInElementType, oiet, oiet.Operation() = operation ) 
          {
              totalptconst.NewTerm( 1.0 * scalefactor_PTQtyInCampaignElementTypeStart_totalptconst, program.PTQtyInCampaignElementTypeStartVariables().Get( oiet, optsubperiod ) ); 
              totalptconst.NewTerm( 1.0 * scalefactor_PTQtyInCampaignElementTypeMid_totalptconst, program.PTQtyInCampaignElementTypeMidVariables().Get( oiet, optsubperiod ) ); 
              totalptconst.NewTerm( 1.0 * scalefactor_PTQtyInCampaignElementTypeEnd_totalptconst, program.PTQtyInCampaignElementTypeEndVariables().Get( oiet, optsubperiod ) ); 
              nrtripletermsadded++; 
          }
        }
        if ( nrtripletermsadded = 0 ) // don't apply restriction on PTQty if combis subset has no coverage
        {
          pto := PeriodTaskOperation::FindPeriodTaskOperationTypeIndex( period.Start(), operation.ID() ); 
          if ( not guard( pto.Quantity() = 0, false ) )
          {
            if ( nrlogged <= 10 ) 
            {
              nrlogged++; 
              debuginfo(  'Creating pt in campaign slack var', period.Start(), operation.ID() ); 
            }
            nrcreatedslackvar++; 
            varslack := program.PTQtyInCampaignSlackVariables().New(  operation, period ); 
            totalptconst.NewTerm( 1.0 * scalefactor_PTQtyInCampaignSlack_totalptconst, varslack ); 
          }
        }
      } 
    }
    program.StoreReal( CapacityPlanningSuboptimizer::LoggedNrPTQtyCampaignSlackVarName(), [Real]nrcreatedslackvar ); 
    debuginfo(  'Nr created pt in campaign slack var:', nrcreatedslackvar );
  *]
  InterfaceProperties { Accessibility: 'Module' }
}