using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Collections.Generic; using lpsolve55; /// /// Code developed by Kenrick Mock and Oran Weaver to return percentages /// of use for a given set of plant data. This will be utilized untill a better /// /// public static class LinearCalculations { private static int PLANT_BIOMASS = 0; private static int PLANT_DDM = 1; private static int PLANT_DP = 2; private static int PLANT_MTB = 3; //using 100% for the model; changed to use this for model upper limit private static int PLANT_TIME = 4; //animal array indexes private static int ANIMAL_DDM = 0; private static int ANIMAL_DP = 1; //private static int ANIMAL_MIN = 2; //private static int ANIMAL_MAX = 3; private static int ANIMAL_TIME = 4; /* getPlantPart uses the lpsolver to calculate the precentage of plants used * and returns the value in an array plantPart[] which corralates with pArray * as each i of plant part is the precentage of pArray[i] consumed. * * double pArray[i][] = {seasonal biomass, %DDM, %DP, MTB} * DDM: Digestable Dry Matter, DP: Digestable Protein, MTB: Max Total Biomass, time per gram * * double aArray[] = {%DDM, %DP, min, max, time_total/dry_matter_intake} (min and max will be implemented after testing is done for 0 and 100) */ public static double[] getPlantPart(/*double[][] pArray*/ List forageList, double[] aArray, bool variation) { /*converts the objects in forageList to a 2d array to be used in the calculations */ double[][] pArray; pArray = new double[(forageList.Count * 8)][]; int m = 0; foreach (Plant thePlant in forageList) { for (int y = 0; y < 8; y++) { pArray[m] = new double[5]; pArray[m][0] = thePlant.CalculatedNutritionalValues[y, 0]; pArray[m][1] = thePlant.CalculatedNutritionalValues[y, 1]; pArray[m][2] = thePlant.CalculatedNutritionalValues[y, 2]; pArray[m][3] = thePlant.MTB; pArray[m][4] = thePlant.CalculatedNutritionalValues[y, 4]; m++; } } /* Make Vars */ int lp; int release = 0, Major = 0, Minor = 0, build = 0; int pLength = pArray.Length; double[] Row; //holds tempory data with a base of 1 double[] storeArray; //holds tempory data with a base of 0 lp = lpsolve.make_lp(0, pLength); lpsolve.lp_solve_version(ref Major, ref Minor, ref release, ref build); //long timeout = 0; //lpsolve.set_timeout(lp, timeout); lpsolve.set_verbose(lp, -1); /* constraints - each has to be <= 1 and >= 0 */ int j = 0; for (int i = 0; i < pLength; i++) { storeArray = new double[pLength]; if (j++ == i) storeArray[i] = 1.0; else storeArray[i] = 0.0; FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve.lpsolve_constr_types.LE, 1);//pArray[i][PLANT_MTB]); } j = 0; for (int i = 0; i < pLength; i++) { storeArray = new double[pLength]; if (j++ == i) storeArray[i] = 1.0; else storeArray[i] = 0.0; FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve.lpsolve_constr_types.GE, 0.0); } // add protein constraint storeArray = new double[pLength]; for (int i = 0; i < pLength; i++) { storeArray[i] = pArray[i][PLANT_DP] * pArray[i][PLANT_BIOMASS] - aArray[ANIMAL_DP] * pArray[i][PLANT_BIOMASS]; } FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve55.lpsolve.lpsolve_constr_types.GE, 0.0); storeArray = new double[pLength]; for (int i = 0; i < pLength; i++) storeArray[i] = pArray[i][PLANT_DDM] * pArray[i][PLANT_BIOMASS] - aArray[ANIMAL_DDM] * pArray[i][PLANT_BIOMASS]; FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve55.lpsolve.lpsolve_constr_types.GE, 0.0); // add time constraint double time_constraint = aArray[ANIMAL_TIME]; storeArray = new double[pLength]; for (int i = 0; i < pLength; i++) { storeArray[i] = pArray[i][PLANT_TIME] * pArray[i][PLANT_BIOMASS] - time_constraint * pArray[i][PLANT_BIOMASS]; } FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve55.lpsolve.lpsolve_constr_types.LE, 0.0); if (!variation) { // add non-variation biomass constraint /* the outer loop is used to specify which plant the store array is building for, * the inner loop is used to make the constriant for eacy plant based on the * plant it is making the storeArray for. * Each iteration of the outer loop represents the set of constraints for that plant * to all plants */ storeArray = new double[pLength]; for (int i = 0; i < pLength; i++) { for (int k = 0; k < pLength; k++) { if (i == k) if (pArray[k][PLANT_MTB] == 1) storeArray[k] = 0; else storeArray[k] = (pArray[k][PLANT_BIOMASS] * pArray[k][PLANT_MTB] - pArray[k][PLANT_BIOMASS]); else storeArray[k] = pArray[k][PLANT_BIOMASS] * pArray[i][PLANT_MTB]; // KJM: I think this should be i } FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve55.lpsolve.lpsolve_constr_types.GE, 0.0); } } else //variation was used //JRS: this area has been slightly modified to work with the moose model. Instead of 3 "subplants" by applying standard //deviation in the deer model, we are dealing with 8 subplants that account for the 8 different stem size classes. { //add variation biomass conststraint for (int i = 0; i < pLength; i += 8) //specifies which plant the storeArray is making the { //constraints for for (int deviation = 0; deviation < 8; deviation++) //iterates throught the deviations for that plant { storeArray = new double[pLength]; for (int k = 0; k < pLength; k++) //used to make the constraint for each plant based on the current { //plant being worked on (the outter two loops) // KJM: // Probably this should be using pArray[i][PLANT_MTB] here as well, although // I haven't changed anything or thought this part through // OLW: // see the two changes below. if (k < i || k > (i + 7)) { storeArray[k] = -pArray[i + deviation][PLANT_MTB] * pArray[k][PLANT_BIOMASS]; //*pArray[k][PLANT_MTB]; //change 1) removed last part } else { storeArray[k] = (1 - pArray[i + deviation][PLANT_MTB]) * pArray[k][PLANT_BIOMASS]; //change 2) changed from (1-pArray[k][PLANT_MTB]) //to (1-pArray[i+deviation][PLANT_MTB]) } } FillArray(out Row, storeArray); lpsolve.add_constraint(lp, ref Row[0], lpsolve55.lpsolve.lpsolve_constr_types.LE, 0.0); } } } // Solve it lpsolve.set_maxim(lp); storeArray = new double[pLength]; for (int i = 0; i < pLength; i++) storeArray[i] = pArray[i][PLANT_BIOMASS]; FillArray(out Row, storeArray); //fill based on data lpsolve.set_obj_fn(lp, ref Row[0]); lpsolve.solve(lp); double[] vars = new double[pLength]; lpsolve.get_variables(lp, ref vars[0]); lpsolve.delete_lp(lp); return vars; } private static void FillArray(out double[] Arry, double[] v) { Arry = new double[v.Length + 1]; for (int i = 0; i < v.Length; i++) { Arry[i + 1] = v[i]; } } }