static void print_vector(c_vector * p) { c_iterator first, last; first = c_vector_begin(p); last = c_vector_end(p); print_vector2(first, last); }
//---------- Begin of function Finance::optimize_policy_3 -----------// //! bool Finance::optimize_policy_3() { Department *deptPtr; int i; int deptCount = department_array.department_count; #ifdef TEST_MATHCA deptCount = 10; #endif const double weight_intrinsic = 0.45f; // c148 Weight on intrinsic value (v. TL) //const double weight_response = 0.7f; // c149 Weight on responsiveness (v. stability) err_when(deptCount<=0); //----------------------------// //ColumnVector avgSalary(deptCount); // column E 153:162 // $000 //ColumnVector facCount(deptCount); // column I 153:162 //----------------------------// check player input //## chea check the total_hires & totaltarget int totalupper = 0; for (int r=0; r<department_array.department_count; r++ ) { HiringPolicy* finPr2 = &(finance.hiring_policy_array[r]); totalupper += finPr2 -> upper_bound; } if (totalupper < total_hires) { box.msg("The total of your upper bound values is less than the total faculty you wanted to be hired. "); return false; } //## chea check the total_hires & totaltarget ColumnVector targetHire(deptCount), weightsIV3(deptCount), upperBound(deptCount); for (i=deptCount; i>0; i--) { err_if ( department_array.is_deleted(i) ) err_here(); deptPtr = department_array[i]; DepartmentInfo* deptInfo = department_res[deptPtr->department_id]; weightsIV3(i) = (double)1/(double)max( 1,deptPtr->faculty_array.size() ); //## chea try to avoid the bug below if (finance.hiring_policy_array[i-1].upper_bound< finance.hiring_policy_array[i-1].target_value) { finance.hiring_policy_array[i-1].upper_bound = finance.hiring_policy_array[i-1].target_value; } upperBound(i) = finance.hiring_policy_array[i-1].upper_bound; targetHire(i) = finance.hiring_policy_array[i-1].target_value; err_when(upperBound(i) < targetHire(i)); } #ifdef TEST_MATHCA double dummyArr[] = {3,7,13,2,2, 1,5,0,1,4}; double dummyW[] = {1.000,1.135,1.450,1.000,0.955,1.000,1.000,0.775,1.000,1.000}; targetHire << dummyArr; upperBound << dummyArr; weightsIV3 << dummyW; #endif //----------------------------// construct quad_program input matrices PART A ColumnVector c(deptCount); DiagonalMatrix Q(deptCount); c = -SP(targetHire, weightsIV3); Q.set_diagonal(weightsIV3); //----------------------------// PART B // for (i=1; i <=deptCount; i++) // { // surplusRHS(1) += avgSalary(i) * facCount(i) * (1+growthRate); // surplusCoefs3(i) = avgSalary(i) * (1+growthRate); // } // { // double maxSavingAtNewSalary = 0; // J177 // for (i=1; i <=deptCount; i++) // { // maxSavingAtNewSalary += (lowerBound3(i) - facCount(i)) * avgSalary(i) * (1+growthRate); // } // double C136 = finance.cost_rise_policy_array[PL_FACULTY_FTE].result_value / 100; // double C203 = finance.stage1_expense[S1_FACULTY_SALARY_INCREASES].base_value; // // #ifdef TEST_MATHCA // surplusRHS(1) += -520.327f; // #else // surplusRHS(1) += max(C136*C203,maxSavingAtNewSalary); // += i178 where i178=MAX(C136*C203,J177) // #endif // } DiagonalMatrix I(deptCount); I = 1; Matrix A = -I; ColumnVector b = -upperBound; err_when(total_hires<0); // check player input RowVector tmpList(deptCount); tmpList = 1; ColumnVector totalHires(1); totalHires(1) = total_hires; #ifdef TEST_MATHCA err_here(); totalHires(1) = -10; for (i=1;i<=deptCount;i++) totalHires(1) += targetHire(i); #endif A = A & -tmpList; b = b & -totalHires; //----------------------------// Go run it! ColumnVector xNames(deptCount); if (!LinearAlgebra::quadratic_prog(c,Q,A,b,xNames)) return false; print_vector2(xNames); //----------------------------// //int deptCount = department_array.size(); int resultTotal = 0; // 990423 //int resultArr[MAX_DEPARTMENT]; // use following procedures : // i) find the largest (remaining) value in xNames and round it to the nearest integer. // For ties, just use the department that comes up first in the search // ii) if that integer >= 1 put it into the Results vector ELSE put 1 in the result vector // iii) repeat from (i) until sum of results equals maxHires. If the value in the (ii) // is greate than the remaining hires, use the remaining hires instead of (ii) int deptRank; double lastXNames; int lastDept=0; for(deptRank=0; deptRank<deptCount; ++deptRank) { int curDept=0; double curXNames; for( i=1; i<=deptCount; ++i ) { double xNamesValue = xNames(i); // this department has been searched if( lastDept != 0 && (xNamesValue > lastXNames || xNamesValue == lastXNames && i <= lastDept) ) continue; // find the department with maximum xNames if( curDept != 0 && xNamesValue <= curXNames ) continue; curDept = i; curXNames = xNamesValue; } // find a department, mark it so next for(deptRank) won't scan it again i = lastDept = curDept; lastXNames = curXNames; int xNamesInt = int( curXNames + 0.5 ); //round to integer // at least get 1 place // or use ceil((total_hires-resultTotal)/(deptCount-deptRank)), if 1 can't fill up all the vacancies xNamesInt = max( xNamesInt, 1 ); // check remaining err_when( resultTotal > total_hires ); if( xNamesInt > total_hires - resultTotal ) xNamesInt = total_hires - resultTotal; // place the result and add the total finance.hiring_policy_array[curDept-1].result_value = xNamesInt; resultTotal += xNamesInt; } //## chea fix the rounding error int counter =0; if (resultTotal > total_hires) { counter = resultTotal - total_hires; //## chea set upper bound to target for (int q=0; q<department_array.department_count; q++ ) { HiringPolicy* finPr5 = &(finance.hiring_policy_array[q]); if (finPr5 -> result_value >=1) { finPr5 -> result_value --; counter--; } if (counter == 0) break; } resultTotal = total_hires; } // readjust result_value may cause bug int diff = total_hires - resultTotal; int deptRecno = 0; for (i=0; i<diff; i++) { finance.hiring_policy_array[deptRecno].result_value ++; if(finance.hiring_policy_array[deptRecno].result_value > 10) { finance.hiring_policy_array[deptRecno].result_value --; diff++; } if ( ++deptRecno == deptCount ) deptRecno = 0; } //## chea set upper bound to target for (int cq=0; cq<department_array.department_count; cq++ ) { HiringPolicy* finPr3 = &(finance.hiring_policy_array[cq]); // finPr3 -> target_value = finPr3 -> result_value; //BUGHERE if (finPr3 -> upper_bound < finPr3 -> result_value) finPr3 -> upper_bound = finPr3 -> result_value; } return true; }