Virtual U.org
Get Personal Training on VU Today
    
Top shadow
 
 register/help
User Name:

Password:

Ofinance.cpp Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

Ofinance.cpp

Go to the documentation of this file.
00001 //Filename    : OFINANCE.CPP
00002 //Description : School class
00003 //Owner       : Fred
00004 
00005 #include <OMATH.H>
00006 #include <OSYS.H>
00007 #include <OGAMESET.H>
00008 
00009 #include <OSCHLRES.H>
00010 #include <OPEERSCH.H>                             // for init_data
00011 #include <OSTUDENT.H>                             // MAX_STUDENT_LEVEL
00012 #include <ODEPT.H>                                // facutly_count
00013 #include <OCHANCE.H>
00014 
00015 // CU header file
00016 #include <OPSCHOOL.H>
00017 #include <OINVEST.H>
00018 #include <OATHLETI.H>
00019 #include <OFACILIT.H>
00020 #include <ODEVELOP.H>                             //990608
00021 #include <OOPT.H>
00022 
00023 #include <OLinAlg.h>                              // for its quadratic_prog() and class Matrix
00024 #if(GAME_VERSION>=200)
00025 #include <OQUADPRG.H>
00026 #endif
00027 #include <OFINANCE.H>
00028 #include <OCHANCE.H>                              //## chea 230699
00029 
00030 #include <OSTUOFF.H>
00031 #include <OLIBTECH.H>
00032 
00033 #ifdef DEBUG
00034 //#define _DEBUG_STAGE1
00035 //#define _DEBUG_STAGE2
00036 #endif
00037 
00038 #define DEBUG_VC
00039 #ifdef DEBUG_VC
00040 #include <STDIO.H>                                //temp for debug matrix
00041 #endif
00042 #include <OLOG.H>                                 // for debug matrix
00043 
00044 // --------- "Input from elsewhere in the model" --------- //
00045 //TO make these all to member variables or macro
00046 
00047 /*
00048 X       faculty_ftes = 320;
00049   avg_faculty_compensation = $268
00050   Indirect cost rate    50.0%
00051   spons_research_for_AY_fac_sals = 20;
00052   percent_of_sponsored_research_for_other_salaries = 40.00;
00053 
00054 X       tuition_rate = 18260;
00055 X       Room and board rate     $6,583
00056 X       Real growth of room & board rate        0.00%
00057   New building construction     $0
00058 New debt        $20,000
00059 */
00060 //const int     faculty_ftes = 230;                                     // for stage2
00061 //const int     avg_faculty_compensation = 268; // for stage2; from resalloc.ex file: "This is an unrealisticly large number, caused by an inconsistency between the financial data used for testing this partof the model and the assumed bumber of faculty. Setting initial conditions from the game's database should take care of the problem."
00062 const int percent_spons_research_for_AY_fac = 20; // c61
00063 // c62; for buget_report
00064 const float percent_of_sponsored_research_for_other_salaries = 40.00;
00065 
00066 // constants for buget_revenue/expense
00067 //const int     library_acqs = 3780;
00068 //const int     utilities_expense       = 3285;
00069 
00070 //---------- Begin of static function prt_vector -----------//
00071 static void print_vector(const ColumnVector &xNames) {
00072 #ifdef DEBUG_VC
00073     char s[300];
00074     sprintf(s, "%f, %f, %f, %f, %f, %f, %f, %f, %f",
00075             xNames(1),xNames(2),xNames(3),
00076             xNames(4),xNames(5),xNames(6),
00077             xNames(7),xNames(8),xNames(9));
00078     DEBUG_LOG(s);
00079 #endif
00080 }
00081 
00082 static void print_vector2(const ColumnVector &xNames) {
00083 #ifdef DEBUG_VC
00084     int count = xNames.Storage();
00085     char t[30];
00086 
00087     String s = "-> ";
00088     for (int i=1; i<=count; i++ ) {
00089         sprintf(t, "%.3f, ", xNames(i));
00090         s+= t;
00091     }
00092     DEBUG_LOG(s);
00093 #endif
00094 }
00095 
00096 //---------- Begin of static function prt_vector -----------//
00097 
00098 //---------- Begin of function FinancePolicy::bound_correction -----------//
00099 void FinancePolicy::bound_correction() {
00100     err_when(lower_limit > upper_limit);
00101 
00102     if (lower_bound > upper_bound)
00103         lower_bound = upper_bound;
00104 
00105     lower_bound = min(upper_limit, max(lower_bound, lower_limit));
00106     upper_bound = max(lower_limit, min(upper_bound, upper_limit));
00107 
00108     target_value = min(upper_bound, max(lower_bound, target_value));
00109     result_value = min(upper_bound, max(lower_bound, result_value));
00110 }
00111 
00112 //---------- End of function FinancePolicy::bound_correction -----------//
00113 
00114 //---------- Begin of function FinancePolicy::constraint_policy -----------//
00118 void FinancePolicy::set_constraint_policy(int saveLast) {
00119     if( saveLast ) {
00120         last_target_value = target_value;
00121         last_upper_bound  = upper_bound;
00122         last_lower_bound  = lower_bound;
00123     }
00124 
00125     lower_bound = min(upper_limit,max(lower_limit, target_value - OPT_MINIMUM_RANGE ));
00126     upper_bound = max(lower_limit, min(upper_limit, target_value + OPT_MINIMUM_RANGE ));
00127 
00128     target_value = min( max(target_value , lower_bound), upper_bound);
00129     bound_correction();                             // ## 290699  //## chea 310899 try not using all the bound_correction
00130 }
00131 
00132 void FinancePolicy::reset_constraint_policy() {
00133     target_value = last_target_value;
00134     upper_bound  = last_upper_bound;
00135     lower_bound  = last_lower_bound;
00136 
00137     target_value = min( max(target_value , lower_bound), upper_bound);
00138     bound_correction();                             // ## 290699 //## chea 310899 try not using all the bound_correction
00139 }
00140 
00141 //---------- End of function FinancePolicy::constraint_policy -----------//
00142 
00143 //---------- Begin of function FinancePolicy::reset_change -----------//
00145 void FinancePolicy::reset_change(bool resetAll) {
00146     //------- restore settings before Consider, Promise or Implement Now ---//
00147 
00148     if ( applied_flag > P_NONE ) {
00149         target_value = last_target_value ;
00150         upper_bound  = last_upper_bound;
00151         lower_bound  = last_lower_bound;
00152         import_weight = last_import_weight;
00153         required_flag = last_required_flag;
00154     }
00155 
00156     applied_flag = P_NONE;
00157 
00158     //-------- reset penality ---------//
00159 
00160     if ( resetAll ) {
00161         penalty_multiplier1 = 1;
00162         penalty_multiplier2 = 1;
00163     }
00164 }
00165 
00166 //---------- End of function FinancePolicy::reset_change -----------//
00167 
00168 //---------- Begin of function FinancePolicy::set_policy_target -----------//
00170 void Finance::set_policy_target(bool isRevenue, char index) {
00171     FinancePolicy& policyP = isRevenue ? revenue_policy_array[index] : expense_policy_array[index];
00172 
00173     double targetArr[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT] = {
00174         1.5, 1.5, 0, ( policyP.upper_bound + policyP.lower_bound ) / 2,
00175         1.0, 1.0, 0, 0, 0,
00176     };
00177 
00178     policyP.target_value = targetArr[isRevenue?index:index+REVENUE_POLICY_COUNT];
00179 }
00180 
00181 //---------- End of function FinancePolicy::set_policy_target -----------//
00182 
00183 #if(GAME_VERSION>=200)
00184 
00186 struct Revenue_and_Expense {
00187     double Surplus_Deficit;
00188     double Tuition_Rate;
00189     double Revenue_Array[REVENUE_ITEM_COUNT][4];    // max accessed [5][3] /[][1]=direct, [][2]=indirect, [][3]=total
00190     double Expense_Array[EXPENSE_ITEM_COUNT][4];    // max accessed [12][3] / [][0]=faculty [][1]=staff [][2]=other [][3]=total
00191 
00192     double calc_Surplus_Deficit() {
00193         int i;
00194         Revenue_Array[AC_NET_TUITION_INCOME][3] = 0.0f;
00195         for( i = 0; i < AC_NET_TUITION_INCOME; ++i )
00196             Revenue_Array[AC_NET_TUITION_INCOME][3] += Revenue_Array[i][3];
00197         Surplus_Deficit = 0.0f;
00198         for( i = AC_NET_TUITION_INCOME; i < REVENUE_ITEM_COUNT; ++i )
00199             Surplus_Deficit += Revenue_Array[i][3];
00200         for( i = 0; i < EXPENSE_ITEM_COUNT; ++i )
00201             Surplus_Deficit -= Expense_Array[i][3];
00202         return Surplus_Deficit;
00203     }
00204 };
00205 
00206 static void Optimize_policy_ver2(
00207 // output
00208     Revenue_and_Expense &Trial_Budget,
00209     Revenue_and_Expense &Final_Budget,
00210     // result of stage 1
00211     float Result_Vector_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT],
00212     float Result_Vector_S2[COST_RISE_POLICY_COUNT],   // result of stage 2
00213 // input
00214     int endStage,                                     // finish in stage 1 or stage 2
00215     const Revenue_and_Expense &Base_Budget,           // Base_Budget is projected actual on 1st Aug
00216     const Revenue_and_Expense &Base_Actual,           // Base_Actual is actual at year end
00217     // PL_Policy_Array_S1 is slider in stage 1 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00218     const float PL_Policy_Array_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][4],
00219     // PL_Policy_Array_S2 is slider in stage 2 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00220     const float PL_Policy_Array_S2[COST_RISE_POLICY_COUNT][4],
00221 
00222     double inflation, double Base_tuition_rate, double Base_enrollment, double Target_enrollment,
00223     double Actual_enrollment, double Base_endowmentMV, double Base_OpResBalance, float ST_int_rate_01Aug,
00224     float ST_int_rate_31Aug, double New_Debt_service );
00225 
00226 static void Calc_Budget( Revenue_and_Expense &Budget_Obj, float *Policy_Vector_S1, float *Policy_Vector_S2,
00227                          const Revenue_and_Expense &Base_Budget,
00228                          double New_State_approp, double inflation, double Base_tuition_rate, double Target_enrollment,
00229                          double Base_endowmentMV, double Base_OpResBalance, double ST_int_rate_01Aug, double New_Debt_service );
00230 static void Write_Budget( Revenue_and_Expense &, int, int );
00231 static void Calc_Matrices_S1( double trial_Surplus_Deficit, ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b,
00232                               const float PL_Policy_Array_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][4],
00233                               const Revenue_and_Expense &Base_Budget, double Base_tuition_rate, double Target_enrollment,
00234                               double Base_endowmentMV, double inflation );
00235 static void quadratic_prog( ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b, ColumnVector &xNames, int );
00236 static void Calc_Matrices_S2( double dollar_Constraint, ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b,
00237                               const Revenue_and_Expense &Base_Budget,
00238                               const float PL_Policy_Array_S2[COST_RISE_POLICY_COUNT][4] );
00239 static void Calc_Actual( Revenue_and_Expense &Actual_Obj, const Revenue_and_Expense &Budget_Obj,
00240                          const Revenue_and_Expense &Base_Actual, double Actual_fac_salaries_31Aug, double ST_int_rate_31Aug, double Actual_enrollment,
00241                          double Base_OpResBalance );
00242 
00243 static void Optimize_policy_ver2(
00244 // output
00245     Revenue_and_Expense &Trial_Budget,
00246     Revenue_and_Expense &Final_Budget,
00247     // result of stage 1
00248     float Result_Vector_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT],
00249     float Result_Vector_S2[COST_RISE_POLICY_COUNT],   // result of stage 2
00250 
00251 // input
00252     int endStage,                                     // finish in stage 1 or stage 2
00253 
00254     const Revenue_and_Expense &Base_Budget,           // Base_Budget is projected actual on 1st Aug
00255     const Revenue_and_Expense &Base_Actual,           // Base_Actual is actual at year end
00256     // PL_Policy_Array_S1 is slider in stage 1 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00257     const float PL_Policy_Array_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][4],
00258     // PL_Policy_Array_S2 is slider in stage 2 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00259     const float PL_Policy_Array_S2[COST_RISE_POLICY_COUNT][4],
00260 
00261     double inflation,
00262     double Base_tuition_rate,                         // Tuition rate (eg, 4,000)
00263     double Base_enrollment,                           // Total number of students at the start of the year (eg 5,000)
00264     double Target_enrollment,                         // Sum of enrollment targets for the coming year + number of doctoral students at start of year (eg,5,200)
00265     double Actual_enrollment,                         // Actual number of student enrollments after the admissions process (eg.5,100)
00266     double Base_endowmentMV,                          // Endowment plus quasi endowment market value as of August 1; smoothed (eg, 220,000)
00267     double Base_OpResBalance,                         // Operating reserve balance as of August 1 (eg, 21,000)
00268     float ST_int_rate_01Aug,                          // Short-term interest rate as of August 1
00269     float ST_int_rate_31Aug,                          // short-term interest rate as of August 31
00270     double New_Debt_service                           // Debt service projected for next year (4,500)
00271     ) {
00272     int i;
00273     Revenue_and_Expense   S1_Output_Budget, New_Actual;
00274 
00275     double Real_Budget_Growth_Dollars;
00276     // state appropriation
00277     double New_State_approp = Base_Budget.Revenue_Array[AC_STATE_APPROPRIATION][3];
00278     double Actual_fac_salaries_31Aug = 0.0f;        // Total salaries of faculty sims, including new hires (assumes player changes hiring slider)
00279     // in spreadsheet, Bill use the formula :
00280     // (Sum(i) Base_Budget.Expense_Array[i][0])
00281     // * (1+ PL_Policy_Array_S1[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES][0]
00282     //   + PL_Policy_Array_S2[PL_FACULTY_FTE][0] + 0.01 )
00283     for( i = 0; i < EXPENSE_ITEM_COUNT; ++i )
00284         Actual_fac_salaries_31Aug += Base_Budget.Expense_Array[i][0];
00285     Actual_fac_salaries_31Aug *= (1.0 + PL_Policy_Array_S1[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES][0]
00286                                   + PL_Policy_Array_S2[PL_FACULTY_FTE][0] + 0.01 );
00287 
00288     // Create temporary results vectors to get the stage 1 trial budget
00289     for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i )
00290         // stage 1 allocations equal player input
00291         Result_Vector_S1[i] = PL_Policy_Array_S1[i][0];
00292 
00293     // Create temporary results vectors to get the stage 1 trial budget
00294     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i )
00295         // stage 2 allocations all equal the planned real budget growth
00296         Result_Vector_S2[i] = PL_Policy_Array_S1[REVENUE_POLICY_COUNT+PL_BUDGET_ADJUSTMENT][0];
00297 
00298     // instantiate the trial budget class object; calculate and write the data
00299     // Set Trial_Budget = New Revenue_and_Expense; // ?
00300     Calc_Budget( Trial_Budget, Result_Vector_S1, Result_Vector_S2,
00301                  Base_Budget, New_State_approp, inflation, Base_tuition_rate, Target_enrollment,
00302                  Base_endowmentMV, Base_OpResBalance, ST_int_rate_01Aug, New_Debt_service );
00303 
00304     // DEBUG OUTPUT
00305     Write_Budget( Trial_Budget, 76, 3 ); {
00306 
00307         ColumnVector c(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT);
00308         DiagonalMatrix Q(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT);
00309         Matrix A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2,REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT);
00310         ColumnVector b((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2);
00311 
00312         // row x column
00313 
00314         ColumnVector xNames(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT);
00315 
00316         // Calculate S1 input matrices, do the S1 optimization, and update the S1 result vector
00317         Calc_Matrices_S1( Trial_Budget.Surplus_Deficit, c, Q, A, b,
00318                           PL_Policy_Array_S1, Base_Budget,
00319                           Base_tuition_rate, Target_enrollment, Base_endowmentMV, inflation );
00320 
00321         quadratic_prog( c, Q, A, b, xNames, 100);
00322 
00323         // Create temporary results vectors to get the Stage 1 output budget
00324         for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00325             Result_Vector_S1[i] = (float)xNames(i+1);   // start from xNames(1)
00326         }
00327 
00328         // get the sum of last constraints
00329         float cSum = 0.0f;
00330         for( i = 1; i <= REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00331             cSum += xNames(i) * A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1, i );
00332         }
00333         // compare with b((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2)
00334 
00335         // calc the value to minimize Qx^2 + cx
00336         float wSum = 0.0f;
00337         for( i = 1; i <= REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00338             wSum += (Q(i) * xNames(i) + c(i)) * xNames(i);
00339         }
00340 
00341         // use another method to do optimization
00342 
00343         double Alt_Result_Vector_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00344         double lowLimit[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00345         double highLimit[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00346         double tolLimit[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00347         double limitCoeff[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00348         double limitSum;
00349         double cost1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00350         double cost2[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00351         for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00352             lowLimit[i] = PL_Policy_Array_S1[i][1];
00353             highLimit[i] = PL_Policy_Array_S1[i][2];
00354             tolLimit[i] = 0.0005;                       // except PL_ENDOWMENT_SPENDING_RATE, PL_INDIRECT_COST_RATE
00355             limitCoeff[i] = A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1, i+1 );
00356             cost1[i] = c(i+1);
00357             cost2[i] = Q(i+1);
00358         }
00359         limitSum = b((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1);
00360         tolLimit[PL_ENDOWMENT_SPENDING_RATE] = 0.001;
00361         tolLimit[PL_INDIRECT_COST_RATE] = 0.005;
00362         // give bigger error tol on surplus/deficit
00363         tolLimit[REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT] = 0.001;
00364 
00365         QuadProgramming quadProg;
00366 
00367         if( quadProg.sp_quadratic_programming( REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT,
00368                                                Alt_Result_Vector_S1,
00369                                                lowLimit, highLimit, tolLimit, limitCoeff, limitSum, cost1, cost2 ) ) {
00370             // calc how good confront to constraint
00371 
00372             double cSum2 = 0.0;
00373             for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i )
00374                 cSum2 += limitCoeff[i] * Alt_Result_Vector_S1[i];
00375             // now compare cSum2 with limitSum
00376 
00377             double wSum2 = 0.0f;
00378             for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00379                 wSum2 += (cost2[i] * Alt_Result_Vector_S1[i] + cost1[i]) * Alt_Result_Vector_S1[i];
00380             }
00381 
00382             // now compare wSum2 with wSum
00383             if( wSum2 < wSum ) {
00384                 // better solution
00385 
00386                 for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00387                     Result_Vector_S1[i] = Alt_Result_Vector_S1[i];
00388                 }
00389             }
00390         }
00391     }
00392 
00393     // DEBUG OUTPUT
00394     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00395         Result_Vector_S2[i] = Result_Vector_S1[REVENUE_POLICY_COUNT+PL_BUDGET_ADJUSTMENT];
00396     }
00397 
00398     // Set S1_Output_Budget = new Revenue_and_Expense
00399     Calc_Budget( S1_Output_Budget, Result_Vector_S1, Result_Vector_S2,
00400                  Base_Budget, New_State_approp, inflation, Base_tuition_rate, Target_enrollment,
00401                  Base_endowmentMV, Base_OpResBalance, ST_int_rate_01Aug, New_Debt_service );
00402     Write_Budget( S1_Output_Budget, 76, 8 );
00403 
00404   // find Base_Budget OperatingCost
00405     double Base_Budget_OperatingCost = 0.0f;
00406     for( i = 0; i < OPERATING_EXPENSE_ITEM_COUNT; ++i )
00407         Base_Budget_OperatingCost += Base_Budget.Expense_Array[i][3];
00408 
00409   // stage 1 finish
00410 
00411     if( endStage <= 1 )
00412         return;
00413 
00414   // Calculate S2 input matrices, do the S2 optimization, l and update the S2 result vector
00415     Real_Budget_Growth_Dollars = Result_Vector_S1[REVENUE_POLICY_COUNT+PL_BUDGET_ADJUSTMENT]
00416         * (Base_Budget_OperatingCost - Base_Budget.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][3]); {
00417 
00418         ColumnVector c(COST_RISE_POLICY_COUNT);
00419         DiagonalMatrix Q(COST_RISE_POLICY_COUNT);
00420         Matrix A(COST_RISE_POLICY_COUNT*2+2,COST_RISE_POLICY_COUNT);
00421         ColumnVector b(COST_RISE_POLICY_COUNT*2+2);
00422 
00423         ColumnVector xNames(COST_RISE_POLICY_COUNT);
00424 
00425         // Real_Budget_Growth_Dollars = (budget growth % from S1) * (total base operating expenditures - spons res)
00426         Calc_Matrices_S2( Real_Budget_Growth_Dollars, c, Q, A, b,
00427                           Base_Budget, PL_Policy_Array_S2 );
00428 
00429         quadratic_prog( c, Q, A, b, xNames, 100 );
00430 
00431         for( i = 0; i < COST_RISE_POLICY_COUNT; ++i )
00432             Result_Vector_S2[i] = (float)xNames(i+1);   // start from xNames(1)
00433 
00434         // get the sum of last constraints
00435         float cSum = 0.0f;
00436         for( i = 1; i <= COST_RISE_POLICY_COUNT; ++i ) {
00437             cSum += xNames(i) * A(COST_RISE_POLICY_COUNT*2+1, i );
00438         }
00439         // compare with b(COST_RISE_POLICY_COUNT*2+2)
00440 
00441         // calc the value to minimize Qx^2 + cx
00442         float wSum = 0.0f;
00443         for( i = 1; i <= COST_RISE_POLICY_COUNT; ++i ) {
00444             wSum += (Q(i) * xNames(i) + c(i)) * xNames(i);
00445         }
00446 
00447         // use another method to do optimization
00448 
00449         double Alt_Result_Vector_S2[COST_RISE_POLICY_COUNT];
00450         double lowLimit[COST_RISE_POLICY_COUNT];
00451         double highLimit[COST_RISE_POLICY_COUNT];
00452         double tolLimit[COST_RISE_POLICY_COUNT];
00453         double limitCoeff[COST_RISE_POLICY_COUNT];
00454         double limitSum;
00455         double cost1[COST_RISE_POLICY_COUNT];
00456         double cost2[COST_RISE_POLICY_COUNT];
00457         for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00458             lowLimit[i] = PL_Policy_Array_S2[i][1];
00459             highLimit[i] = PL_Policy_Array_S2[i][2];
00460             tolLimit[i] = 0.0005;
00461             limitCoeff[i] = A(COST_RISE_POLICY_COUNT*2+1, i+1 );
00462             cost1[i] = c(i+1);
00463             cost2[i] = Q(i+1);
00464         }
00465         limitSum = b(COST_RISE_POLICY_COUNT*2+1);
00466 
00467         QuadProgramming quadProg;
00468 
00469         if( quadProg.sp_quadratic_programming( COST_RISE_POLICY_COUNT,
00470                                                Alt_Result_Vector_S2,
00471                                                lowLimit, highLimit, tolLimit, limitCoeff, limitSum, cost1, cost2 ) ) {
00472             // calc how good confront to constraint
00473 
00474             double cSum2 = 0.0;
00475             for( i = 0; i < COST_RISE_POLICY_COUNT; ++i )
00476                 cSum2 += limitCoeff[i] * Alt_Result_Vector_S2[i];
00477             // now compare cSum2 with limitSum
00478 
00479             double wSum2 = 0.0f;
00480             for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00481                 wSum2 += (cost2[i] * Alt_Result_Vector_S2[i] + cost1[i]) * Alt_Result_Vector_S2[i];
00482             }
00483 
00484             // now compare cSum2 with cSum
00485             if( fabs(cSum2 - limitSum) < fabs(cSum - limitSum) ) {
00486                 // better solution
00487 
00488                 for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00489                     Result_Vector_S2[i] = Alt_Result_Vector_S2[i];
00490                 }
00491             }
00492         }
00493 
00494     }
00495 
00496     // Set Final_Budget = new Revenue_and_Expense
00497     Calc_Budget( Final_Budget, Result_Vector_S1, Result_Vector_S2,
00498                  Base_Budget, New_State_approp, inflation, Base_tuition_rate, Target_enrollment,
00499                  Base_endowmentMV, Base_OpResBalance, ST_int_rate_01Aug, New_Debt_service );
00500 
00501     // DEBUG OUTPUT
00502     Write_Budget( Final_Budget, 107, 3 );
00503 
00504     // Set New_Actual = New Revenue_and_Expense
00505 
00506     Calc_Actual( New_Actual, Final_Budget,
00507                  Base_Actual, Actual_fac_salaries_31Aug, ST_int_rate_31Aug,
00508                  Actual_enrollment, Base_OpResBalance );
00509 
00510     // DEBUG OUTPUT
00511     Write_Budget( New_Actual, 107, 8 );
00512 }
00513 
00514 static void Calc_Actual( Revenue_and_Expense &Actual_Obj, const Revenue_and_Expense &Budget_Obj,
00515                          const Revenue_and_Expense &Base_Actual,
00516                          double Actual_fac_salaries_31Aug,
00517                          double ST_int_rate_31Aug,
00518                          double Actual_enrollment,
00519                          double Base_OpResBalance ) {
00520     int i, j;
00521 
00522   // beware some use Budget_Obj, some use Base_Actual
00523                                                   // Tuition revenue
00524     Actual_Obj.Revenue_Array[AC_GROSS_TUITION_INCOME][3] = Budget_Obj.Tuition_Rate * Actual_enrollment / 1000.0;
00525     // Financial Aid
00526     Actual_Obj.Revenue_Array[AC_FINANCIAL_AID][3] = Budget_Obj.Revenue_Array[AC_FINANCIAL_AID][3];
00527     Actual_Obj.Revenue_Array[AC_NET_TUITION_INCOME][3] = 0.0f;
00528     for( i = AC_GROSS_TUITION_INCOME; i < AC_NET_TUITION_INCOME; ++i )
00529         Actual_Obj.Revenue_Array[AC_NET_TUITION_INCOME][3] += Actual_Obj.Revenue_Array[i][3];
00530 
00531                                                   // Direct sponsored research
00532     Actual_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1] = Base_Actual.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1];
00533     Actual_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2] = Base_Actual.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1]
00534         // Indirect (=0 if denominator = 0)
00535         * math.safe_divide(Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2],Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1]);
00536     Actual_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][3] = Actual_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1]
00537         + Actual_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2];
00538 
00539                                                   // Gifts
00540     Actual_Obj.Revenue_Array[AC_GIFTS][3] = Base_Actual.Revenue_Array[AC_GIFTS][3];
00541     // Endowment spending
00542     Actual_Obj.Revenue_Array[AC_ENDOWMENT_SPENDING][3] = Budget_Obj.Revenue_Array[AC_ENDOWMENT_SPENDING][3];
00543     // Athletics
00544     Actual_Obj.Revenue_Array[AC_INTERCOLLEGIATE_ATHLETICS][3] = Base_Actual.Revenue_Array[AC_INTERCOLLEGIATE_ATHLETICS][3];
00545     // Other income
00546     Actual_Obj.Revenue_Array[AC_OTHER_OPERATING_INCOME][3] = Base_Actual.Revenue_Array[AC_OTHER_OPERATING_INCOME][3];
00547     // Int on oper res
00548     Actual_Obj.Revenue_Array[AC_INTEREST_EARNED_OR_PAID][3] = ST_int_rate_31Aug * (Base_OpResBalance + Base_Actual.Surplus_Deficit);
00549     // State appropriation
00550     Actual_Obj.Revenue_Array[AC_STATE_APPROPRIATION][3] = Budget_Obj.Revenue_Array[AC_STATE_APPROPRIATION][3];
00551 
00552     // Most actuals equal forecast
00553     for( i = 0; i < OPERATING_EXPENSE_ITEM_COUNT; ++i ) {
00554         for( j = 0; j <= 2; ++j ) {
00555             Actual_Obj.Expense_Array[i][j] = Budget_Obj.Expense_Array[i][j];
00556         }
00557     }
00558 
00559     // Now process the exceptions and "below the line" items
00560     // Faculy salaries
00561     Actual_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][0] = Actual_fac_salaries_31Aug;
00562     for( j = 0; j <= 2; ++j )
00563         // Sponsored research
00564         Actual_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][j] = Base_Actual.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][j];
00565 
00566     // although in VBA from Bill, is 11 and 12
00567     // change the index to 11-12, as Bill may think index 10 is used to operating expense total
00568     for( j = 0; j <= 2; ++j )
00569         // Debt service
00570         Actual_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][j] = Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][j];
00571     for( j = 0; j <= 2; ++j )
00572         // Transfer to capital reserve
00573         Actual_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][j] = Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][j];
00574 
00575     // calc faulty+staff+other to total of each expense item
00576     for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00577         double expenseItemTotal = 0.0f;
00578         for( j = 0; j <= 2; ++j ) {
00579             expenseItemTotal += Actual_Obj.Expense_Array[i][j];
00580         }
00581         Actual_Obj.Expense_Array[i][3] = expenseItemTotal;
00582     }
00583     Actual_Obj.calc_Surplus_Deficit();
00584 }
00585 
00586 static void Calc_Budget( Revenue_and_Expense &Budget_Obj, float *Policy_Vector_S1, float *Policy_Vector_S2,
00587                          const Revenue_and_Expense &Base_Budget,
00588                          double New_State_approp, double inflation, double Base_tuition_rate, double Target_enrollment,
00589                          double Base_endowmentMV, double Base_OpResBalance, double ST_int_rate_01Aug, double New_Debt_service ) {
00590     int i;
00591     // Forecasts revenue and expense items for use in budgeting
00592 
00593     // Revenues
00594     // Tuition revenue
00595     Budget_Obj.Tuition_Rate = (1.0 + inflation + Policy_Vector_S1[PL_TUITION_RATE_GROWTH]) * Base_tuition_rate;
00596     Budget_Obj.Revenue_Array[AC_GROSS_TUITION_INCOME][3] = (Budget_Obj.Tuition_Rate / 1000.0) * Target_enrollment;
00597 
00598     // Financial Aid
00599     Budget_Obj.Revenue_Array[AC_FINANCIAL_AID][3] = (1.0 + inflation + Policy_Vector_S1[PL_FINANCIAL_AID]) * Base_Budget.Revenue_Array[AC_FINANCIAL_AID][3];
00600 
00601     // calc net tuition income
00602     Budget_Obj.Revenue_Array[AC_NET_TUITION_INCOME][3] = 0.0f;
00603     for( i = AC_GROSS_TUITION_INCOME; i < AC_NET_TUITION_INCOME; ++i ) {
00604         Budget_Obj.Revenue_Array[AC_NET_TUITION_INCOME][3] += Budget_Obj.Revenue_Array[i][3];
00605     }
00606 
00607     // Sponsored research is calculated later
00608 
00609   // Gifts
00610     Budget_Obj.Revenue_Array[AC_GIFTS][3] = (1.0 + inflation) * Base_Budget.Revenue_Array[AC_GIFTS][3];
00611 
00612     // Endowment spending (row 6)
00613     Budget_Obj.Revenue_Array[AC_ENDOWMENT_SPENDING][3] = Policy_Vector_S1[PL_ENDOWMENT_SPENDING_RATE] * Base_endowmentMV;
00614 
00615     // Athletics
00616     Budget_Obj.Revenue_Array[AC_INTERCOLLEGIATE_ATHLETICS][3] = (1.0 + inflation) * Base_Budget.Revenue_Array[AC_INTERCOLLEGIATE_ATHLETICS][3];
00617 
00618     // Other operating income
00619     Budget_Obj.Revenue_Array[AC_OTHER_OPERATING_INCOME][3] = (1.0 + inflation) * Base_Budget.Revenue_Array[AC_OTHER_OPERATING_INCOME][3];
00620 
00621     // Interest on the operating reserve (adjust for current year surplus/deficit)
00622     Budget_Obj.Revenue_Array[AC_INTEREST_EARNED_OR_PAID][3] = (Base_OpResBalance + Base_Budget.Surplus_Deficit) * ST_int_rate_01Aug;
00623 
00624     // state appropriation
00625     Budget_Obj.Revenue_Array[AC_STATE_APPROPRIATION][3] = New_State_approp;
00626 
00627     // Expenses
00628 
00629   // Academic departments
00630     Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][0] = Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][0]
00631         * (1.0 + Policy_Vector_S2[PL_FACULTY_FTE] + inflation
00632            // Faculty salaries
00633            + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES] );
00634     Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][1] = Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][1]
00635         * (1.0 + Policy_Vector_S2[PL_NON_FACULTY_DEPARTMENTAL_EXPENSE] + inflation
00636            // Staff salaries
00637            + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_STAFF_SALARY_INCREASES]);
00638     Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][2] = Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][2]
00639         // other salaries
00640         * (1.0 + Policy_Vector_S2[PL_NON_FACULTY_DEPARTMENTAL_EXPENSE] + inflation);
00641     Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][3] = Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][0]
00642         + Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][1]
00643         + Budget_Obj.Expense_Array[AC_ACADEMIC_DEPARTMENTS][2];
00644 
00645   // Sponsered research (equal last year except for salary increases)
00646     Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][0] = Base_Budget.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][0]
00647         // Faculty salaries
00648         * (1.0 + inflation + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES]);
00649     Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][1] = Base_Budget.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][1]
00650         // Staff salaries
00651         * (1.0 + inflation + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_STAFF_SALARY_INCREASES]);
00652     Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][2] = Base_Budget.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][2]
00653         * (1.0 + inflation);                          // other expense
00654     Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][3] = Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][0]
00655         + Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][1]
00656         + Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][2];
00657 
00658   // Support Service
00659     for( i = 1+AC_SPONSORED_RESEARCH_EXPENSE; i < OPERATING_EXPENSE_ITEM_COUNT; ++i ) {
00660         Budget_Obj.Expense_Array[i][0] = Base_Budget.Expense_Array[i][0]
00661             * (1.0 + Policy_Vector_S2[i] + inflation
00662                // Faculty salaries
00663                + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES] );
00664         Budget_Obj.Expense_Array[i][1] = Base_Budget.Expense_Array[i][1]
00665             * (1.0 + Policy_Vector_S2[i] + inflation
00666                // Staff salaries
00667                + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_STAFF_SALARY_INCREASES]);
00668         Budget_Obj.Expense_Array[i][2] = Base_Budget.Expense_Array[i][2]
00669             * (1.0 + Policy_Vector_S2[i] + inflation);  // other salaries
00670         Budget_Obj.Expense_Array[i][3] = Budget_Obj.Expense_Array[i][0]
00671             + Budget_Obj.Expense_Array[i][1] + Budget_Obj.Expense_Array[i][2];
00672     }
00673 
00674     // Service on general plant debt and Transfer to capital reserve
00675 
00676     Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][0] = 0.0f;
00677     Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][1] = 0.0f;
00678     Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][2] = New_Debt_service;
00679     Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][3] = Budget_Obj.Expense_Array[AC_SERVICE_ON_GENERAL_PLANT_DEBT][2];
00680 
00681     Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][0] = 0.0f;
00682     Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][1] = 0.0f;
00683     Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][2] = Base_Budget.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][2]
00684         // Other Expense
00685         * (1.0 + inflation + Policy_Vector_S1[REVENUE_POLICY_COUNT+PL_REAL_TRANSFER_TO_PLANT_GROWTH]);
00686     Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][3] = Budget_Obj.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][2];
00687 
00688   // Sponsored research REVENUE (direct revenue = sponsored research expense;
00689   //    indirect revenue = smoothed adjustment based on the new indirect cost rate)
00690 
00691     Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1] = Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][3];
00692     Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2] = Base_Budget.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2]
00693         + 0.5 * (Budget_Obj.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][3]
00694                  * Policy_Vector_S1[PL_INDIRECT_COST_RATE] - Base_Budget.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2]);
00695     Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][3] = Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][1]
00696         + Budget_Obj.Revenue_Array[AC_SPONSORED_RESEARCH_REVENUE][2];
00697 
00698   // calc surplus deficit
00699 
00700     Budget_Obj.calc_Surplus_Deficit();
00701 }
00702 
00703 // this function original for Bill to fill fields on spreadsheet
00704 static void Write_Budget( Revenue_and_Expense &Trial_Budget, int, int ) {
00705 #ifdef DEBUG
00706     DEBUG_LOG("Revenue :");
00707 
00708     String s;
00709     for( int i = 0; i < REVENUE_ITEM_COUNT; ++i ) {
00710         s  = Trial_Budget.Revenue_Array[i][3];
00711         if( i == AC_SPONSORED_RESEARCH_REVENUE ) {
00712             s += "   {";
00713             s += Trial_Budget.Revenue_Array[i][1];
00714             s += " + ";
00715             s += Trial_Budget.Revenue_Array[i][2];
00716             s += "}";
00717         }
00718         DEBUG_LOG( (char *)s );
00719     }
00720 
00721     DEBUG_LOG("Expense :");
00722     for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00723         s  = Trial_Budget.Expense_Array[i][3];
00724         s += "  {";
00725         s += Trial_Budget.Expense_Array[i][0];
00726         s += " + ";
00727         s += Trial_Budget.Expense_Array[i][1];
00728         s += " + ";
00729         s += Trial_Budget.Expense_Array[i][2];
00730         s += "}";
00731         DEBUG_LOG( (char *)s );
00732     }
00733 
00734     s  = "Surplus = ";
00735     s += Trial_Budget.Surplus_Deficit;
00736     DEBUG_LOG( (char *)s );
00737 #endif
00738 }
00739 
00740 // dimension of c is [REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT]
00741 // dimension of Q is [REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT]
00742 // dimension of A is [(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2][REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT]
00743 // dimension of b is [(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2]
00744 
00745 static void Calc_Matrices_S1( double trial_Surplus_Deficit, ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b,
00746                               const float PL_Policy_Array_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][4],
00747                               const Revenue_and_Expense &Base_Budget,
00748                               double Base_tuition_rate,
00749                               double Target_enrollment,
00750                               double Base_endowmentMV,
00751                               double inflation
00752     ) {
00753     // Calculate the matrices for stage 1 optimization input
00754     // minimize c'x + x'Qx/2 s.t. Ax >= b ( and x >= 0 )
00755 
00756     double remainder, coefficients[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT];
00757     double Base_Budget_OperatingCost[4];
00758     double Base_Budget_TotalUseOfFund[4];
00759 
00760     int i,j;
00761     for( j = 0; j < 4; ++j ) {
00762         Base_Budget_OperatingCost[j] = 0.0f;
00763         for(i=0; i < OPERATING_EXPENSE_ITEM_COUNT; ++i )
00764             Base_Budget_OperatingCost[j] += Base_Budget.Expense_Array[i][j];
00765     }
00766     for( j = 0; j < 4; ++j ) {
00767         Base_Budget_TotalUseOfFund[j] = 0.0f;
00768         for(i=0; i < EXPENSE_ITEM_COUNT; ++i )
00769             Base_Budget_TotalUseOfFund[j] += Base_Budget.Expense_Array[i][j];
00770     }
00771 
00772     // initialize A to zero
00773     A = 0.0;
00774 
00775     // Contraints
00776     // Tuition rate
00777     coefficients[PL_TUITION_RATE_GROWTH] = Base_tuition_rate * Target_enrollment / 1000.0;
00778     // Financial aid
00779     coefficients[PL_FINANCIAL_AID] = Base_Budget.Revenue_Array[AC_FINANCIAL_AID][3];
00780     // Endowment spending
00781     coefficients[PL_ENDOWMENT_SPENDING_RATE] = Base_endowmentMV;
00782     // indirect cost rate
00783     coefficients[PL_INDIRECT_COST_RATE] = Base_Budget.Expense_Array[AC_SPONSORED_RESEARCH_EXPENSE][3] * (1.015 + inflation) / 2.0f;
00784 
00785   // Approximates the salary increases to maintain linearity and allows for the smooth
00786                                                   // faculty salaries
00787     coefficients[REVENUE_POLICY_COUNT+PL_FACULTY_SALARY_INCREASES] = -Base_Budget_OperatingCost[0];
00788     // staff salaries
00789     coefficients[REVENUE_POLICY_COUNT+PL_STAFF_SALARY_INCREASES] = -Base_Budget_OperatingCost[1];
00790     // real budget growth
00791     coefficients[REVENUE_POLICY_COUNT+PL_BUDGET_ADJUSTMENT] = -Base_Budget_OperatingCost[3];
00792     // Transfer to capital reserve
00793     coefficients[REVENUE_POLICY_COUNT+PL_REAL_TRANSFER_TO_PLANT_GROWTH] = -Base_Budget.Expense_Array[AC_TRANSFER_TO_CAPITAL_RESERVE][3];
00794     // surplus/deficit
00795     coefficients[REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT] = -Base_Budget_TotalUseOfFund[3] * (1.0 + inflation);
00796 
00797     // object function
00798     static double weightScale = 100000.0;
00799     for(i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00800         // original design
00801         //c(i+1) = -PL_Policy_Array_S1[i][0] * PL_Policy_Array_S1[i][3]; // -target * weight
00802         //Q(i+1) = PL_Policy_Array_S1[i][3] / 2.0; // weight / 2
00803 
00804         // change 1
00805         double adjWeight = 1.0;
00806         if( coefficients[i] != 0.0 ) {                // avoid adjWeight to be zero, (eg. sponsored research is zero, then indirect cost rate in unconstrainted. If adjWeight is zero, optimization can't get the target value (c/-2Q))
00807             // order 1 : default
00808             adjWeight = PL_Policy_Array_S1[i][3] * fabs(coefficients[i])/weightScale;
00809             // order 0
00810             //adjWeight = PL_Policy_Array_S1[i][3];
00811             // order -1
00812             //adjWeight = fabs(coefficients[i]) < 1.0 ? PL_Policy_Array_S1[i][3]
00813             //  : PL_Policy_Array_S1[i][3] * weightScale / fabs(coefficients[i]);
00814             // order 2
00815             //adjWeight = PL_Policy_Array_S1[i][3] * coefficients[i] * coefficients[i] / weightScale;
00816         }
00817 
00818         // -target * weight
00819         c(i+1) = -PL_Policy_Array_S1[i][0] * adjWeight;
00820         Q(i+1) = adjWeight / 2.0;                     // weight / 2
00821     }
00822 
00823     remainder = trial_Surplus_Deficit;
00824 
00825     for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00826         if( i != REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT )
00827             remainder -= coefficients[i] * PL_Policy_Array_S1[i][0];
00828     }
00829 
00830     for( i = 0; i < REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT; ++i ) {
00831         A(i+1,i+1) = 1.0;
00832         b(i+1) = PL_Policy_Array_S1[i][1];            // lower bound
00833         A(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT+i+1, i+1) = -1.0f;
00834         // upper bound
00835         b(REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT+i+1) = -PL_Policy_Array_S1[i][2];
00836 
00837         A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1, i+1) = -coefficients[i];
00838         // positive budget constraint
00839         b((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1) = remainder;
00840         A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2, i+1) = coefficients[i];
00841         // negative budget constraint
00842         b((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+2) = -remainder;
00843     }
00844 
00845     // reverse the signs of the surplus/deficit terms
00846     // A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2, REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT)
00847     // = -A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2, REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT);
00848     // A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1, REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT)
00849     // = -A((REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT)*2+1, REVENUE_POLICY_COUNT+PL_SURPLUS_DEFICIT);
00850 }
00851 
00852 //      dimension of c is [COST_RISE_POLICY_COUNT]
00853 //      dimension of Q is [COST_RISE_POLICY_COUNT][COST_RISE_POLICY_COUNT]
00854 //      dimension of A is [COST_RISE_POLICY_COUNT*2+2][COST_RISE_POLICY_COUNT]
00855 // dimension of b is [COST_RISE_POLICY_COUNT*2+2]
00856 
00857 static void Calc_Matrices_S2( double dollar_Constraint, ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b,
00858                               const Revenue_and_Expense &Base_Budget,
00859                               const float PL_Policy_Array_S2[COST_RISE_POLICY_COUNT][4]
00860     ) {
00861     // calculate the matrices for stage 2 optimization input
00862     // minimize c'x + x'Qx/2 s.t. Ax >= b ( and x >= 0 )
00863     // NOTE :  the second-order effects between real budget growth and salary increments
00864     // and faculty research offsets are ignored to make the results easy to track.
00865 
00866     double coefficients[COST_RISE_POLICY_COUNT];
00867 
00868     int i;
00869 
00870     // initialize A to zero
00871     A = 0.0;
00872 
00873     // constraint
00874 
00875     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00876         if( i == PL_FACULTY_FTE ) {
00877             // faculty budget
00878             coefficients[i] = Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][0];
00879         }
00880         else if( i == PL_NON_FACULTY_DEPARTMENTAL_EXPENSE ) {
00881             coefficients[i] = Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][1]
00882                 // nonfaculty dept'l expense
00883                 + Base_Budget.Expense_Array[AC_ACADEMIC_DEPARTMENTS][2];
00884         }
00885         else {
00886             err_when( i >= OPERATING_EXPENSE_ITEM_COUNT );
00887             // all other expenditure line items
00888             coefficients[i] = Base_Budget.Expense_Array[i][3];
00889         }
00890     }
00891 
00892     // objective function
00893     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00894         // original design
00895         //c(i+1) = -PL_Policy_Array_S2[i][0] * PL_Policy_Array_S2[i][3]; // -target * weight
00896         //Q(i+1) = PL_Policy_Array_S2[i][3] / 2.0; // weight / 2
00897 
00898         // change 1
00899         double adjWeight = PL_Policy_Array_S2[i][3] * fabs(coefficients[i])/100000.0;
00900         // -target * weight
00901         c(i+1) = -PL_Policy_Array_S2[i][0] * adjWeight;
00902         Q(i+1) = adjWeight / 2.0;                     // weight / 2
00903     }
00904 
00905     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
00906         A(i+1,i+1) = 1.0;
00907         b(i+1) = PL_Policy_Array_S2[i][1];            // lower bound
00908         A(COST_RISE_POLICY_COUNT+i+1,i+1) = -1.0f;
00909         // upper bound
00910         b(COST_RISE_POLICY_COUNT+i+1) = -PL_Policy_Array_S2[i][2];
00911 
00912         A(COST_RISE_POLICY_COUNT*2+1,i+1) = coefficients[i];
00913         // Positive budget constraint
00914         b(COST_RISE_POLICY_COUNT*2+1) = dollar_Constraint;
00915         A(COST_RISE_POLICY_COUNT*2+2,i+1) = -coefficients[i];
00916         // Negative budget constraint
00917         b(COST_RISE_POLICY_COUNT*2+2) = -dollar_Constraint;
00918     }
00919 }
00920 
00921 static void quadratic_prog( ColumnVector &c, DiagonalMatrix &Q, Matrix &A, ColumnVector &b, ColumnVector &xNames, int loopCountMultiplier ) {
00922     // use another way to do programming
00923     LinearAlgebra::quadratic_prog(c,Q,A,b,xNames, loopCountMultiplier);
00924     // may return false
00925 }
00926 
00927 // get input for Optimize_policy_ver2
00928 static void input_Optimize_policy_ver2(
00929     Revenue_and_Expense& Base_Budget,                 // Base_Budget is projected actual on 1st Aug
00930     Revenue_and_Expense& Base_Actual,                 // Base_Actual is actual at year end
00931     // slider in stage 1 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00932     float PL_Policy_Array_S1[REVENUE_POLICY_COUNT+EXPENSE_POLICY_COUNT][4],
00933     // slider in stage 2 optimization; [0] is target, [1] is lower bound [2] is upper bound [3] is preference (weight)
00934     float PL_Policy_Array_S2[COST_RISE_POLICY_COUNT][4],
00935     double& inflation, double& Base_tuition_rate,
00936     double& Base_enrollment, double& Target_enrollment, double& Actual_enrollment,
00937     double& Base_endowmentMV,double& Base_OpResBalance,
00938     float& ST_int_rate_01Aug, float& ST_int_rate_31Aug,
00939     double& New_Debt_service ) {
00940     // allocation stage 1
00941     // set input parameter
00942 
00943     int i;
00944 
00945     if( info.prerun_year && info.game_year == 1 ) { // initialization
00946         for( i = 0; i < REVENUE_ITEM_COUNT; ++i ) {
00947             Base_Budget.Revenue_Array[i][0] = 0.0;
00948             Base_Budget.Revenue_Array[i][1] = finance.revenue_array[i].direct;
00949             Base_Budget.Revenue_Array[i][2] = finance.revenue_array[i].indirect;
00950             Base_Budget.Revenue_Array[i][3] = finance.revenue_array[i].total;
00951         }
00952         for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00953             Base_Budget.Expense_Array[i][0] = finance.expense_array[i].faculty;
00954             Base_Budget.Expense_Array[i][1] = finance.expense_array[i].staff;
00955             Base_Budget.Expense_Array[i][2] = finance.expense_array[i].other;
00956             Base_Budget.Expense_Array[i][3] = finance.expense_array[i].total;
00957         }
00958     }
00959     else {
00960         for( i = 0; i < REVENUE_ITEM_COUNT; ++i ) {
00961             Base_Budget.Revenue_Array[i][0] = 0.0;
00962             Base_Budget.Revenue_Array[i][1] = finance.projected_revenue_array[i].month_start.direct;
00963             Base_Budget.Revenue_Array[i][2] = finance.projected_revenue_array[i].month_start.indirect;
00964             Base_Budget.Revenue_Array[i][3] = finance.projected_revenue_array[i].month_start.total;
00965         }
00966         for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00967             Base_Budget.Expense_Array[i][0] = finance.projected_expense_array[i].month_start.faculty;
00968             Base_Budget.Expense_Array[i][1] = finance.projected_expense_array[i].month_start.staff;
00969             Base_Budget.Expense_Array[i][2] = finance.projected_expense_array[i].month_start.other;
00970             Base_Budget.Expense_Array[i][3] = finance.projected_expense_array[i].month_start.total;
00971         }
00972     }
00973 
00974     if( info.prerun_year && info.game_year == 1 ) { // initialization
00975         for( i = 0; i < REVENUE_ITEM_COUNT; ++i ) {
00976             Base_Actual.Revenue_Array[i][0] = 0.0;
00977             Base_Actual.Revenue_Array[i][1] = finance.revenue_array[i].direct;
00978             Base_Actual.Revenue_Array[i][2] = finance.revenue_array[i].indirect;
00979             Base_Actual.Revenue_Array[i][3] = finance.revenue_array[i].total;
00980         }
00981         for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00982             Base_Actual.Expense_Array[i][0] = finance.expense_array[i].faculty;
00983             Base_Actual.Expense_Array[i][1] = finance.expense_array[i].staff;
00984             Base_Actual.Expense_Array[i][2] = finance.expense_array[i].other;
00985             Base_Actual.Expense_Array[i][3] = finance.expense_array[i].total;
00986         }
00987     }
00988     else {
00989         for( i = 0; i < REVENUE_ITEM_COUNT; ++i ) {
00990             Base_Actual.Revenue_Array[i][0] = 0.0;
00991             Base_Actual.Revenue_Array[i][1] = finance.projected_revenue_array[i].this_year.direct;
00992             Base_Actual.Revenue_Array[i][2] = finance.projected_revenue_array[i].this_year.indirect;
00993             Base_Actual.Revenue_Array[i][3] = finance.projected_revenue_array[i].this_year.total;
00994         }
00995         for( i = 0; i < EXPENSE_ITEM_COUNT; ++i ) {
00996             Base_Actual.Expense_Array[i][0] = finance.projected_expense_array[i].this_year.faculty;
00997             Base_Actual.Expense_Array[i][1] = finance.projected_expense_array[i].this_year.staff;
00998             Base_Actual.Expense_Array[i][2] = finance.projected_expense_array[i].this_year.other;
00999             Base_Actual.Expense_Array[i][3] = finance.projected_expense_array[i].this_year.total;
01000         }
01001     }
01002 
01003     for( i = 0; i < REVENUE_POLICY_COUNT; ++i ) {
01004         // [0] is target
01005         PL_Policy_Array_S1[i][0] = (float)finance.revenue_policy_array[i].target_value / 100.0f;
01006         // [1] is ower bound
01007         PL_Policy_Array_S1[i][1] = (float)finance.revenue_policy_array[i].lower_bound / 100.0f;
01008         // [2] is upper bound
01009         PL_Policy_Array_S1[i][2] = (float)finance.revenue_policy_array[i].upper_bound / 100.0f;
01010         // [3] is preference (weight)
01011         PL_Policy_Array_S1[i][3] = (float)finance.revenue_policy_array[i].import_weight;
01012         if( finance.revenue_policy_array[i].required_flag ) {
01013             // [0] is target
01014             PL_Policy_Array_S1[i][1] = PL_Policy_Array_S1[i][2] = (float)finance.revenue_policy_array[i].target_value / 100.0f;
01015             PL_Policy_Array_S1[i][3] = OPT_HIGH_WEIGHT * 10;
01016         }
01017     }
01018     for( i = 0; i < EXPENSE_POLICY_COUNT; ++i ) {
01019         // [0] is target
01020         PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][0] = (float)finance.expense_policy_array[i].target_value / 100.0f;
01021         // [1] is ower bound
01022         PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][1] = (float)finance.expense_policy_array[i].lower_bound / 100.0f;
01023         // [2] is upper bound
01024         PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][2] = (float)finance.expense_policy_array[i].upper_bound / 100.0f;
01025         // [3] is preference (weight)
01026         PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][3] = (float)finance.expense_policy_array[i].import_weight;
01027         if( finance.expense_policy_array[i].required_flag ) {
01028             // [0] is target
01029             PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][1] = PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][2] = (float)finance.expense_policy_array[i].target_value / 100.0f;
01030             PL_Policy_Array_S1[REVENUE_POLICY_COUNT+i][3] = OPT_HIGH_WEIGHT * 10;
01031         }
01032     }
01033 
01034     for( i = 0; i < COST_RISE_POLICY_COUNT; ++i ) {
01035         PL_Policy_Array_S2[i][0] = (float)finance.cost_rise_policy_array[i].target_value / 100.0f;
01036         PL_Policy_Array_S2[i][1] = (float)finance.cost_rise_policy_array[i].lower_bound / 100.0f;
01037         PL_Policy_Array_S2[i][2] = (float)finance.cost_rise_policy_array[i].upper_bound / 100.0f;
01038         PL_Policy_Array_S2[i][3] = (float)finance.cost_rise_policy_array[i].import_weight;
01039         if( finance.cost_rise_policy_array[i].required_flag ) {
01040             PL_Policy_Array_S2[i][1] = PL_Policy_Array_S2[i][2] = (float)finance.cost_rise_policy_array[i].target_value / 100.0f;
01041             PL_Policy_Array_S2[i][3] = OPT_HIGH_WEIGHT * 10;
01042         }
01043     }
01044 
01045     inflation = finance.inflation_rate/100.0;
01046     Base_tuition_rate = finance.tuition_rate;
01047     // initialization
01048     Base_enrollment = (info.prerun_year && info.game_year == 1)
01049         ? enroll_res.total_student_count
01050         : department_array.student_level_history[MAX_STUDENT_LEVEL_TOTAL][HISTORY_YEAR_COUNT-1];
01051     Target_enrollment = enroll_res.target_enrollment[UG_TRADITION] + enroll_res.target_enrollment[UG_NONTRADITION]
01052         + enroll_res.target_enrollment[MASTER] + department_array.student_level_history[DOCTOR][HISTORY_YEAR_COUNT-1];
01053     Actual_enrollment = Target_enrollment;          // temp, don't know because not generate next year enrollment yet
01054 
01055     // Base_endowmentMV = investment_office.smoothed_endowment_value;
01056     // Base_endowmentMV = finance.this_year.asset_array[AC_ENDOWMENT] + finance.this_year.asset_array[AC_QUASI];
01057     Base_endowmentMV = investment_office.smoothed_endowment_value + investment_office.smoothed_quasi_endowment_value;
01058 
01059     Base_OpResBalance = finance.this_year.asset_array[AC_OPERATING_RESERVE];
01060     ST_int_rate_01Aug = (float)finance.short_term_debt_interest_history[THIS_MONTH-1] / 100.0f;
01061     ST_int_rate_31Aug = (float)finance.short_term_debt_interest_history[THIS_MONTH] / 100.0f;
01062     //initialization
01063     New_Debt_service = (info.prerun_year && info.game_year == 1)
01064         ? finance.expense_array[AC_SERVICE_ON_GENERAL_PLANT_DEBT].total
01065         : finance.projected_expense_array[AC_SERVICE_ON_GENERAL_PLANT_DEBT].next_year.total;
01066 }
01067 #endif
01068 
01069 //---------- Begin of function Finance::init -----------//
01071 void Finance::init() {
01072     memset( this, 0, sizeof(Finance) );
01073 
01074     fiscal_year_start_month = 9;
01075     fiscal_year_end_month = 8;
01076 
01077     //---- fully exogenous factors -----//
01078 
01079     inflation_rate          = 0.0;                  // 0222     3.0;                            // C72
01080     short_term_debt_interest  = 3.0;                // 0406     3.0;
01081     long_term_debt_interest   = 6.0;                // 0406     6.0;
01082     debt_fraction_repaid_annually = 4.0;
01083     family_income_growth        = 0.0;
01084     construction_cost_growth    = 3.0;
01085 
01086     building_life_for_calc_depreciation = 50;       // G80
01087 
01088     //--- exogenous, but may be influenced by the player ---//
01089 
01090     investment_office.expected_real_annual_return_rate = 7.0f;  endowment_return = 7.0;
01091     sponsored_research_growth   = 0.0;
01092     gifts_growth            = 0.0;
01093     athletics_revenue_growth    = 0.0;              // G75
01094     bank_debt_interest        = 5.0;
01095     other_expense_growth        = 0.5;
01096     other_income_growth       = 0.0;
01097 
01098     //--------- time variation variable 1017 --------//
01099     //------- initialization ("design notes 0830 section8.2)
01100 
01101     float rate = m.fmax(.01f, math.get_random_snd(.04f, PSCH_SD(.01f))) / 12;
01102 
01103     //inflation_rate_hist.init(FA_HISTORY_YEAR, rate);
01104     inflation_rate_hist.init(FA_HISTORY_YEAR, 0);   //0222
01105     inflation_rate = inflation_rate_hist.get_sum();
01106 
01107     err_when(inflation_rate  != 0);
01108 
01109     //------------------------------------------------//
01110     // ----- init player input for stage1       ----- //
01111     //------------------------------------------------//
01112 
01113     int i;
01114 
01115     //--------//
01116     revenue_policy_array[PL_TUITION_RATE_GROWTH].lower_limit = -5;
01117     revenue_policy_array[PL_FINANCIAL_AID].lower_limit = -5;
01118     revenue_policy_array[PL_ENDOWMENT_SPENDING_RATE].lower_limit = 4;
01119     revenue_policy_array[PL_INDIRECT_COST_RATE].lower_limit = 20;
01120 
01121     expense_policy_array[0].lower_limit = 0.0;
01122     expense_policy_array[1].lower_limit = 0.0;
01123     expense_policy_array[2].lower_limit = -5;
01124     expense_policy_array[3].lower_limit = -5;
01125     expense_policy_array[4].lower_limit = -3;
01126 
01127     //----//
01128     revenue_policy_array[PL_TUITION_RATE_GROWTH].upper_limit = 5;
01129     revenue_policy_array[PL_FINANCIAL_AID].upper_limit = 5;
01130     revenue_policy_array[PL_ENDOWMENT_SPENDING_RATE].upper_limit = 10;
01131     revenue_policy_array[PL_INDIRECT_COST_RATE].upper_limit = 70;
01132 
01133     expense_policy_array[0].upper_limit = 5.0;
01134     expense_policy_array[1].upper_limit = 5.0;
01135     expense_policy_array[2].upper_limit = 5.0;
01136     expense_policy_array[3].upper_limit = 5.0;
01137     expense_policy_array[4].upper_limit = 3;
01138 
01139     revenue_policy_array[0].max_penalty1 = 10;
01140     revenue_policy_array[1].max_penalty1 = 10;
01141     revenue_policy_array[2].max_penalty1 = 5;
01142     revenue_policy_array[3].max_penalty1 = 20;
01143 
01144     expense_policy_array[0].max_penalty1 = 20;
01145     expense_policy_array[1].max_penalty1 = 20;
01146     expense_policy_array[2].max_penalty1 = 5;
01147     expense_policy_array[3].max_penalty1 = 10;
01148     expense_policy_array[4].max_penalty1 = 20;
01149 
01150     expense_policy_array[0].max_penalty2 = 20;
01151     expense_policy_array[1].max_penalty2 = 20;
01152     expense_policy_array[2].max_penalty2 = 5;
01153     expense_policy_array[3].max_penalty2 = 10;
01154     expense_policy_array[4].max_penalty2 = 20;
01155 
01156     //max_penalty_effect
01157 
01158     for ( i=0; i<REVENUE_POLICY_COUNT; i++) {
01159         //990506 revenue_policy_array[i].target_value = (revenue_policy_array[i].lower_limit+revenue_policy_array[i].upper_limit) / 2;
01160 
01161         revenue_policy_array[i].lower_bound = revenue_policy_array[i].lower_limit;
01162         revenue_policy_array[i].upper_bound = revenue_policy_array[i].upper_limit;
01163         revenue_policy_array[i].import_weight = OPT_MID_WEIGHT;
01164         revenue_policy_array[i].penalty_multiplier1 = 1;
01165         revenue_policy_array[i].penalty_multiplier2 = 1;
01166 
01167         set_policy_target(true, i);
01168     }
01169 
01170     for ( i=0; i<EXPENSE_POLICY_COUNT; i++) {
01171         // expense_policy_array[i].target_value = (expense_policy_array[i].lower_limit+expense_policy_array[i].upper_limit) / 2;
01172 
01173         expense_policy_array[i].lower_bound = expense_policy_array[i].lower_limit;
01174         expense_policy_array[i].upper_bound = expense_policy_array[i].upper_limit;
01175         expense_policy_array[i].import_weight = OPT_MID_WEIGHT;
01176         expense_policy_array[i].penalty_multiplier1 = 1;
01177         expense_policy_array[i].penalty_multiplier2 = 1;
01178 
01179         set_policy_target(false, i);
01180     }
01181 
01182     //---------//
01183 
01184     revenue_policy_array[0].lower_bound = 0;        // 990518; temp fix for 2.6.2 and 5.1.1
01185 
01186     //---------//
01187     for (i=0; i<REVENUE_POLICY_COUNT; i++) {
01188         revenue_policy_array[i].reset_change(true);
01189         revenue_policy_array[i].bound_correction();   //## chea 310899 try not using all the bound_correction
01190         revenue_policy_array[i].penalty_direction = NEGATIVE;
01191     }
01192 
01193     for (i=0; i<EXPENSE_POLICY_COUNT; i++) {
01194         expense_policy_array[i].reset_change(true);
01195         expense_policy_array[i].bound_correction();   //## chea 310899 try not using all the bound_correction
01196         expense_policy_array[i].penalty_direction = NEGATIVE;
01197     }
01198 
01199     revenue_policy_array[PL_TUITION_RATE_GROWTH].penalty_direction = POSITIVE;
01200     revenue_policy_array[PL_INDIRECT_COST_RATE].penalty_direction = POSITIVE;
01201 
01202     //
01203     // ----- for stage2 ----- //
01204     //
01205 
01206     cost_rise_policy_array[0].target_value = 0.0;
01207     cost_rise_policy_array[1].target_value = 0.0;
01208     cost_rise_policy_array[2].target_value = 0.0;
01209     cost_rise_policy_array[3].target_value = 0.0;
01210     cost_rise_policy_array[4].target_value = 0.0;
01211 
01212     cost_rise_policy_array[5].target_value = 0.0;
01213     cost_rise_policy_array[6].target_value = 0.0;
01214     cost_rise_policy_array[7].target_value = 0.0;
01215     cost_rise_policy_array[8].target_value = 0.0;
01216     cost_rise_policy_array[9].target_value = 0.0;
01217 
01218     cost_rise_policy_array[0].lower_bound = -5;
01219     cost_rise_policy_array[1].lower_bound = -5;
01220     cost_rise_policy_array[2].lower_bound = -5;
01221     cost_rise_policy_array[3].lower_bound = -5;
01222     cost_rise_policy_array[4].lower_bound = -5;
01223 
01224     cost_rise_policy_array[5].lower_bound = -5;
01225     cost_rise_policy_array[6].lower_bound = -5;
01226     cost_rise_policy_array[7].lower_bound = -5;
01227     cost_rise_policy_array[8].lower_bound = -5;
01228     cost_rise_policy_array[9].lower_bound = -5;
01229 
01230     cost_rise_policy_array[0].upper_bound = 5;
01231     cost_rise_policy_array[1].upper_bound = 5;
01232     cost_rise_policy_array[2].upper_bound = 5;
01233     cost_rise_policy_array[3].upper_bound = 5;
01234     cost_rise_policy_array[4].upper_bound = 5;
01235 
01236     cost_rise_policy_array[5].upper_bound = 5;
01237     cost_rise_policy_array[6].upper_bound = 5;
01238     cost_rise_policy_array[7].upper_bound = 5;
01239     cost_rise_policy_array[8].upper_bound = 5;
01240     cost_rise_policy_array[9].upper_bound = 5;
01241 
01242     cost_rise_policy_array[0].max_penalty1 = 5;
01243     cost_rise_policy_array[1].max_penalty1 = 10;
01244     cost_rise_policy_array[2].max_penalty1 = 5;
01245     cost_rise_policy_array[3].max_penalty1 = 50;
01246     cost_rise_policy_array[4].max_penalty1 = 5;
01247 
01248     cost_rise_policy_array[5].max_penalty1 = 5;
01249     cost_rise_policy_array[6].max_penalty1 = 50;
01250     cost_rise_policy_array[7].max_penalty1 = 10;
01251     cost_rise_policy_array[8].max_penalty1 = 10;
01252     cost_rise_policy_array[9].max_penalty1 = 50;
01253 
01254     cost_rise_policy_array[0].max_penalty2 = 0;
01255     cost_rise_policy_array[1].max_penalty2 = 0;
01256     cost_rise_policy_array[2].max_penalty2 = 5;
01257     cost_rise_policy_array[3].max_penalty2 = 10;
01258     cost_rise_policy_array[4].max_penalty2 = 0;
01259 
01260     cost_rise_policy_array[5].max_penalty2 = 50;
01261     cost_rise_policy_array[6].max_penalty2 = 0;
01262     cost_rise_policy_array[7].max_penalty2 = 0;
01263     cost_rise_policy_array[8].max_penalty2 = 0;
01264     cost_rise_policy_array[9].max_penalty2 = 0;
01265 
01266     for ( i=0; i<COST_RISE_POLICY_COUNT; i++) {
01267         cost_rise_policy_array[i].lower_limit = -5.0;
01268         cost_rise_policy_array[i].upper_limit = 5.0;
01269         cost_rise_policy_array[i].import_weight = OPT_MID_WEIGHT;
01270         cost_rise_policy_array[i].penalty_multiplier1 = 1;
01271         cost_rise_policy_array[i].penalty_multiplier2 = 1;
01272     }
01273 
01274     //---------//
01275     for ( i=0; i<COST_RISE_POLICY_COUNT; i++) {
01276         cost_rise_policy_array[i].bound_correction(); //## chea 310899 try not using all the bound_correction
01277         cost_rise_policy_array[i].reset_change(true);
01278         cost_rise_policy_array[i].penalty_direction = NEGATIVE;
01279     }
01280 }
01281 
01282 //---------- End of function Finance::init -----------//
01283 
01284 //---------- Begin of function Finance::deinit -----------//
01286 void Finance::deinit() {
01287 
01288 }
01289 
01290 //---------- End of function Finance::deinit -----------//
01291 
01292 //---------- Begin of function Finance::init_data -----------//
01300 void Finance::init_data_pre_enroll() {            // 1228
01301     PeerSchool *playerSchoolEx = school_res.player_peer_school;
01302 
01303     //---------------------------------------------------//
01304 
01305     tuition_rate = playerSchoolEx->tuition_rate;
01306 }
01307 
01308 void Finance::init_data() {
01309     int i;
01310     PeerSchool *playerSchoolEx = school_res.player_peer_school;
01311 
01312     //-----------------------------------------------------------//
01313 
01314     int totalFacResearchExpense = 0;                // monthly
01315     int d;
01316 
01317     Department *dept;
01318 
01319     for ( d=department_array.size(); d>0; d-- ) {
01320         if ( department_array.is_deleted(d) )
01321             continue;
01322 
01323         dept = department_array[d];
01324 
01325         dept->calc_research_dollar();
01326 
01327         //## chea 221199
01328         //              totalFacResearchExpense += dept->total_research_dollar;
01329         totalFacResearchExpense += dept->total_research_dollar /1000;
01330     }
01331 
01332     int totalResearchExpense = 0;
01333 
01334     //0219      // 990421
01335     totalResearchExpense = int( 12 * totalFacResearchExpense );
01336 
01337     //------------ initialize balance sheet -------------//
01338 
01339     memset( last_year.asset_array, 0, sizeof(last_year.asset_array) );
01340     memset( last_year.liability_array, 0, sizeof(last_year.liability_array) );
01341 
01342     // 0305
01343     last_year.asset_array[AC_OPERATING_RESERVE] = playerSchoolEx->operating_reserve * 1.3;
01344 #if(GAME_VERSION>=200)
01345     this_year.asset_array[AC_OPERATING_RESERVE]  = last_year.asset_array[AC_OPERATING_RESERVE];
01346 #endif
01347     last_year.asset_array[AC_ENDOWMENT]       = playerSchoolEx->endowment_market;
01348