yanweiyuan3
2023-08-09 588bc7829387dfc761cc25f06f77d4c81818bd10
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
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForDependentDemandsInPISPIPForShelfLife (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope,
  const constcontent ProductInStockingPoint_MPs pispsinrun
) const
{
  Description: 'Initialize the constraint to compute the total dependent demands in a pispip for shelflife, also adding a slack (if utilize, penalize high cost) to prevent infeasibility when balancing the demands and supplies'
  TextBody:
  [*
    constname := typeof( MPDependentDemandInPISPIPConstraint );
    
    scalefactor_dependentdemandinpispip_const := this.ScaleConstraintTerm( typeof( MPDependentDemandInPISPIPVariable ), constname );
    scalefactor_operationdemandqty_const := this.ScaleConstraintTerm( typeof( MPOperationDemandQtyVariable ), constname );
    scalefactor_tripdemandqty_const := this.ScaleConstraintTerm( typeof( MPTripDemandQtyVariable ), constname );
    
    scalefactor_rhs_const := this.ScaleConstraintRHS( constname, 1.0 );
    
    // To calculate the total dependent demand quantity in a pispip
    traverse( pispsinrun, Elements, pisp, pisp.IsOptMaturation() or pisp.IsOptShelfLife() ) 
    { 
      pispipsforstockingpoint_shelflifeormaturation := pisp.PISPInOptimizerRun().GetPISPIPForShelfLifeOptimizer( scope ); // included extra pispips prior to optimizer scope 
      traverse( pispipsforstockingpoint_shelflifeormaturation, Elements, pispip ) 
      { 
        traverse( pisp, OutgoingShelfLifeDay, oslday ) 
        {
          // Defining DD(pispip, oslday). Note we don't have a variable for this but we use sum_i DD(pispip, i, osld) and this is what we want to constrain
          // const constraint UoM: PISP
          const := program.DependentDemandInPISPIPShelfLifeConstraints().New( pispip, oslday );
          const.Sense( '=' );
        
          // Inventory supply that is greater than 0. If the supply is less than 0, it will be treated as a "must be fulfilled" demands. This is considered to have outgoing leadtime 0
          supplyquantity := ifexpr( pispip.InventorySupplyQuantity() < 0 and oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips(), pispip.InventorySupplyQuantity(), 0 );
        
          // RHS UoM: PISP
          const.RHSValue( supplyquantity * scalefactor_rhs_const );
          // term UoM: PISP
          traverse( pisp, IncomingShelfLifeDay, islday ) 
          {
            const.NewTerm( -1.0 * scalefactor_dependentdemandinpispip_const,
                           program.DependentDemandInPISPIPShelfLifeVariables().Get( pispip, islday, oslday ) );
          }    
          // Dependent demands for operations - considered outgoing leadtime 0. Note we distinguish between 0 outgoing leadtime for operations and trips using the attribute IsZeroShelfLifeDaysForTrips
          if ( oslday.ShelfLifeDays() = 0 and not oslday.IsZeroShelfLifeDaysForTrips() ) 
          {
            if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent to scope.Contains( pispip.PISPIPInOptimizerRun() ) ) 
            {
              ispostprocessing := runcontext.IsPostProcessing(); 
              traverse( pispip, ProductInStockingPoint_MP.OperationInputAvailableForOptimization, input,
                        guard( scope.Contains( input.Operation().OperationInOptimizerRun() ), false )
                        and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( 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 ) )
                {
                  // Term UoM: PISP
                  const.NewTerm( 1.0 * scalefactor_operationdemandqty_const, operationdemandqtyvar );
                }
              }
            }
            else // we have pispips prior to the optimizer scope where we just want to set constant values from the model  
            {
              operationdemandfulfilled := pispip.DependentDemandNonTripFulfilledQuantity(); 
              const.RHSValue( const.RHSValue() - scalefactor_rhs_const * operationdemandfulfilled ); 
            }
          }
        
          // Dependent demands for trips
          // Only consider those productintrips that are part of the optimizer run
          if ( oslday.ShelfLifeDays() > 0 or oslday.IsZeroShelfLifeDaysForTrips() )
          {
            if ( scope.Contains( pispip.PISPIPInOptimizerRun() ) ) // same transaction, equivalent scope.Contains( pispip.PISPIPInOptimizerRun() ) ) 
            {
              traverse( pispip, astype( ProductInStockingPointInPeriodPlanningLeaf ).DependentDemand.ProductInTrip, productintrip,
                        scope.Contains( productintrip.ProductInTripInOptimizerRun() ) 
                        and productintrip.Trip().GetShelfLifeAgeToAdd() = oslday.ShelfLifeDays()
                       )
              {
                // Term UoM: PISP
                const.NewTerm( 1.0 * scalefactor_tripdemandqty_const, program.TripDemandQtyVariables().Get( productintrip ) );
              }
            }
            else
            {
              ddoutgoingtrip := sum( pispip, 
                                     Demand_MP.astype( DependentDemand ), 
                                     dd, 
                                     guard( dd.ProductInTrip().Trip().GetShelfLifeAgeToAdd() = oslday.ShelfLifeDays(), false ), dd.Quantity() ); 
              const.RHSValue( const.RHSValue() - scalefactor_rhs_const * ddoutgoingtrip ); 
            }
          }
        }
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}