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
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForDependentDemandsInPISPIP (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope,
  const constcontent ProductInStockingPointInPeriodPlanningLeafs leafpispipsinrun,
  const constcontent ProductInTrips pitinrun,
  Number threadnr
) const
{
  Description: 'Initialize the constraint to compute the total dependent demands in a pispip, 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 );
    ispostprocessing := runcontext.IsPostProcessing(); 
    
    getperiodsfromptop := this.GetPeriodsFromPeriodTaskOperation(); 
    
    // To calculate the total dependent demand quantity in a pispip
    traverse( leafpispipsinrun, Elements, pispip, CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr  )
    {
      // const constraint UoM: PISP
      const := program.DependentDemandInPISPIPConstraints().New( pispip );
      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
      supplyquantity := ifexpr( pispip.InventorySupplyQuantity() < 0, pispip.InventorySupplyQuantity(), 0 );
    
      // RHS UoM: PISP
      const.RHSValue( supplyquantity * scalefactor_rhs_const );
      // term UoM: PISP
      const.NewTerm( -1.0 * scalefactor_dependentdemandinpispip_const,
                     program.DependentDemandInPISPIPVariables().Get( pispip ) );
    
      
      // Dependent demands for operations
      if ( not getperiodsfromptop ) // for performance if we know periodtasks are there we can traverse those and add to the constraints
      {
        period := pispip.Period_MP(); 
        traverse( pispip, ProductInStockingPoint_MP.OperationInputAvailableForOptimization, input,
                  scope.Contains( input.Operation().OperationInOptimizerRun() ) 
                  and input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( ispostprocessing ) )
        {
          operationdemandqtyvar := program.OperationDemandQtyVariables().Find( input, period )
          // 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( scalefactor_operationdemandqty_const, operationdemandqtyvar );
          }
        }
      }
    }
    
    if ( getperiodsfromptop ) 
    {
      traverse(  scope.GetPeriodTaskOperationInOptimizerRunConst(), Elements.DependentDemand, dd ) 
      {
        pispip := dd.ProductInStockingPointInPeriodPlanningLeaf(); 
        if ( CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr  ) 
        {
          input := dd.ProcessInput().astype( OperationInput ); 
          if ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( ispostprocessing ) )
          {
            period := pispip.Period_MP(); 
            operationdemandqtyvar := program.OperationDemandQtyVariables().Get( input, period )
            {
              const := program.DependentDemandInPISPIPConstraints().Get( pispip );
              // Term UoM: PISP
              if ( const.Term( operationdemandqtyvar ).Coefficient() = 0 ) 
              {
                const.NewTerm( scalefactor_operationdemandqty_const, operationdemandqtyvar );
              } 
            }
          }
        }
      }    
    }
    
    traverse( pitinrun, Elements, pit ) 
    {
      pispip := pit.DeparturePISPIP(); 
      if ( CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), pispip.PreThreadNr() ) = threadnr ) 
      {
        const := program.DependentDemandInPISPIPConstraints().Get( pispip );
        const.NewTerm( scalefactor_tripdemandqty_const, program.TripDemandQtyVariables().Get( pit ) );
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}