admin
2025-01-22 7e31442f0e9b07764e9c6a9680d3d4aeba5fe1de
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
Quintiq file version 2.0
#parent: #root
Method InitConstraintsForOperationDependentDemands (
  CapacityPlanningSuboptimizer_CapacityPlanningAlgorithm program,
  const RunContextForCapacityPlanning runcontext,
  const LibOpt_Scope scope,
  Number threadnr
) const
{
  Description: 'Initialize constraints for dependent demands for operations which does not have an input group'
  TextBody:
  [*
    // dependent demand quantity of input products = pt quantity * factor * relative duration.
    // relative duration = 1 if there is no pre-processing.
    // 0 < relative duration <= 1 if there is pre-processing.
    
    constddqtyname := typeof( MPOperationDependentDemandQtyConstraint );
    constddpartialname := typeof( MPPartialOperationDependentDemandQtyConstraint );
    
    scalefactor_operationdemandqty_constddqty := this.ScaleConstraintTerm( typeof( MPOperationDemandQtyVariable ), constddqtyname );
    scalefactor_periodtask_constddqty := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), constddqtyname );
    
    scalefactor_partialoperationdemandqty_constddpartial := this.ScaleConstraintTerm( typeof( MPPartialOperationDemandQtyVariable ), constddpartialname );
    scalefactor_periodtask_constddpartial := this.ScaleConstraintTerm( typeof( MPPTQtyVariable ), constddpartialname );
    
    usingproportialleadtimelogic := this.MacroPlan().GlobalParameters_MP().OperationLeadTimeLogic() = Translations::MP_GlobalParameter_LeadTimeLogic_Proportional()
    
    traverse( scope.GetOperationInOptimizerRunConst(), Elements, operation, CapacityPlanningSuboptimizer::GetThreadNr( this.ThreadAParameter(), this.ThreadBParameter(), operation.PreThreadNr() ) = threadnr )
    {
      if ( operation.HasLeadTime() and this.GetPeriodsFromPeriodTaskOperation() ) 
      {
        traverse( operation, PeriodTaskOperationInScope.DependentDemand, dd ) 
        {
          input := dd.ProcessInput().astype( OperationInput ); 
          ddperiod := dd.ProductInStockingPointInPeriodPlanningLeaf().Period_MP();  
          
          if ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )
          {
            pispipperiods := construct(  Period_MPs, constcontent ); 
            pispipperiods.Add( ddperiod ); 
            scaling := guard( input.Operation().OutputQuantity(), 1.0 ); // multiply out the denominator of OperationInput.Factor for better scaling
            if ( scaling = 0.0 ) 
            {
              scaling := 1.0; 
            }
          
            depdemandqty := PeriodTaskOperation::GetDependentDemandQuantity( 1.0, input, 1.0 /* relative duration param */); 
    
            coef_relduration_partialcase := depdemandqty                                    // in order to become PeriodTaskOperation::GetDependentDemandQuantity( 1.0, input, relativeduration ) - we multiply out the relative duration below
                                          * scalefactor_periodtask_constddpartial * scaling // (done for efficiency)
                                          
            this.InitConstraintsForOperationDependentDemands_Add( program, 
                                                                      runcontext, 
                                                                      scope, 
                                                                      input, 
                                                                      dd.PeriodTask_MP().UnitPeriod().Period_MP(), 
                                                                      pispipperiods, 
                                                                      usingproportialleadtimelogic, 
                                                                      scalefactor_partialoperationdemandqty_constddpartial, 
                                                                      scaling, 
                                                                      coef_relduration_partialcase );                                       
          }
        }
      }
      else
      {
        periods := this.GetPeriodsForOperation( scope, operation ); // these are period task periods
        
        // Only select the input where the product is included.
        traverse( operation, OperationInput, input,
                  not input.IsElementOfInputGroup()
                  and ( input.HasRegularProductforOptimizer() or input.GetIsProductInOptimizerRun( runcontext.IsPostProcessing() ) )  )
        {
          scaling := guard( input.Operation().OutputQuantity(), 1.0 ); // multiply out the denominator of OperationInput.Factor for better scaling
          if ( scaling = 0.0 ) 
          {
            scaling := 1.0; 
          }
          
          depdemandqty := PeriodTaskOperation::GetDependentDemandQuantity( 1.0, input, 1.0 /* relative duration param */); 
          coef_relduration_norelative := depdemandqty        // used for case relative duration = 1.
                                         * scalefactor_periodtask_constddqty * scaling; 
                                
          coef_relduration_partialcase := depdemandqty                                    // in order to become PeriodTaskOperation::GetDependentDemandQuantity( 1.0, input, relativeduration ) - we multiply out the relative duration below
                                        * scalefactor_periodtask_constddpartial * scaling // (done for efficiency)
            
          traverse( periods, Elements, period )
          {
            if( operation.HasLeadTime() )
            // The dependent demand has to takes relative duration of the pispip period (the bucket it belongs) and the pt period into account.
            {
              if ( not this.GetPeriodsFromPeriodTaskOperation() ) 
              {
                // To get the period of period tasks from dependent demands, it can be treated as "new supplies" of dependent demands.
                // Please read the optimizer solution design for more information.
                pispipperiods := construct( Period_MPs, constcontent );
                CapacityPlanningSuboptimizer::GetOperationDependentDemandPeriods( period, operation, &pispipperiods, this.GetPeriodsFromPeriodTaskOperation() );
        
                this.InitConstraintsForOperationDependentDemands_Add( program, 
                                                                      runcontext, 
                                                                      scope, 
                                                                      input, 
                                                                      period, 
                                                                      pispipperiods, 
                                                                      usingproportialleadtimelogic, 
                                                                      scalefactor_partialoperationdemandqty_constddpartial, 
                                                                      scaling , 
                                                                      coef_relduration_partialcase ); 
              }                                                          
            } // end if has lead time
            else
            {
              // constddqty constraint UoM: input PISP
              constddqty := program.OperationDependentDemandQtyConstraints().New( input, period );
              constddqty.Sense( '=' );
              // using default 0.0 RHS for constrddqty 
              
              // Term UoM: input PISP
              constddqty.NewTerm( -1.0 * scalefactor_operationdemandqty_constddqty * scaling, program.OperationDemandQtyVariables().Get( input, period ) );
          
              // Term: dependentdemandqty * PTQty variable
              // UoM:  [Unit to input PISP] *   [Unit]
      
                      
              constddqty.NewTerm( coef_relduration_norelative, program.PTQtyVariables().Get( operation, period ) );
            }
          }
        }
      }
    }
  *]
  InterfaceProperties { Accessibility: 'Module' }
}