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];
}
}
}