using System;
namespace Science.Biology.PopulationGenetics
{
///
/// PopulationEquation
///
public class PopulationEquation
{
private double[] adultXX;
private double[] adultXY;
private double[] adultPhenoXX;
private double[] adultPhenoXY;
private double[] birthXX;
private double[] birthXY;
private double[,] parents;
private double[,] effectiveparents;
private double[,] breed;
private double[,] Gamma;
private double[,] GammaPheno;
private int[] mapFromGenoToPhenoXX;
private int[] mapFromGenoToPhenoXY;
private double[,] mutationXX;
private double[,] mutationXY;
private double[,,] reproductioncoefficientXX;
private double[,,] reproductioncoefficientXY;
private double[] disadvantagefactorXX;
private double[] disadvantagefactorXY;
private bool matingtype;
private bool phenoMating;
private bool hierarchicalMating;
public double[] AdultFemalePopulation
{
get{return adultXX;}
}
public double[] AdultMalePopulation
{
get{return adultXY;}
}
public double[] AdultPhenoFemalePopulation
{
get{return adultPhenoXX;}
}
public double[] AdultPhenoMalePopulation
{
get{return adultPhenoXY;}
}
public double[] BirthFemalePopulation
{
get{return birthXX;}
}
public double[] BirthMalePopulation
{
get{return birthXY;}
}
public double[,] ParentPopulation
{
get{return parents;}
}
public double[,] MatingFactor
{
get{return Gamma;}
}
public PopulationEquation(Mating m, Mutation muta, Reproduction r, Selection s)
{
adultXX = new double[muta.NumberOfAlleleFemale];
adultXY = new double[muta.NumberOfAlleleMale];
birthXX = new double[muta.NumberOfAlleleFemale];
birthXY = new double[muta.NumberOfAlleleMale];
parents = new double[muta.NumberOfAlleleFemale, muta.NumberOfAlleleMale];
effectiveparents = new double[muta.NumberOfAlleleFemale, muta.NumberOfAlleleMale];
Gamma = new double[muta.NumberOfAlleleFemale, muta.NumberOfAlleleMale];
for(int i = 0; i < muta.NumberOfAlleleFemale ; i++)
{
for(int j = 0; j < muta.NumberOfAlleleMale ; j++)
{
Gamma[i,j] = 1.0;
}
}
phenoMating = m.PhenotypeQ;
matingtype = m.ObjectiveQ;
hierarchicalMating = m.HierarchicalQ;
if (matingtype) breed = m.BreedParameter;
if (phenoMating)
{
adultPhenoXX = new double[m.NumberOfPhenoAlleleFemale];
adultPhenoXY = new double[m.NumberOfPhenoAlleleMale];
GammaPheno = new double[m.NumberOfPhenoAlleleFemale, m.NumberOfPhenoAlleleMale];
mapFromGenoToPhenoXX = m.MapFromGenoToPhenoFemale;
mapFromGenoToPhenoXY = m.MapFromGenoToPhenoMale;
}
mutationXX = muta.MutationFemale;
mutationXY = muta.MutationMale;
reproductioncoefficientXX = r.CoefficientXX;
reproductioncoefficientXY = r.CoefficientXY;
disadvantagefactorXX = s.DisadvantageXX;
disadvantagefactorXY = s.DisadvantageXY;
InitialRun();
Normalization();
}
private void InitialRun()
{
if(hierarchicalMating)
{
Random ran = new Random();
for(int i = 0; i < adultXX.Length; i++)
{
adultXX[i] = (double) ran.Next(0,100);
adultXY[i] = adultXX[i]+0.01;
}
}
else
{
Random ran = new Random();
for(int i = 0; i < adultXX.Length; i++) adultXX[i] = (double) ran.Next(0,100);
for(int i = 0; i < adultXY.Length; i++) adultXY[i] = (double) ran.Next(0,100);
}
}
private void Normalization()
{
double sum = 0.0;
for(int i = 0; i < adultXX.Length; i++) sum += adultXX[i];
for(int i = 0; i < adultXX.Length; i++) adultXX[i] /= sum;
sum = 0.0;
for(int i = 0; i < adultXY.Length; i++) sum += adultXY[i];
for(int i = 0; i < adultXY.Length; i++) adultXY[i] /= sum;
}
private double[] initialPopulationXX, initialPopulationXY;
public double[] InitialAdultMalePopulation
{
set{initialPopulationXY = value;}
}
public double[] InitialAdultFemalePopulation
{
set{initialPopulationXX = value;}
}
public void SetInitialPopulation()
{
for(int i = 0; i < adultXX.Length; i++) adultXX[i] = initialPopulationXX[i];
for(int i = 0; i < adultXY.Length; i++) adultXY[i] = initialPopulationXY[i];
}
private int howManyTimes;
public int HowManyTimes
{
set{howManyTimes = value;}
}
public void Compute() // after set
{
for (int i = 0; i < howManyTimes; i++)
{
Normalization();
MatingStep();
MutationStep();
ReproductionStep();
SelectionStep();
}
}
private void MatingStep()
{
if(!matingtype & !hierarchicalMating) // random
{
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++) parents[i,j] = adultXX[i]*adultXY[j];
}
else // non-random
{
if(!phenoMating) // genotype
{
if(!hierarchicalMating) // breedfunctiontype
{
LinearOptimization(breed,adultXX,adultXY,Gamma); // Find Gamma[,]
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++) parents[i,j] = adultXX[i]*Gamma[i,j]*adultXY[j];
}
else // hierarchicaltype
{
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++) parents[i,j] = 0.0;
parents[0,0] = adultXX[0];
for(int i = 0; i < adultXX.Length - 1; i++)
{
parents[i+1,i] = adultXY[i] - parents[i,i];
parents[i+1,i+1] = adultXX[i+1] - parents[i+1,i];
}
}
}
else // phenotype
{
for(int i = 0; i < adultPhenoXX.Length; i++)
{
adultPhenoXX[i] = 0.0;
}
for(int i = 0; i < adultXX.Length; i++)
{
adultPhenoXX[mapFromGenoToPhenoXX[i]] += adultXX[i];
}
for(int i = 0; i < adultPhenoXY.Length; i++)
{
adultPhenoXY[i] = 0.0;
}
for(int i = 0; i < adultXY.Length; i++)
{
adultPhenoXY[mapFromGenoToPhenoXY[i]] += adultXY[i];
}
if(!hierarchicalMating) // breedfunctiontype
{
LinearOptimization(breed,adultPhenoXX,adultPhenoXY,GammaPheno);
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++)
{
Gamma[i,j]=GammaPheno[mapFromGenoToPhenoXX[i],mapFromGenoToPhenoXY[j]];
parents[i,j] = adultXX[i]*Gamma[i,j]*adultXY[j];
}
}
else // hierarchicaltype
{
for(int i = 0; i < adultPhenoXX.Length; i++)
for(int j = 0; j < adultPhenoXY.Length; j++) GammaPheno[i,j] = 0.0;
GammaPheno[0,0] = 1.0/adultPhenoXY[0];
for(int i = 0; i < adultPhenoXX.Length - 1; i++)
{
GammaPheno[i+1,i] = (1.0 - adultPhenoXX[i]*GammaPheno[i,i])/adultPhenoXX[i+1];
GammaPheno[i+1,i+1] = (1.0 - GammaPheno[i+1,i]*adultPhenoXY[i])/adultPhenoXY[i+1];
}
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++)
{
Gamma[i,j]=GammaPheno[mapFromGenoToPhenoXX[i],mapFromGenoToPhenoXY[j]];
parents[i,j] = adultXX[i]*Gamma[i,j]*adultXY[j];
}
}
}
}
}
private void LinearOptimization(double[,] bp, double[] pf, double[] pm, double[,] mf)
{
double[,] a;
int[] izrov, iposv;
if(adultXX.Length == adultXY.Length) // auto chromosome
{
a = new Double[2+pf.Length+pf.Length*(pf.Length-1)/2,1+pf.Length*pm.Length];
izrov = new Int32[pf.Length*pm.Length];
iposv = new Int32[pf.Length+pf.Length*(pf.Length-1)/2];
int kk = 0;
for(int i = 0; i < pf.Length ; i++)
{
for(int j = 0; j < pm.Length ; j++)
{
a[0,1+kk] = bp[i,j]*pf[i]*pm[j];
kk++;
}
}
for(int i = 0; i < pf.Length; i++)
{
a[1+i,0] = 1.0;
for(int j = 0; j < pm.Length ; j++) a[1+i,1+pm.Length*i+j] = -pm[j];
}
int k = 0;
for(int i = 0; i < pf.Length ; i++)
{
for(int j = 0; j < i ; j++)
{
a[1+pf.Length+k,1+pm.Length*i+j] = -1.0;
a[1+pf.Length+k,1+pm.Length*j+i] = 1.0;
k++;
}
}
simplx(a,pf.Length+pf.Length*(pf.Length-1)/2,pf.Length*pm.Length,0,0,pf.Length+pf.Length*(pf.Length-1)/2,izrov,iposv);
for(int i = 0; i < pf.Length ; i++)
{
for(int j = 0; j < pm.Length ; j++)
{
mf[i,j] = 0.0;
}
}
for(int i = 0; i < iposv.Length; i++)
{
int v = iposv[i];
int jj, ii;
if(v <= pf.Length*pm.Length)
{
jj = (v-1) % pm.Length;
ii = (v-1-jj)/pm.Length;
mf[ii,jj] = a[1+i,0];
}
}
}
else // sex-linked
{
a = new Double[2+pf.Length+pm.Length,1+pf.Length*pm.Length];
izrov = new int[pf.Length*pm.Length];
iposv = new int[pf.Length+pm.Length];
int kk = 0;
for(int i = 0; i < pf.Length ; i++)
{
for(int j = 0; j < pm.Length ; j++)
{
a[0,1+kk] = bp[i,j]*pf[i]*pm[j];
kk++;
}
}
for(int i = 0; i < pf.Length; i++)
{
a[1+i,0] = 1.0;
for(int j = 0; j < pm.Length; j++)
a[1+i,1+pm.Length*i+j] = -pm[j];
}
for(int i = 0; i < pm.Length; i++)
{
a[1+pf.Length+i,0] = 1.0;
for(int j = 0; j < pf.Length; j++)
a[1+pf.Length+i,1+i+pm.Length*j] = -pf[j];
}
simplx(a,pf.Length+pm.Length,pf.Length*pm.Length,0,0,pf.Length+pm.Length,izrov,iposv);
for(int i = 0; i < pf.Length ; i++)
{
for(int j = 0; j < pm.Length ; j++)
{
mf[i,j] = 0.0;
}
}
for(int i = 0; i < iposv.Length; i++)
{
int k = iposv[i];
if(k <= pf.Length*pm.Length)
{
int jj = (k-1) % pm.Length;
int ii = ((k-1) - ((k-1) % pm.Length))/pm.Length;
mf[ii,jj] = a[1+i,0];
}
}
}
}
private void MutationStep()
{
double sum;
for(int i = 0; i < adultXX.Length; i++)
for(int j = 0; j < adultXY.Length; j++)
{
sum = 0.0;
for(int k = 0; k < adultXX.Length; k++)
for(int l = 0; l < adultXY.Length; l++)
sum += parents[k,l]*mutationXX[k,i]*mutationXY[l,j];
effectiveparents[i,j] = sum;
}
}
private void ReproductionStep()
{
double sum;
for(int i = 0; i < adultXX.Length; i++)
{
sum = 0.0;
for(int j = 0; j < adultXX.Length; j++)
for(int k = 0; k < adultXY.Length; k++)
sum += effectiveparents[j,k]*reproductioncoefficientXX[j,k,i];
birthXX[i] = sum;
}
for(int i = 0; i < adultXY.Length; i++)
{
sum = 0.0;
for(int j = 0; j < adultXX.Length; j++)
for(int k = 0; k < adultXY.Length; k++)
sum += effectiveparents[j,k]*reproductioncoefficientXY[j,k,i];
birthXY[i] = sum;
}
}
private void SelectionStep()
{
double sum = 0.0;
for(int k = 0; k < adultXX.Length; k++)
sum += birthXX[k]*disadvantagefactorXX[k];
for(int i = 0; i < adultXX.Length; i++)
adultXX[i] = birthXX[i]*(1.0 - disadvantagefactorXX[i])/(1.0 - sum);
sum = 0.0;
for(int k = 0; k < adultXY.Length; k++)
sum += birthXY[k]*disadvantagefactorXY[k];
for(int i = 0; i < adultXY.Length; i++)
adultXY[i] = birthXY[i]*(1.0 - disadvantagefactorXY[i])/(1.0 - sum);
}
public string InfantMortality()
{
string result;
double sum = 0.0;
for(int k = 0; k < adultXX.Length; k++)
if(disadvantagefactorXX[k] > 0.5) sum += birthXX[k];
result = "Female\r\n";
result += "Normal vs Defect = "+Convert.ToString(1.0 - sum)+" : "+Convert.ToString(sum)+"\r\n";
sum = 0.0;
for(int k = 0; k < adultXY.Length; k++)
if(disadvantagefactorXY[k] > 0.5) sum += birthXY[k];
result += "Male\r\n";
result += "Normal vs Defect = "+Convert.ToString(1.0 - sum)+" : "+Convert.ToString(sum)+"\r\n";
return result;
}
// numerical recipes source code
private double EPS = 1.0e-6;
private int icase;
public int SimplexMethodResult
{
get{return icase;}
}
private int kp = 0;
private double bmax = 0.0;
private int ip = 0;
private void simplx(double[,] a, int m, int n, int m1, int m2, int m3,
int[] izrov, int[] iposv)
{
int i,iis,k,kh,nl1;
int[] l1 = new Int32[n+1];
int[] l3 = new Int32[m];
double q1;
if (m != (m1 + m2 + m3)) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("Bad input constraint counts in simplx");
}
nl1=n;
for (k=1;k<=n;k++) l1[k-1]=izrov[k-1]=k;
for (i=1;i<=m;i++)
{
if (a[i, 0] < 0.0) try { throw new Science.Error(); }
catch (Science.Error e)
{
e.Write("Bad input tableau in simplx");
}
iposv[i-1]=n+i;
}
if ((m2+m3) != 0)
{
for (i=1;i<=m2;i++) l3[i-1]=1;
for (k=1;k<=(n+1);k++)
{
q1=0.0;
for (i=m1+1;i<=m;i++) q1 += a[i,k-1];
a[m+1,k-1] = -q1;
}
for (;;)
{
simp1(a,m+1,l1,nl1,0);
if (bmax <= EPS && a[m+1,0] < -EPS)
{
icase = -1;
return;
}
else if (bmax <= EPS && a[m+1,0] <= EPS)
{
for (ip=m1+m2+1;ip<=m;ip++)
{
if (iposv[ip-1] == (ip+n))
{
simp1(a,ip,l1,nl1,1);
if (bmax > EPS)
goto one;
}
}
for (i=m1+1;i<=m1+m2;i++)
if (l3[i-m1-1] == 1)
for (k=1;k<=n+1;k++)
a[i,k-1] = -a[i,k-1];
break;
}
simp2(a,m,n,kp);
if (ip == 0)
{
icase = -1;
return;
}
one: simp3(a,m+1,n,ip,kp);
if (iposv[ip-1] >= (n+m1+m2+1))
{
for (k=1;k<=nl1;k++)
if (l1[k-1] == kp) break;
--nl1;
for (iis=k;iis<=nl1;iis++) l1[iis-1]=l1[iis+1-1];
}
else
{
kh=iposv[ip-1]-m1-n;
if ((kh >= 1) && (l3[kh-1] != 0))
{
l3[kh-1]=0;
++a[m+1,kp];
for (i=1;i<=m+2;i++)
a[i-1,kp] = -a[i-1,kp];
}
}
iis=izrov[kp-1];
izrov[kp-1]=iposv[ip-1];
iposv[ip-1]=iis;
}
}
for (;;)
{
simp1(a,0,l1,nl1,0);
if (bmax <= EPS)
{
icase=0;
return;
}
simp2(a,m,n,kp);
if (ip == 0)
{
icase=1;
return;
}
simp3(a,m,n,ip,kp);
iis=izrov[kp-1];
izrov[kp-1]=iposv[ip-1];
iposv[ip-1]=iis;
}
}
private void simp1(double[,] a, int mm, int[] ll, int nll, int iabf)
{
int k;
double test;
if (nll <= 0)
bmax=0.0;
else
{
kp=ll[0];
bmax=a[mm,kp];
for (k=1;k 0.0)
{
bmax=a[mm,ll[k]];
kp=ll[k];
}
}
}
}
private void simp2(double[,] a, int m, int n, int kp)
{
int k,i;
double qp=0.0,q0=0.0,q,q1;
ip=0;
for (i=1;i<=m;i++)
if (a[i,kp] < -EPS) break;
if (i>m) return;
q1 = -a[i,0]/a[i,kp];
ip=i;
for (i=ip+1;i<=m;i++)
{
if (a[i,kp] < -EPS)
{
q = -a[i,0]/a[i,kp];
if (q < q1)
{
ip=i;
q1=q;
}
else if (q == q1)
{
for (k=1;k<=n;k++)
{
qp = -a[ip,k]/a[ip,kp];
q0 = -a[i,k]/a[i,kp];
if (q0 != qp) break;
}
if (q0 < qp) ip=i;
}
}
}
}
private void simp3(double[,] a, int i1, int k1, int ip, int kp)
{
int kk,ii;
double piv;
piv=1.0/a[ip,kp];
for (ii=1;ii<=i1+1;ii++)
if (ii-1 != ip)
{
a[ii-1,kp] *= piv;
for (kk=1;kk<=k1+1;kk++)
if (kk-1 != kp)
a[ii-1,kk-1] -= a[ip,kk-1]*a[ii-1,kp];
}
for (kk=1;kk<=k1+1;kk++)
if (kk-1 != kp) a[ip,kk-1] *= -piv;
a[ip,kp]=piv;
}
}
}