chenqinghong
2024-05-07 3ec06a830367465068963156dcc1d8e522571c13
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
Quintiq file version 2.0
#parent: #root
Method InitConstraintsGoalsForDriverVolume (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const LibOpt_Scope scope,
  const constcontent ProductInTrips pitinrun
) const
{
  Description: 'Init constraints goals for account depends on volume, i.e., quantity'
  TextBody:
  [*
    // Volume accounts
    ptqty_varname := typeof( MPPTQtyVariable );
    tripnewsupply_varname := typeof( MPTripNewSupplyVariable );
    drivervolume_varname := typeof( MPDriverVolumeVariable );
    drivervolume_constname := typeof( MPDriverVolumeConstraint );
    
    scalefactor_driver_dconst := this.ScaleConstraintTerm( drivervolume_varname, drivervolume_constname );
    scalefactor_periodtaskqty_dconst := this.ScaleConstraintTerm( ptqty_varname, drivervolume_constname );
    scalefactor_tripnewsupply_dconst := this.ScaleConstraintTerm( tripnewsupply_varname, drivervolume_constname );
    
    scalefactor_rhs_dconst := this.ScaleConstraintRHS( drivervolume_constname, 1.0 );
    
    driver := select( this, MacroPlan.AccountCostDriver, driver, driver.Name() = Translations::MP_AccountAssignmentCostDriverVolume() ); // unique
    
    if ( this.GetPeriodsFromPeriodTaskOperation() ) 
    {
      traverse( scope.GetAccountsInOptimizerRunConst(), Elements, account, account.HasVolumeAssignment() ) // condition => driver not null
      {
        // dcconst constraint UoM: Monetary
        dcconst := program.DriverVolumeConstraints().New( account, driver );
        dcconst.Sense( '=' );
        dcconst.RHSValue( 0.0 * scalefactor_rhs_dconst );
        // Term UoM: Monetary
        dcconst.NewTerm( 1.0 * scalefactor_driver_dconst, program.DriverVolumeVariables().Get( account, driver ) );
      }
      
      traverse( scope.GetPeriodTaskOperationInOptimizerRunConst(), Elements, pto ) 
      {
        up := pto.UnitPeriod(); 
        operation := pto.Operation(); 
        period := up.Period_MP(); 
        traverse( up, UnitAccountInPeriodForVolume.UnitAccount, aa, aa.AccountCost( relsize ) > 0 ) 
        {
            dcconst := program.DriverVolumeConstraints().Get( aa.Account_MP(), aa.AccountCostDriver() ); 
            cost := operation.GetBaseCostPerQuantityForVolume( aa, up );
            ptqtyvar := program.PTQtyVariables().Get( operation, period );
            
            dcconst.NewTerm( -cost * operation.QuantityToProcessFactor() * scalefactor_periodtaskqty_dconst,
                                 ptqtyvar );
        }
      }
    }
    else
    {
      traverse( scope.GetAccountsInOptimizerRunConst(), Elements, account, account.HasVolumeAssignment() ) // condition => driver not null
      {
        // dcconst constraint UoM: Monetary
        dcconst := program.DriverVolumeConstraints().New( account, driver );
        dcconst.Sense( '=' );
        dcconst.RHSValue( 0.0 * scalefactor_rhs_dconst );
        // Term UoM: Monetary
        dcconst.NewTerm( 1.0 * scalefactor_driver_dconst, program.DriverVolumeVariables().Get( account, driver ) );
      
        traverse( account, AccountAssignment, aa, aa.AccountCostDriver() = driver and aa.AccountCost( relsize ) > 0  )
        {
          // Operation (only include those that are part of this optimizer run and related to a unit period that is part of this optimizer run)
          traverse( aa, astype( UnitAccount ).UnitAccountInPeriodForVolume.UnitPeriod, up,
                    scope.Contains( up.UnitPeriodInOptimizerRun() ) )
          {
            traverse( up, Unit.OperationForOptimizationInScope, operation) 
            {
              cost := operation.GetBaseCostPerQuantityForVolume( aa, up );
              ptqtyvar := program.PTQtyVariables().Find( operation, up.Period_MP() );
              // If the period task quantity variable does not exist, then this combination of period and operation is not considered by the optimizer
              if( not isnull( ptqtyvar ) )
              {
                // Term:      -cost      * qtpfactor * PTQty variable
                // UoM:  [Monetary/Unit] *    [-]    *    [Unit]
                dcconst.NewTerm( -cost * operation.QuantityToProcessFactor() * scalefactor_periodtaskqty_dconst,
                                 ptqtyvar );
              }
            }
          }
        }
      }
    }
    
    traverse( pitinrun, Elements, pit ) 
    {
      trip := pit.Trip(); 
      laneleg := trip.LaneLeg(); 
      uomconversion := pit.UnitConversionFactor();
      traverse( pit, Trip.ArrivalUnitPeriod.UnitAccountInPeriodForVolume.UnitAccount, aa ) 
      {
        cost := laneleg.GetBaseCostPerQuantityForVolume( aa, trip.DepartureUnitPeriod() );
        tripnewsupplyvar := program.TripNewSupplyVariables().Get( pit );
        dcconst := program.DriverVolumeConstraints().Get( aa.Account_MP(), aa.AccountCostDriver() );
        
        dcconst.NewTerm( -uomconversion * cost * laneleg.QuantityToProcessFactor() * scalefactor_tripnewsupply_dconst,
                               tripnewsupplyvar );
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}